diff options
author | Martin Odersky <odersky@gmail.com> | 2003-09-02 12:57:45 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2003-09-02 12:57:45 +0000 |
commit | ec46a90f5cd17d5ed506201bdc0b0a55324dffae (patch) | |
tree | db322d9b07f1a8ae3417d757a22549039293e9fc /sources/scalac/typechecker | |
parent | 3228df8eafa7a70792615356042b427595999b26 (diff) | |
download | scala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.tar.gz scala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.tar.bz2 scala-ec46a90f5cd17d5ed506201bdc0b0a55324dffae.zip |
*** empty log message ***
Diffstat (limited to 'sources/scalac/typechecker')
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 79 | ||||
-rw-r--r-- | sources/scalac/typechecker/RefCheck.java | 71 |
2 files changed, 108 insertions, 42 deletions
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 6d54de146c..55b6324880 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -212,20 +212,44 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { /** Check that `sym' is accessible as a member of tree `site' in current context. */ - void checkAccessible(int pos, Symbol sym, Tree site) { - if (!isAccessible(sym, site)) { - error(pos, sym + " cannot be accessed in " + site.type); - } - if (site instanceof Tree.Super && (sym.flags & DEFERRED) != 0) { - Symbol sym1 = context.enclClass.owner.thisSym().info().lookup(sym.name); - if ((sym1.flags & OVERRIDE) == 0 || (sym1.flags & DEFERRED) != 0) - error(pos, "symbol accessed from super may not be abstract"); + Type checkAccessible(int pos, Symbol sym, Type symtype, Tree site) { + switch (symtype) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + int nacc = 0; + for (int i = 0; i < alts.length; i++) { + if (isAccessible(alts[i], site)) { + nacc++; + } + } + if (nacc == 0) { + error(pos, sym + " cannot be accessed in " + site.type.widen()); + return Type.ErrorType; + } else { + Symbol[] alts1 = new Symbol[nacc]; + Type[] alttypes1 = new Type[nacc]; + nacc = 0; + for (int i = 0; i < alts.length; i++) { + if (isAccessible(alts[i], site)) { + alts1[nacc] = alts[i]; + alttypes1[nacc] = alttypes[i]; + nacc++; + } + } + return Type.OverloadedType(alts1, alttypes1); + } + default: + if (isAccessible(sym, site)) { + return symtype; + } else { + error(pos, sym + " cannot be accessed in " + site.type.widen()); + return Type.ErrorType; + } } } /** Is `sym' accessible as a member of tree `site' in current context? */ - boolean isAccessible(Symbol sym, Tree site) { + private boolean isAccessible(Symbol sym, Tree site) { return (sym.flags & (PRIVATE | PROTECTED)) == 0 || @@ -783,8 +807,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Symbol owner = sym.owner(); if (sym.kind == VAL && (sym.flags & (PRIVATE | SEALED)) == 0 && owner != null && owner.kind == CLASS && - (owner.flags & FINAL) != 0) + (owner.flags & FINAL) != 0) { + System.out.println(sym + " is final"); sym.flags |= FINAL; + } sym = enterInScope(sym); } tree.setSymbol(sym); @@ -835,6 +861,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { context.scope.enter(sym); } else if (sym.kind == VAL && other.kind == VAL) { // it's an overloaded definition + /* if (((sym.flags ^ other.flags) & SOURCEFLAGS) != 0) { // todo: refine, DEFERRED, MUTABLE and OVERRIDE should be // treated specially; maybe only PRIVATE and PROTECTED? @@ -843,9 +870,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { ": modifier lists differ in " + Modifiers.Helper.toString( (sym.flags ^ other.flags) & SOURCEFLAGS)); - } else { - e.setSymbol(other.overloadWith(sym)); - } + */ + e.setSymbol(other.overloadWith(sym)); } else { error(sym.pos, sym.nameString() + " is already defined as " + @@ -1247,11 +1273,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (tree.type.isObjectType()) { // insert apply method Symbol applyMeth = tree.type.lookup(Names.apply); - if (applyMeth != Symbol.NONE && isAccessible(applyMeth, tree)) { - applyMeth.flags |= (ACCESSED | SELECTOR); + if (applyMeth != Symbol.NONE) { + Type applyType = checkAccessible( + tree.pos, applyMeth, tree.type.memberType(applyMeth), + tree); tree = make.Select(tree.pos, tree, Names.apply) .setSymbol(applyMeth) - .setType(tree.type.memberType(applyMeth)); + .setType(applyType); return adapt(tree, mode, pt); } } @@ -1362,14 +1390,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { //System.out.println(name);//DEBUG return error(tree.pos, "not found: " + decode(name)); } else { - sym.flags |= ACCESSED; if (sym.owner().kind == CLASS) { pre = nextcontext.enclClass.owner.thisType(); if (!sym.owner().isPackage()) { Tree qual1 = makeStableId(tree.pos, pre); tree = make.Select(tree.pos, qual1, name); - if (context.enclClass != nextcontext.enclClass) - sym.flags |= SELECTOR; //System.out.println(name + " :::> " + tree + " " + qual1.symbol());//DEBUG } } else { @@ -1395,15 +1420,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { nextimports = nextimports.prev; } sym = sym1; - sym.flags |= (ACCESSED | SELECTOR); qual = lastimports.importPrefix().duplicate(); pre = qual.type; //new TextTreePrinter().print(name + " => ").print(lastimports.tree).print("." + name).println().end();//DEBUG tree = make.Select(tree.pos, qual, name); } - if (qual != Tree.Empty) checkAccessible(tree.pos, sym, qual); Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type()) .asSeenFrom(pre, sym.owner()); + if (qual != Tree.Empty) + symtype = checkAccessible(tree.pos, sym, symtype, qual); if (symtype == Type.NoType) return error(tree.pos, "not found: " + decode(name)); if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) && sym.isStable()) { @@ -1430,14 +1455,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return error(tree.pos, decode(name) + " is not a member of " + qual.type.widen()); } else { - checkAccessible(tree.pos, sym, qual); - sym.flags |= ACCESSED; - if (!TreeInfo.isSelf(qual, context.enclClass.owner)) - sym.flags |= SELECTOR; Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type()) .asSeenFrom(qual.type, sym.owner()); if (symtype == Type.NoType) return error(tree.pos, "not found: " + decode(name)); + else + symtype = checkAccessible(tree.pos, sym, symtype, qual); //System.out.println(sym.name + ":" + symtype);//DEBUG if (uninst.length != 0) { switch (symtype) { @@ -2144,8 +2167,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Symbol tsym = TreeInfo.methSymbol(fn1); if (tsym.kind != ERROR) { assert tsym.isType() : tsym; - Type tp = fn1.type.unalias(); - switch (tp) { + switch (fn1.type.unalias()) { case TypeRef(Type pre, Symbol c, Type[] argtypes): if (c.kind == CLASS) { c.initialize(); @@ -2154,7 +2176,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { fn1 = gen.mkRef(fn1.pos, pre, constr); switch (fn1) { case Select(Tree fn1qual, _): - checkAccessible(fn1.pos, constr, fn1qual); + fn1.type = checkAccessible( + fn1.pos, constr, fn1.type, fn1qual); } if (tsym == c) { switch (fn0) { diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index d25c547e20..24c452cf70 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -43,6 +43,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { private Unit unit; private Definitions defs = global.definitions; private Infer infer = new Infer(this); + private Symbol enclClass; public void apply(Unit unit) { this.unit = unit; @@ -65,13 +66,17 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { Type[] closure = clazz.closure(); HashMap/*<Symbol,Symbol>*/ overrides = null; for (int i = 0; i < closure.length; i++) { - for (Scope.SymbolIterator it = closure[i].members().iterator(); + for (Scope.SymbolIterator it = closure[i].members().iterator(true); it.hasNext();) { Symbol other = it.next(); - Symbol member = ((other.flags & PRIVATE) != 0) ? other + Symbol members = ((other.flags & PRIVATE) != 0) ? other : clazz.info().lookup(other.name); - if (member != other && member.kind != NONE) - checkOverride(pos, clazz, member, other); + Symbol member = Symbol.NONE; + if (members.kind != NONE && + members.owner() != other.owner() && + (members.owner() == clazz || + !members.owner().isSubClass(other.owner()))) + member = checkOverride(pos, clazz, members, other); if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) { if ((member.flags & DEFERRED) != 0) { abstractClassError( @@ -97,7 +102,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { if ((other.flags & DEFERRED) != 0) { abstractClassError( clazz, member + member.locationString() + - " is marked `override' and overrides only abstract members"); + " is marked `override' and overrides only abstract members" + other + other.locationString()); } } } @@ -125,10 +130,33 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { * 7. If O and M are values, then M's type is a subtype of O's type. * 8. If O is an immutable value, then so is M. */ - void checkOverride(int pos, Symbol clazz, Symbol member, Symbol other) { + Symbol checkOverride(int pos, Symbol clazz, Symbol members, Symbol other) { + Type self = clazz.thisType(); + Symbol member = members; + Type memberinfo = normalizedInfo(self, member); + Type otherinfo = normalizedInfo(self, other); + switch (memberinfo) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + for (int i = 0; i < alts.length; i++) { + if (alttypes[i].isSubType(otherinfo)) { + if (member == members) { + member = alts[i]; + memberinfo = alttypes[i]; + } else { + unit.error( + pos, + "ambiguous override: both " + + member + ":" + memberinfo + + "\n and " + alts[i] + ":" + alttypes[i] + + "\n override " + other + ":" + otherinfo + + other.locationString()); + } + } + } + if (member == members) { + } + } if (member.owner() == clazz) pos = member.pos; - else if (member.owner().isSubClass(other.owner())) - return; // everything was already checked elsewhere if ((member.flags & PRIVATE) != 0) { overrideError(pos, member, other, "has weaker access privileges; it should not be private"); @@ -149,7 +177,6 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { ":\n both are inherited from mixin classes; " + "\n an overriding definition in the current template is required"); } else { - Type self = clazz.thisType(); switch (other.kind) { case CLASS: overrideError(pos, member, other, "cannot override a class"); @@ -162,9 +189,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { if (other.isConstructor()) overrideError(pos, member, other, "cannot override a class constructor"); - Type selftype = normalizedInfo(self, member); - Type othertype = normalizedInfo(self, other); - if (!selftype.isSubType(othertype)) + if (!memberinfo.isSubType(otherinfo)) overrideTypeError(pos, member, other, self, false); if (member.kind == TYPE && !self.memberLoBound(other).isSubType( @@ -173,6 +198,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } } + return member; } void overrideError(int pos, Symbol member, Symbol other, String msg) { @@ -842,10 +868,14 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { Symbol sym = tree.symbol(); switch (tree) { case ClassDef(_, _, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ): + Symbol enclClassPrev = enclClass; + enclClass = sym; validateVariance(sym, sym.info(), CoVariance); validateVariance(sym, sym.typeOfThis(), CoVariance); - return super.transform( + Tree tree1 = super.transform( copy.ClassDef(tree, tree.symbol(), tparams, vparams, tpe, addCaseMethods(templ, tree.symbol()))); + enclClass = enclClassPrev; + return tree1; case DefDef(_, _, _, _, _, _): validateVariance(sym, sym.type(), CoVariance); @@ -933,10 +963,23 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { maxindex[i] = symindex; } } + sym.flags |= ACCESSED; return elimTypeNode(tree); + + case Select(Tree qual, Name name): + sym.flags |= ACCESSED; + if (!TreeInfo.isSelf(qual, enclClass)) + sym.flags |= SELECTOR; + if (qual instanceof Tree.Super && (sym.flags & DEFERRED) != 0) { + Symbol sym1 = enclClass.thisSym().info().lookup(sym.name); + if ((sym1.flags & OVERRIDE) == 0 || (sym1.flags & DEFERRED) != 0) + unit.error(tree.pos, + "symbol accessed from super may not be abstract"); + } + return elimTypeNode(super.transform(tree)); + default: return elimTypeNode(super.transform(tree)); } - } } |