From 682856e0623ddc61442f644e4935ce449480a958 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jun 2004 12:33:10 +0000 Subject: *** empty log message *** --- .../scala/tools/scalac/typechecker/Analyzer.scala | 54 ++++++++--- sources/scala/tools/scalac/typechecker/Infer.scala | 6 +- sources/scalac/symtab/Modifiers.java | 2 +- sources/scalac/symtab/Symbol.java | 69 +++++++++++++- sources/scalac/symtab/Type.java | 101 ++++++++++++++++----- .../scalac/symtab/classfile/ClassfileParser.java | 1 + sources/scalac/symtab/classfile/Pickle.java | 4 +- sources/scalac/symtab/classfile/UnPickle.java | 4 +- sources/scalac/transformer/AddInterfaces.java | 14 ++- sources/scalac/transformer/UnCurry.java | 9 +- sources/scalac/transformer/UnCurryPhase.java | 2 +- sources/scalac/typechecker/RefCheck.java | 14 ++- sources/scalac/typechecker/RefCheckPhase.java | 3 +- 13 files changed, 223 insertions(+), 60 deletions(-) (limited to 'sources') diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala index fc6a659be7..6ed24e1c9b 100644 --- a/sources/scala/tools/scalac/typechecker/Analyzer.scala +++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala @@ -942,18 +942,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( val info = new LazyTreeType(tree); clazz.setInfo(info); modul.setInfo(info); - // !!! Unfortunately, this breaks separate compilation -// val lclass = modul.linkedClass(); -// // Taken from SymbolLoader.initializeRoot() -// if (lclass != null) { -// if (lclass.rawInfo().isInstanceOf[SymbolLoader] && -// !lclass.rawInfo().isInstanceOf[SourceCompleter]) { -// lclass.setInfo(Type.ErrorType); -// //val allConstr = lclass.allConstructors(); -// //allConstr.setInfo(Type.ErrorType); -// //allConstr.flags = allConstr.flags | Modifiers.PRIVATE; -// } -// } } enterSym(tree, modul) @@ -1077,6 +1065,22 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( } } +/* + def addOverloaded(tp: Type, sym: Symbol): Type = { + if (!sym.isPrivate()) { + val owner = sym.owner(); + if (owner.kind == CLASS) { + for (p <- sym.owner().info.parents()) { + val sym1 = p.lookupNonPrivate(sym.name); + if (sym1.kind != NONE) { + + } + } + } + } + } +*/ + // Definining Symbols ------------------------------------------------------- /** Define symbol associated with `tree' using given `unit' and `context'. @@ -1176,6 +1180,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( owntype = makeMethodType(tparamSyms, vparamSyms, restype); //System.out.println("methtype " + name + ":" + owntype);//DEBUG + sym.addInheritedOverloaded(owntype); case Tree$ValDef(mods, name, _tpe, _rhs) => var tpe = _tpe; @@ -1207,6 +1212,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( owntype = owntype.deconst(); } popContext(); + sym.addInheritedOverloaded(owntype); } case Tree$AliasTypeDef(mods, name, tparams, _rhs) => @@ -1931,6 +1937,13 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( popContext(); val templ1: Tree$Template = copy.Template(templ, parents, body1); templ1.setType(owner.getType()); + // initialize all members; necessary to initialize overloaded symbols + val members = owner.members().iterator(false); + while (members.hasNext()) { + val sym = members.next(); + sym.initialize(); + //System.out.println(owner.toString() + " defines " + sym + ":" + sym.getType());//DEBUG + } templ1 } @@ -2199,7 +2212,22 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( val templ1: Tree$Template = transformTemplate(templ, sym.moduleClass()); if (tpe1 != Tree.Empty && !templ1.getType().isSubType(tpe1.getType())) error(tree.pos, "" + sym + " does not implement " + tpe1.getType()); - copy.ModuleDef(tree, sym, tpe1, templ1) + + /* + // !!! Unfortunately, this breaks separate compilation + val lclass = sym.linkedClass(); + // Taken from SymbolLoader.initializeRoot() + if (lclass != null) { + if (lclass.rawInfo().isInstanceOf[SymbolLoader]) { + lclass.setInfo(Type.ErrorType); + val allConstr = lclass.allConstructors(); + allConstr.setInfo(Type.ErrorType); + allConstr.flags = allConstr.flags | Modifiers.PRIVATE; + } + } + */ + + copy.ModuleDef(tree, sym, tpe, templ1) .setType(Type.NoType); case Tree$DefDef(_, name, tparams, vparams, tpe, rhs) => diff --git a/sources/scala/tools/scalac/typechecker/Infer.scala b/sources/scala/tools/scalac/typechecker/Infer.scala index 36efbc8a69..5c33e3b845 100644 --- a/sources/scala/tools/scalac/typechecker/Infer.scala +++ b/sources/scala/tools/scalac/typechecker/Infer.scala @@ -391,7 +391,7 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal gen.mkNullLit(pos) } else { val v = bestView(vargs(0), vargs(1), Names.EMPTY); - if (v != null) { + if (v != null && !v.locked) { if (v.locked) { error(pos, "recursive view instantiation of non-contractive " + v.sym + v.sym.locationString() + " with type " + @@ -802,7 +802,9 @@ class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scal while (!viewMeths.isEmpty && !isApplicable(viewMeths.head.symtype, argtypes, pt, Names.EMPTY, false)) viewMeths = viewMeths.tail; - if (!viewMeths.isEmpty) true + if (!viewMeths.isEmpty) { + true + } // todo: remove else { val coerceMeth: Symbol = tp1.lookup(Names.coerce); diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java index 1b07e2967f..4ba225471a 100644 --- a/sources/scalac/symtab/Modifiers.java +++ b/sources/scalac/symtab/Modifiers.java @@ -41,7 +41,7 @@ public interface Modifiers { int PACKAGE = 0x00100000; // symbol is a java package. int STABLE = 0x00800000; // functions that are assumed to be stable - // (typically, access methods for valdefs) + // (typically, access methods for valdefs) int CAPTURED = 0x01000000; // variables is accessed from // nested function. Set by LambdaLift diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index c6c38c33bb..45c3b05548 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -1067,7 +1067,7 @@ public abstract class Symbol implements Modifiers, Kinds { String name1 = name.toString(); if (name1.endsWith(Names._EQ.toString())) name1 = name1.substring(0, name1.length() - Names._EQ.length()); - return owner.info().lookup(Name.fromString(name1 + "$")); + return owner.lookup(Name.fromString(name1 + "$")); } /** The members of this class or module symbol @@ -1503,10 +1503,15 @@ public abstract class Symbol implements Modifiers, Kinds { public Symbol overloadWith(Symbol that) { assert isTerm() : Debug.show(this); assert this.name == that.name : Debug.show(this) + " <> " + Debug.show(that); - assert this.owner == that.owner : Debug.show(this) + " != " + Debug.show(that); + //assert this.owner == that.owner : Debug.show(this) + " != " + Debug.show(that); assert this.isConstructor() == that.isConstructor(); - int overflags = (this.flags & that.flags & (JAVA | ACCESSFLAGS | DEFERRED | PARAM | SYNTHETIC)) | - ((this.flags | that.flags) & ACCESSOR); + int overflags; + //if (this.owner == that.owner) + overflags = (this.flags & that.flags & + (JAVA | ACCESSFLAGS | DEFERRED | PARAM | SYNTHETIC)) | + ((this.flags | that.flags) & ACCESSOR); + // else // it's an inherited overloaded alternative + // overflags = this.flags & SOURCEFLAGS; Symbol overloaded = (this.isConstructor()) ? this.constructorClass().newConstructor(this.constructorClass().pos, overflags) : owner.newTerm(pos, overflags, name, 0); @@ -1638,6 +1643,62 @@ public abstract class Symbol implements Modifiers, Kinds { public int tag() { return name.toString().hashCode(); } + + public void addInheritedOverloaded(Type owntype) { + if (false && owner().kind == CLASS && !isConstructor() && owner().lookup(name) == this) { + // it's a class member which is not an overloaded alternative + Symbol sym = Type.lookupNonPrivate(owner().parents(), name); + if (sym.kind == VAL) { + Type symtype = owner.thisType().memberType(sym); + switch (symtype) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + for (int i = 0; i < alts.length; i++) + addInheritedOverloaded(owntype, alts[i], alttypes[i]); + break; + default: + addInheritedOverloaded(owntype, sym, symtype); + } + } + } + } + + private void addInheritedOverloaded(Type owntype, Symbol sym, Type symtype) { + if (!owntype.overrides(symtype)) { + System.out.println(owner() + " inherits overloaded: " + sym + ":" + symtype + sym.locationString());//debug + owner().members().lookupEntry(name).setSymbol(overloadWith(sym)); + //System.out.println("type is now: " + owner().members().lookup(name).type()); + } + } + + public Type removeInheritedOverloaded(Type owntype) { + //assert name != Names.toString || + // Global.instance.currentPhase.id != Global.instance.PHASE.UNCURRY.id(); + switch (owntype) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + int n = 0; + for (int i = 0; i < alts.length; i++) + if (alts[i].owner() == owner()) n++; + if (n < alts.length) { + Symbol[] alts1 = new Symbol[n]; + Type[] alttypes1 = new Type[n]; + int j = 0; + for (int i = 0; i < alts.length; i++) { + if (alts[i].owner() == owner()) { + alts1[j] = alts[i]; + alttypes1[j] = alttypes[i]; + j++; + } else { + System.out.println("removing inherited alternatve " + alts[i] + ":" + alttypes[i]);//debug + } + } + return Type.OverloadedType(alts1, alttypes1); + } else { + return owntype; + } + default: + return owntype; + } + } } /** A class for term symbols diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 8f57093823..e88240a56f 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -197,7 +197,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } public static Type typeRef(Type pre, Symbol sym, Type[] args) { - if (!pre.isLegalPrefix() && !pre.isError()) + if (sym.kind == TYPE && !pre.isLegalPrefix() && !pre.isError()) throw new Type.Malformed(pre, sym.nameString()); rebind: if (sym.isAbstractType()) { @@ -225,7 +225,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return new ExtTypeRef(pre, sym, args); } private static boolean isLegalTypeRef(Type pre, Symbol sym, Type[] args) { - if (!pre.isLegalPrefix() && !pre.isError()) return false; + if (sym.kind == TYPE && !pre.isLegalPrefix() && !pre.isError()) return false; if (!sym.isType() && !sym.isError()) return false; // !!! return args.length == 0 || args.length == sym.typeParams().length; return true; @@ -687,9 +687,12 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return true; case TypeRef(_, Symbol sym, _): if (sym.isParameter() && sym.isSynthetic()) return true; + return false; + /* return sym.kind == CLASS && ((sym.flags & JAVA) != 0 || (sym.flags & (TRAIT | ABSTRACT)) == 0); + */ default: return false; } @@ -806,33 +809,34 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return sym.info().lookupNonPrivate(name); case CompoundType(Type[] parts, Scope members): Symbol sym = members.lookup(name); - if (sym.kind != NONE && (sym.flags & PRIVATE) == 0) - return sym; - - // search base types in reverse; non-abstract members - // take precedence over abstract ones. - int i = parts.length; - sym = Symbol.NONE; - while (i > 0) { - i--; - Symbol sym1 = parts[i].lookupNonPrivate(name); - if (sym1.kind != NONE && - (sym1.flags & PRIVATE) == 0 && - (sym.kind == NONE - || - (sym.flags & DEFERRED) != 0 && - (sym1.flags & DEFERRED) == 0 - || - (sym.flags & DEFERRED) == (sym1.flags & DEFERRED) && - sym1.owner().isSubClass(sym.owner()))) - sym = sym1; - } - return sym; + if (sym.kind != NONE && (sym.flags & PRIVATE) == 0) return sym; + else return lookupNonPrivate(parts, name); default: return Symbol.NONE; } } + public static Symbol lookupNonPrivate(Type[] parts, Name name) { + // search base types in reverse; non-abstract members + // take precedence over abstract ones. + int i = parts.length; + Symbol sym = Symbol.NONE; + while (i > 0) { + i--; + Symbol sym1 = parts[i].lookupNonPrivate(name); + if (sym1.kind != NONE && + (sym.kind == NONE + || + (sym.flags & DEFERRED) != 0 && + (sym1.flags & DEFERRED) == 0 + || + (sym.flags & DEFERRED) == (sym1.flags & DEFERRED) && + sym1.owner().isSubClass(sym.owner()))) + sym = sym1; + } + return sym; + } + /** * Looks up in the current type a symbol with the same name as the * given symbol and whose type (as seen from the given prefix) is @@ -2342,6 +2346,55 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } } + /** Does this type match type `tp', so that corresponding symbols with + * the two types would be taken to override each other? + */ + public boolean overrides(Type tp) { + switch (this) { + case OverloadedType(Symbol[] alts, Type[] alttypes): + for (int i = 0; i < alttypes.length; i++) { + if (alttypes[i].overrides(tp)) return true; + } + return false; + default: + switch (tp) { + case MethodType(Symbol[] ps1, Type res1): + switch (this) { + case MethodType(Symbol[] ps, Type res): + if (ps.length != ps1.length) return false; + for (int i = 0; i < ps.length; i++) { + Symbol p1 = ps1[i]; + Symbol p = ps[i]; + if (!p1.type().isSameAs(p.type()) || + (p1.flags & (DEF | REPEATED)) != (p.flags & (DEF | REPEATED))) + return false; + } + return res.overrides(res1); + } + return false; + + case PolyType(Symbol[] ps1, Type res1): + switch (this) { + case PolyType(Symbol[] ps, Type res): + if (ps.length != ps1.length) return false; + for (int i = 0; i < ps.length; i++) + if (!ps1[i].info().subst(ps1, ps).isSameAs(ps[i].info()) || + !ps[i].loBound().isSameAs(ps1[i].loBound().subst(ps1, ps)) || + !ps[i].vuBound().isSameAs(ps1[i].vuBound().subst(ps1, ps))) + return false; + return res.overrides(res1.subst(ps1, ps)); + } + return false; + + case OverloadedType(_, _): + throw new ApplicationError("overrides inapplicable for " + tp); + + default: + return true; + } + } + } + // Closures and Least Upper Bounds --------------------------------------------------- /** The closure of this type, i.e. the widened type itself followed by all diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java index c4eaab9e5c..73432a945f 100644 --- a/sources/scalac/symtab/classfile/ClassfileParser.java +++ b/sources/scalac/symtab/classfile/ClassfileParser.java @@ -226,6 +226,7 @@ public class ClassfileParser implements ClassfileConstants { symbol = owner.newTerm(Position.NOPOS, sflags, name); } setParamOwners(type, symbol); + symbol.addInheritedOverloaded(type); symbol.setInfo(type); attrib.readAttributes(symbol, type, METH_ATTR); if (name != CONSTR_N) { diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java index 6891093e75..4bb9419b2b 100644 --- a/sources/scalac/symtab/classfile/Pickle.java +++ b/sources/scalac/symtab/classfile/Pickle.java @@ -138,7 +138,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags { putSymbol(it.next()); break; case VAL: - putType(sym.info()); + putType(sym.removeInheritedOverloaded(sym.info())); if (sym.isConstructor() && sym == sym.constructorClass().allConstructors()) putSymbol(sym.constructorClass()); @@ -358,7 +358,7 @@ public class Pickle implements Kinds, Modifiers, EntryTags { writeRef(sym.allConstructors()); break; case VAL: - writeRef(sym.info()); + writeRef(sym.removeInheritedOverloaded(sym.info())); if (sym.isConstructor() && sym == sym.constructorClass().allConstructors()) writeRef(sym.constructorClass()); diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index 6f6866782e..1c41932a6d 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -306,7 +306,9 @@ public class UnPickle implements Kinds, Modifiers, EntryTags, TypeTags { Symbol clasz = readSymbolRef(); assert clasz == sym.moduleClass(): Debug.show(sym); } - sym.setInfo(getType(inforef, sym)); + Type owntype = getType(inforef, sym); + sym.addInheritedOverloaded(owntype); + sym.setInfo(owntype); break; default: diff --git a/sources/scalac/transformer/AddInterfaces.java b/sources/scalac/transformer/AddInterfaces.java index 82bd3d4fdd..a54bcc95e8 100644 --- a/sources/scalac/transformer/AddInterfaces.java +++ b/sources/scalac/transformer/AddInterfaces.java @@ -222,15 +222,21 @@ public class AddInterfaces extends GenTransformer { /** * Returns the tree of the given class whose body is built by * adding to the given body the class members. Non-abstract - * methods are removed from the given method map. All other + * methods are removed from the ngiven method map. All other * members are generated from their symbol. */ private Tree getClassTree(Symbol clasz, TreeList body, Map methods) { Scope members = clasz.nextInfo().members(); + /* + for (Scope.SymbolIterator i = members.iterator(false); i.hasNext(); ) { + Symbol sym = i.next(); + System.out.println(clasz + " defines " + sym + ":" + sym.getType()); + } + */ for (Scope.SymbolIterator i = members.iterator(true); i.hasNext(); ) { Symbol member = i.next(); if (!member.isTerm()) continue; - body.append(getMemberTree(member, methods)); + body.append(getMemberTree(clasz, member, methods)); } return gen.ClassDef(clasz, body.toArray()); } @@ -240,11 +246,11 @@ public class AddInterfaces extends GenTransformer { * removed from the given method map. All other members are * generated from their symbol. */ - private Tree getMemberTree(Symbol member, Map methods) { + private Tree getMemberTree(Symbol clasz, Symbol member, Map methods) { if (!member.isMethod()) return gen.ValDef(member, Tree.Empty); if (member.isDeferred()) return gen.DefDef(member, Tree.Empty); Tree method = (Tree)methods.remove(member); - assert method != null: Debug.show(member); + assert method != null: Debug.show(clasz + "." + member + ":" + member.info() + member.locationString()); return method; } diff --git a/sources/scalac/transformer/UnCurry.java b/sources/scalac/transformer/UnCurry.java index f088ca6943..9eadc4d85f 100644 --- a/sources/scalac/transformer/UnCurry.java +++ b/sources/scalac/transformer/UnCurry.java @@ -113,7 +113,14 @@ public class UnCurry extends OwnerTransformer System.out.flush(); //uncurry type and symbol Type prevtype = tree.type; - if (prevtype != null) tree.type = descr.uncurry(prevtype); + if (prevtype != null) { + switch (prevtype) { + case OverloadedType(_, _): + assert tree.symbol() != null; + prevtype = tree.symbol().removeInheritedOverloaded(prevtype); + } + tree.type = descr.uncurry(prevtype); + } switch (tree) { case ClassDef(_, _, AbsTypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl): return copy.ClassDef( diff --git a/sources/scalac/transformer/UnCurryPhase.java b/sources/scalac/transformer/UnCurryPhase.java index 00a966b3eb..79b96f0094 100644 --- a/sources/scalac/transformer/UnCurryPhase.java +++ b/sources/scalac/transformer/UnCurryPhase.java @@ -30,7 +30,7 @@ public class UnCurryPhase extends Phase implements Modifiers { * - if symbol is a def parameter with transformed type T, return () => T */ public Type transformInfo(Symbol sym, Type tp0) { - Type tp1 = uncurry(tp0); + Type tp1 = uncurry(sym.removeInheritedOverloaded(tp0)); if (sym.isDefParameter()) return global.definitions.FUNCTION_TYPE(Type.EMPTY_ARRAY, tp1); else return tp1; } diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index 9358f39722..5239a4d68a 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -76,9 +76,12 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { void checkAllOverrides(int pos, Symbol clazz) { Type[] closure = clazz.closure(); for (int i = 0; i < closure.length; i++) { - for (Scope.SymbolIterator it = closure[i].members().iterator(true); + Type basetype = closure[i]; + Symbol baseclazz = basetype.symbol(); + for (Scope.SymbolIterator it = basetype.members().iterator(true); it.hasNext();) { - checkOverride(pos, clazz, it.next()); + Symbol sym = it.next(); + if (sym.owner() == baseclazz) checkOverride(pos, clazz, sym); } } @@ -86,12 +89,12 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { for (Scope.SymbolIterator it = clazz.members().iterator(true); it.hasNext();) { Symbol sym = it.next(); - if ((sym.flags & OVERRIDE) != 0) { + if ((sym.flags & OVERRIDE) != 0 && sym.owner() == clazz) { 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"); + unit.error(sym.pos, sym + ":" + sym.type() + sym.locationString() + " overrides nothing");//debug sym.flags &= ~OVERRIDE; } else if (sym.isAbstractOverride() && sym.overriddenSymbol(parents[0]).kind == NONE) { @@ -117,7 +120,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { switch (member1.info()) { case OverloadedType(Symbol[] alts, _): for (int i = 0; i < alts.length; i++) { - if (normalizedInfo(self, alts[i]).isSubType(template)) { + if (normalizedInfo(self, alts[i]).isSubType(template) && + alts[i].owner() == clazz) { if (member == other) member = alts[i]; else diff --git a/sources/scalac/typechecker/RefCheckPhase.java b/sources/scalac/typechecker/RefCheckPhase.java index e46ac290f9..ca73d37d6d 100644 --- a/sources/scalac/typechecker/RefCheckPhase.java +++ b/sources/scalac/typechecker/RefCheckPhase.java @@ -27,9 +27,8 @@ public class RefCheckPhase extends Phase { } public Type transformInfo(Symbol sym, Type tp) { - if (sym.isModule() && !sym.isStatic()) { + if (sym.isModule() && !sym.isStatic()) return Type.PolyType(Symbol.EMPTY_ARRAY, tp); - } else return tp; } -- cgit v1.2.3