diff options
Diffstat (limited to 'sources')
-rw-r--r-- | sources/scalac/ast/parser/Parser.java | 62 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 21 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 182 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/UnPickle.java | 28 | ||||
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 14 | ||||
-rw-r--r-- | sources/scalac/typechecker/Infer.java | 18 | ||||
-rw-r--r-- | sources/scalac/typechecker/RefCheck.java | 55 |
7 files changed, 283 insertions, 97 deletions
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java index 12eb76dd2c..cbceab76f4 100644 --- a/sources/scalac/ast/parser/Parser.java +++ b/sources/scalac/ast/parser/Parser.java @@ -1121,11 +1121,11 @@ public class Parser implements Tokens { return enums.toArray(); } - /** Generator ::= val Pattern `<-' Expr + /** Generator ::= val Pattern1 `<-' Expr */ Tree generator() { int pos = accept(VAL); - Tree pat = validPattern(); + Tree pat = validPattern1(); accept(LARROW); Tree rhs = expr(); if (!TreeInfo.isVarPattern(pat)) @@ -1162,6 +1162,22 @@ public class Parser implements Tokens { return make.Bad(pos); } + /** Pattern1 ( see pattern1() ) which is checked for validity + */ + Tree validPattern1() { + int pos = s.pos; + + Tree pat = pattern1(); + + if( this.pN.check( pat ) ) { // reports syntax errors as side effect + // normalize + Tree res = pN.wrapAlternative( pN.elimSequence( pN.flattenSequence ( pat ))); + return res; + } + //syntaxError( pos, "invalid pattern", false ); + return make.Bad(pos); + } + /** Patterns ::= Pattern {`,' Pattern} */ Tree[] patterns() { @@ -1174,18 +1190,17 @@ public class Parser implements Tokens { return ts.toArray(); } - /** Pattern ::= TreePattern { `|' TreePattern } + /** Pattern ::= Pattern1 { `|' Pattern1 } */ - Tree pattern() { int pos = s.pos; - Tree first = treePattern(); + Tree first = pattern1(); if(( s.token == IDENTIFIER )&&( s.name == BAR )) { TreeList choices = new TreeList(); choices.append( first ); while(( s.token == IDENTIFIER )&&( s.name == BAR )) { s.nextToken(); - choices.append( treePattern() ); + choices.append( pattern1() ); } TreeList ts = pN.flattenAlternativeChildren( choices.toArray() ); return pN.flattenAlternative( make.Alternative( pos, ts.toArray() ) ); @@ -1193,12 +1208,11 @@ public class Parser implements Tokens { return first; } - /** TreePattern ::= varid `:' Type1 - * | `_' `:' Type1 - * | SimplePattern [ '*' | '?' | '+' ] - * | SimplePattern {Id SimplePattern} // op2 must not be empty + /** Pattern1 ::= varid `:' Type1 + * | `_' `:' Type1 + * | Pattern2 */ - Tree treePattern() { + Tree pattern1() { int base = sp; Tree top = simplePattern(); if (s.token == COLON) { @@ -1206,6 +1220,17 @@ public class Parser implements Tokens { return make.Typed(s.skipToken(), top, type1()); } } + return pattern1rest(base, top); + } + + /* Pattern2 ::= SimplePattern [ '*' | '?' | '+' ] + * | SimplePattern {Id SimplePattern} // op2 must not be empty + */ + Tree pattern2() { + return pattern1rest(sp, simplePattern()); + } + + Tree pattern1rest(int base, Tree top) { if (s.token == IDENTIFIER) { if (s.name == STAR) { /* p* becomes z@( |(p,z)) */ s.nextToken(); @@ -1683,22 +1708,13 @@ public class Parser implements Tokens { } } - /** PatDef ::= Pattern `=' Expr + /** PatDef ::= Pattern2 [`:' Type] `=' Expr * ValDcl ::= Id `:' Type */ Tree patDefOrDcl(int mods) { int pos = s.pos; - Tree pat = validPattern(); - Tree tp; - switch (pat) { - case Typed(Tree pat1, Tree tp1): - pat = pat1; - tp = tp1; - break; - default: - if (s.token == COLON) tp = typedOpt(); - else tp = Tree.Empty; - } + Tree pat = pattern2(); + Tree tp = (s.token == COLON) ? typedOpt() : Tree.Empty; switch (pat) { case Ident(Name name): if (tp == Tree.Empty || s.token == EQUALS) diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 364324a3cb..200e9acecf 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -1130,16 +1130,15 @@ public abstract class Symbol implements Modifiers, Kinds { if (sym1.kind == Kinds.NONE || (sym1.flags & STATIC) != 0) { return Symbol.NONE; } else { - //System.out.println(this + ":" + this.type() + locationString() + " overrides? " + sym1 + sym1.type() + sym1.locationString()); //DEBUG - //System.out.println(owner.thisType());//DEBUG + //System.out.println(this + ":" + this.type() + locationString() + " overrides? " + sym1 + ":" + owner.thisType().memberType(sym1) + sym1.locationString()); //DEBUG - Type symtype = this.type();//owner.thisType().memberType(this); - //todo: try whether we can do: this.type(); instead - Type sym1type = owner.thisType().memberType(sym1); + Type symtype = this.type().derefDef(); + Type sym1type = owner.thisType().memberType(sym1).derefDef(); switch (sym1type) { case OverloadedType(Symbol[] alts, Type[] alttypes): for (int i = 0; i < alts.length; i++) { - if (symtype.isSubType(alttypes[i])) return alts[i]; + if (symtype.isSubType(alttypes[i].derefDef())) + return alts[i]; } return Symbol.NONE; default: @@ -1164,12 +1163,12 @@ public abstract class Symbol implements Modifiers, Kinds { //System.out.println(this + ":" + this.type() + locationString() + " overrides? " + sym1 + sym1.type() + sym1.locationString()); //DEBUG //System.out.println(owner.thisType());//DEBUG - Type symtype = sub.memberType(this); - Type sym1type = sub.memberType(sym1); + Type symtype = sub.memberType(this).derefDef(); + Type sym1type = sub.memberType(sym1).derefDef(); switch (sym1type) { case OverloadedType(Symbol[] alts, Type[] alttypes): for (int i = 0; i < alts.length; i++) { - if (alttypes[i].isSubType(symtype)) return alts[i]; + if (alttypes[i].derefDef().isSubType(symtype)) return alts[i]; } return Symbol.NONE; default: @@ -1188,8 +1187,8 @@ public abstract class Symbol implements Modifiers, Kinds { return ((this.flags | that.flags) & (PRIVATE | STATIC)) == 0 && this.name == that.name && - owner.thisType().memberType(this).isSubType( - owner.thisType().memberType(that)); + owner.thisType().memberType(this).derefDef().isSubType( + owner.thisType().memberType(that).derefDef()); } /** Reset symbol to initial state diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 2b05469f58..acdf8e1d13 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -316,6 +316,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } } + /** If this type is a parameterless method, its underlying resulttype; + * otherwise the type itself + */ + public Type derefDef() { + switch (this) { + case PolyType(Symbol[] tparams, Type restp): + if (tparams.length == 0) return restp; + } + return this; + } + /** The lower approximation of this type (which must be a typeref) */ public Type loBound() { @@ -706,6 +717,32 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } } +// Set Owner ------------------------------------------------------------------ + + public Type setOwner(Symbol owner) { + switch (this) { + case PolyType(Symbol[] tparams, Type restpe): + Type restpe1 = restpe.setOwner(owner); + if (restpe1 == restpe) return this; + else return Type.PolyType(tparams, restpe1); + case MethodType(Symbol[] params, Type restpe): + Symbol[] params1 = params; + if (params.length > 0 && + params[0].owner() != owner && params[0].owner() != Symbol.NONE) { + params1 = new Symbol[params.length]; + for (int i = 0; i < params.length; i++) + params1[i] = params[i].cloneSymbol(); + } + for (int i = 0; i < params.length; i++) + params1[i].setOwner(owner); + Type restpe1 = restpe.setOwner(owner); + if (params1 == params && restpe1 == restpe) return this; + else return Type.MethodType(params1, restpe1); + default: + return this; + } + } + // Maps -------------------------------------------------------------------------- /** The type of type-to-type functions. @@ -1555,8 +1592,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { Symbol p1 = ps1[i]; Symbol p = ps[i]; if (!p1.type().isSameAs(p.type()) || - (p1.flags & (Modifiers.DEF | Modifiers.REPEATED)) != - (p.flags & (Modifiers.DEF | Modifiers.REPEATED))) + (p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED))) return false; } return res.isSubType(res1); @@ -1828,8 +1864,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { Symbol p1 = ps1[i]; Symbol p = ps[i]; if (!p1.type().isSameAs(p.type()) || - (p1.flags & (Modifiers.DEF | Modifiers.REPEATED)) != - (p.flags & (Modifiers.DEF | Modifiers.REPEATED))) + (p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED))) return false; } return res.isSameAs(res1); @@ -2147,9 +2182,14 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { int nredundant = 0; boolean[] redundant = new boolean[tps.length]; for (int i = 0; i < tps.length; i++) { - if (tps[i] == ErrorType) { + switch (tps[i]) { + case ErrorType: return new Type[]{ErrorType}; - } else { + case MethodType(_, _): + case PolyType(_, _): + case OverloadedType(_, _): + return new Type[]{NoType}; + default: assert tps[i].isObjectType(): tps[i]; for (int j = 0; j < i && !redundant[i]; j++) { if (!redundant[j]) { @@ -2186,6 +2226,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { //If all types are method types with same parameters, //compute lub of their result types. + switch (tps[0]) { + case PolyType(Symbol[] tparams, _): + return polyLub(tps, tparams); + case MethodType(Symbol[] vparams, _): + return methodLub(tps, vparams); + } // remove types that are subtypes of some other type. tps = elimRedundant(tps, true); @@ -2250,6 +2296,66 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return sym.kind == CLASS ? base.memberType(sym) : base.memberInfo(sym); } + private static Type polyLub(Type[] tps, Symbol[] tparams0) { + Type[][] hiboundss = new Type[tparams0.length][tps.length]; + Type[][] loboundss = new Type[tparams0.length][tps.length]; + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case PolyType(Symbol[] tparams, Type restp): + if (tparams.length == tparams0.length) { + for (int j = 0; j < tparams0.length; j++) { + hiboundss[j][i] = tparams[j].info() + .subst(tparams, tparams0); + loboundss[j][i] = tparams[j].loBound() + .subst(tparams, tparams0); + } + restps[i] = restp.subst(tparams, tparams0); + } else { + return Type.NoType; + } + break; + default: + return Type.NoType; + } + } + Type[] hibounds = new Type[tparams0.length]; + Type[] lobounds = new Type[tparams0.length]; + for (int j = 0; j < tparams0.length; j++) { + hibounds[j] = glb(hiboundss[j]); + lobounds[j] = lub(loboundss[j]); + } + Symbol[] tparams = new Symbol[tparams0.length]; + for (int j = 0; j < tparams.length; j++) { + tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE) + .setInfo(hibounds[j].subst(tparams0, tparams)) + .setLoBound(lobounds[j].subst(tparams0, tparams)); + } + return Type.PolyType(tparams, lub(restps).subst(tparams0, tparams)); + } + + private static Type methodLub(Type[] tps, Symbol[] vparams0) { + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case MethodType(Symbol[] vparams, Type restp): + if (vparams.length != vparams0.length) + return Type.NoType; + for (int j = 0; j < vparams.length; j++) + if (!vparams[i].type().isSameAs(vparams0[i].type()) || + (vparams[i].flags & (DEF | REPEATED)) != + (vparams0[i].flags & (DEF | REPEATED))) + return Type.NoType; + restps[i] = restp; + } + } + Symbol[] vparams = new Symbol[vparams0.length]; + for (int j = 0; j < vparams.length; j++) { + vparams[j] = vparams0[j].cloneSymbol(Symbol.NONE); + } + return Type.MethodType(vparams, lub(restps)); + } + private static Symbol lub(Symbol[] syms, Type[] tps, Type[] lbs, Symbol owner) { //System.out.println("lub" + ArrayApply.toString(syms));//DEBUG int lubKind = syms[0].kind; @@ -2276,7 +2382,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { default: throw new ApplicationError(); } - lubSym.setInfo(lubType); + lubSym.setInfo(lubType.setOwner(lubSym)); return lubSym; } @@ -2426,7 +2532,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { e.sym.setInfo(syminfo); } else if (sym.kind == VAL && e.sym.kind == VAL || sym.kind == TYPE && e.sym.kind == TYPE) { - e.sym.setInfo(glb(new Type[]{einfo, syminfo})); + e.sym.setInfo(glb(new Type[]{einfo, syminfo}).setOwner(e.sym)); } else { return false; } @@ -2444,6 +2550,66 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return true; } + private static Type polyGlb(Type[] tps, Symbol[] tparams0) { + Type[][] hiboundss = new Type[tparams0.length][tps.length]; + Type[][] loboundss = new Type[tparams0.length][tps.length]; + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case PolyType(Symbol[] tparams, Type restp): + if (tparams.length == tparams0.length) { + for (int j = 0; j < tparams0.length; j++) { + hiboundss[j][i] = tparams[j].info() + .subst(tparams, tparams0); + loboundss[j][i] = tparams[j].loBound() + .subst(tparams, tparams0); + } + restps[i] = restp.subst(tparams, tparams0); + } else { + return Type.NoType; + } + break; + default: + return Type.NoType; + } + } + Type[] hibounds = new Type[tparams0.length]; + Type[] lobounds = new Type[tparams0.length]; + for (int j = 0; j < tparams0.length; j++) { + hibounds[j] = lub(hiboundss[j]); + lobounds[j] = glb(loboundss[j]); + } + Symbol[] tparams = new Symbol[tparams0.length]; + for (int j = 0; j < tparams.length; j++) { + tparams[j] = tparams0[j].cloneSymbol(Symbol.NONE) + .setInfo(hibounds[j].subst(tparams0, tparams)) + .setLoBound(lobounds[j].subst(tparams0, tparams)); + } + return Type.PolyType(tparams, glb(restps).subst(tparams0, tparams)); + } + + private static Type methodGlb(Type[] tps, Symbol[] vparams0) { + Type[] restps = new Type[tps.length]; + for (int i = 0; i < tps.length; i++) { + switch (tps[i]) { + case MethodType(Symbol[] vparams, Type restp): + if (vparams.length != vparams0.length) + return Type.NoType; + for (int j = 0; j < vparams.length; j++) + if (!vparams[i].type().isSameAs(vparams0[i].type()) || + (vparams[i].flags & (DEF | REPEATED)) != + (vparams0[i].flags & (DEF | REPEATED))) + return Type.NoType; + restps[i] = restp; + } + } + Symbol[] vparams = new Symbol[vparams0.length]; + for (int j = 0; j < vparams.length; j++) { + vparams[j] = vparams0[j].cloneSymbol(Symbol.NONE); + } + return Type.MethodType(vparams, glb(restps)); + } + // Erasure -------------------------------------------------------------------------- public static Map erasureMap = new MapOnlyTypes() { diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index ed3dd1bac8..e76b9f03cb 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -77,30 +77,6 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { } } - Type setOwner(Type tp, Symbol owner) { - switch (tp) { - case PolyType(Symbol[] tparams, Type restpe): - Type restpe1 = setOwner(restpe, owner); - if (restpe1 == restpe) return tp; - else return Type.PolyType(tparams, restpe1); - case MethodType(Symbol[] params, Type restpe): - Symbol[] params1 = params; - if (params.length > 0 && - params[0].owner() != owner && params[0].owner() != Symbol.NONE) { - params1 = new Symbol[params.length]; - for (int i = 0; i < params.length; i++) - params1[i] = params[i].cloneSymbol(); - } - for (int i = 0; i < params.length; i++) - params1[i].setOwner(owner); - Type restpe1 = setOwner(restpe, owner); - if (params1 == params && restpe1 == restpe) return tp; - else return Type.MethodType(params1, restpe1); - default: - return tp; - } - } - int readByte() { return bytes[bp++]; } @@ -288,7 +264,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { entries[n] = sym = moduleroot; } Type tp = getType(inforef); - sym.setFirstInfo(setOwner(tp, sym)); + sym.setFirstInfo(tp.setOwner(sym)); break; default: @@ -387,7 +363,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { : alts.length + "!=" + alttypes.length + " at " + bp0 + "/" + bp1 + "/" + bp; for (int i = 0; i < alts.length; i++) - alttypes[i] = setOwner(alttypes[i], alts[i]); + alttypes[i] = alttypes[i].setOwner(alts[i]); tpe = Type.OverloadedType(alts, alttypes); break; case FLAGGEDtpe: diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 063108a9d0..05657ba759 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -319,20 +319,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { sym.flags &= ~DEFERRED; } } - if ((sym.flags & OVERRIDE) != 0) { - int i = -1; - if (sym.owner().kind == CLASS) { - Type[] parents = sym.owner().info().parents(); - i = parents.length - 1; - while (i >= 0 && - parents[i].lookupNonPrivate(sym.name).kind == NONE) - i--; - } - if (i < 0) { - error(sym.pos, sym + " overrides nothing"); - sym.flags &= ~OVERRIDE; - } - } checkNoConflict(sym, DEFERRED, PRIVATE); checkNoConflict(sym, FINAL, SEALED); checkNoConflict(sym, FINAL, PRIVATE); diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java index 5dcf9bf0db..05d8916d66 100644 --- a/sources/scalac/typechecker/Infer.java +++ b/sources/scalac/typechecker/Infer.java @@ -123,6 +123,24 @@ public class Infer implements Modifiers, Kinds { } } return tree; + + case TypeApply(Tree fun, Tree[] targs): + boolean proceed = true; + switch (fun.type) { + case PolyType(Symbol[] tparams1, _): + if (tparams1.length == tparams.length && + tparams1[0] == tparams[0] && + targs.length == tparams.length) { + proceed = false; + for (int i = 0; i < tparams.length; i++) + if (!typeSubstituter.matches(targs[i].type.symbol(), tparams[i])) + proceed = true; + } + } + Tree fun1 = proceed ? transform(fun) : fun; + Tree[] targs1 = transform(targs); + return copy.TypeApply(tree, fun1, targs1); + /* case TypeTerm(): Symbol sym = tree.type.symbol(); diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index da3bef4476..9c493db761 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -71,6 +71,22 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { checkOverride(pos, clazz, it.next(), overrides); } } + + Type[] parents = clazz.info().parents(); + for (Scope.SymbolIterator it = clazz.members().iterator(true); + it.hasNext();) { + Symbol sym = it.next(); + if ((sym.flags & OVERRIDE) != 0) { + int i = parents.length - 1; + while (i >= 0 && sym.overriddenSymbol(parents[i]).kind == NONE) + i--; + if (i < 0) { + unit.error(sym.pos, sym + " overrides nothing"); + sym.flags &= ~OVERRIDE; + } + } + } + for (Iterator/*<Symbol>*/ it = overrides.keySet().iterator(); it.hasNext();) { Symbol member = (Symbol) it.next(); @@ -89,12 +105,13 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { if ((other.flags & PRIVATE) == 0) { Symbol member1 = clazz.info().lookup(other.name); if (member1.kind != NONE && member1.owner() != other.owner()) { + Type self = clazz.thisType(); + Type otherinfo = normalizedInfo(self, other); + Type template = resultToAny(otherinfo); switch (member1.info()) { case OverloadedType(Symbol[] alts, _): - Type self = clazz.thisType(); - Type otherinfo = normalizedInfo(self, other); for (int i = 0; i < alts.length; i++) { - if (normalizedInfo(self, alts[i]).isSubType(otherinfo)) { + if (normalizedInfo(self, alts[i]).isSubType(template)) { if (member == other) member = alts[i]; else @@ -109,12 +126,14 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } break; default: - member = member1; + if (normalizedInfo(self, member1).isSubType(template)) { + member = member1; + } } } - } - if (member != other) { - checkOverride(pos, clazz, member, other); + if (member != other) { + checkOverride(pos, clazz, member, other); + } } if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) { if ((member.flags & DEFERRED) != 0) { @@ -123,13 +142,24 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { member + member.locationString() + " is not defined" + (((member.flags & MUTABLE) == 0) ? "" : "\n(Note that variables need to be initialized to be defined)")); - } else if ((member.flags & OVERRIDE) != 0 && + } else if (member != other && + (member.flags & OVERRIDE) != 0 && ((other.flags & DEFERRED) == 0 || overrides.get(member) == null)) overrides.put(member, other); } } //where + private Type resultToAny(Type tp) { + switch (tp) { + case PolyType(Symbol[] tparams, Type restp): + return Type.PolyType(tparams, resultToAny(restp)); + case MethodType(Symbol[] tparams, Type restp): + return Type.MethodType(tparams, Type.AnyType); + default: + return defs.ANY_TYPE; + } + } private void abstractClassError(Symbol clazz, String msg) { if (clazz.isAnonymousClass()) unit.error(clazz.pos, "object creation impossible, since " + msg); @@ -227,12 +257,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } Type normalizedInfo(Type site, Symbol sym) { - Type tp = site.memberInfo(sym); - switch (tp) { - case PolyType(Symbol[] tparams, Type restp): - if (tparams.length == 0) return restp; - } - return tp; + return site.memberInfo(sym).derefDef(); } String infoString(Symbol sym, Type symtype, boolean lobound) { @@ -946,7 +971,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { //System.out.println("name: "+name); Scope.Entry e = scopes[level].lookupEntry(name); //System.out.println("sym: "+sym); - if (sym.isLocal() && sym == e.sym) { + if (sym != null && sym.isLocal() && sym == e.sym) { int i = level; while (scopes[i] != e.owner) i--; int symindex = ((Integer) symIndex.get(tree.symbol())).intValue(); |