From 70d78cbfc802ccc49d5d324755865ff07985dfef Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Sep 2003 17:54:44 +0000 Subject: *** empty log message *** --- sources/scala/xml/Generic.scala | 6 +- sources/scalac/ast/printer/TextTreePrinter.java | 14 ++--- sources/scalac/symtab/Scope.java | 12 +++- sources/scalac/symtab/Symbol.java | 3 +- sources/scalac/symtab/Type.java | 84 +++++++++++++++---------- sources/scalac/transformer/LambdaLift.java | 10 ++- sources/scalac/typechecker/Analyzer.java | 26 +++++--- sources/scalac/typechecker/Infer.java | 21 +------ sources/scalac/typechecker/RefCheck.java | 60 ++++++++++-------- test/files/neg/bug97.check | 2 +- test/neg/bug97.check | 2 +- 11 files changed, 135 insertions(+), 105 deletions(-) diff --git a/sources/scala/xml/Generic.scala b/sources/scala/xml/Generic.scala index bc760bcfef..fd2628aeb1 100644 --- a/sources/scala/xml/Generic.scala +++ b/sources/scala/xml/Generic.scala @@ -67,10 +67,10 @@ object Generic { def save( filename:String, doc:Any ):Unit = { import java.io.{FileOutputStream,Writer}; import java.nio.channels.{Channels,FileChannel}; - def toXML( xs: List[Any], fc:Writer ):Unit = xs match { + def toXMLList( xs: List[Any], fc:Writer ):Unit = xs match { case _::ys => toXML( xs.head, fc ); - toXML( ys, fc ); + toXMLList( ys, fc ); case _ => () } def toXML( doc: Any, fc:Writer ):Unit = doc match { @@ -82,7 +82,7 @@ object Generic { fc.write( Generic.toXML(( doc.asInstanceOf[ Attribbed ]) .attribs )); fc.write( ">" ); - toXML( xs, fc ); + toXMLList( xs, fc ); fc.write( "" ); diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java index e4889b9bc2..53b48c8a41 100644 --- a/sources/scalac/ast/printer/TextTreePrinter.java +++ b/sources/scalac/ast/printer/TextTreePrinter.java @@ -313,13 +313,13 @@ public class TextTreePrinter implements TreePrinter { printOpt(TXT_EQUAL, rhs, true); break; - case DefDef(int mods, - Name name, - Tree.AbsTypeDef[] tparams, - Tree.ValDef[][] vparams, - Tree tpe, - Tree rhs): - printModifiers(mods); + case DefDef(int mods, + Name name, + Tree.AbsTypeDef[] tparams, + Tree.ValDef[][] vparams, + Tree tpe, + Tree rhs): + printModifiers(mods); print(KW_DEF); print(Text.Space); if (name.isTypeName()) print(KW_THIS); diff --git a/sources/scalac/symtab/Scope.java b/sources/scalac/symtab/Scope.java index d0a2bf5b9b..9a3125f21c 100644 --- a/sources/scalac/symtab/Scope.java +++ b/sources/scalac/symtab/Scope.java @@ -69,11 +69,11 @@ public class Scope { /** the next entry in the hash bucket */ - Entry tail; + private Entry tail; /** the next entry in this scope */ - public Entry next; + private Entry next; /** The owner of the entry; */ @@ -109,7 +109,7 @@ public class Scope { /** all elements of this scope */ - public Entry elems; + private Entry elems; /** the hash table */ @@ -165,6 +165,12 @@ public class Scope { return clone; } + /** is the scope empty? + */ + public boolean isEmpty() { + return elems == Entry.NONE; + } + /** the number of entries in this scope */ int size() { diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 1abfa90ec8..8a583ccff9 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -1020,7 +1020,8 @@ public abstract class Symbol implements Modifiers, Kinds { assert this.name == that.name : 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); + int overflags = (this.flags & that.flags & (JAVA | ACCESSFLAGS)) | + ((this.flags | that.flags) & ACCESSOR); TermSymbol overloaded = (this.isConstructor()) ? TermSymbol.newConstructor(this.constructorClass(), overflags) : new TermSymbol(pos, name, owner, overflags); diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 5fa9d9e745..e94c7e87bc 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -199,8 +199,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return tsym; } void validate() {//debug - for (Scope.Entry e = members.elems; e != Scope.Entry.NONE; e = e.next) - assert e.sym.owner() == tsym; + for (Scope.SymbolIterator it = members.iterator(true); it.hasNext(); ) + assert it.next().owner() == tsym; } } @@ -599,7 +599,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return sym.fullName().startsWith(Names.scala_Function) && args.length > 0; case CompoundType(Type[] parents, Scope members): - return members.elems == Scope.Entry.NONE && + return members.isEmpty() && parents.length == 2 && parents[0].symbol().fullName() == Names.scala_Object && parents[1].isFunctionType(); @@ -607,6 +607,21 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return false; } + /** Is this a polymorphic method type? + */ + public boolean isPolymorphic() { + return typeParams().length > 0; + } + + /** Is this a parameterized or polymorphic method type? + */ + public boolean isParameterized() { + switch (this) { + case MethodType(_, _): return true; + default: return isPolymorphic(); + } + } + // Members and Lookup ------------------------------------------------------- /** Get the scope containing the local members of this type. @@ -1665,8 +1680,9 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { /** Does this type implement all symbols in scope `s' with same or stronger types? */ public boolean specializes(Scope s) { - for (Scope.Entry e = s.elems; e != Scope.Entry.NONE; e = e.next) - if (!specializes(e.sym)) return false; + for (Scope.SymbolIterator it = s.iterator(true); it.hasNext();) { + if (!specializes(it.next())) return false; + } return true; } @@ -1689,6 +1705,20 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { public boolean specializes0(Symbol sym1) { Symbol sym = lookup(sym1.name); + switch (sym.info()) { + case NoType: + return false; + case OverloadedType(Symbol[] alts, Type[] alttypes): + for (int i = 0; i < alts.length; i++) { + if (specializes0(alts[i], sym1)) return true; + } + return false; + default: + return specializes0(sym, sym1); + } + } + + private boolean specializes0(Symbol sym, Symbol sym1) { Type self = narrow(); Symbol[] tparams = symbol().typeParams(); Type[] targs = typeArgs(); @@ -1888,8 +1918,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { /** Does scope `s1' define all symbols of scope `s2' with the same kinds and infos? */ private boolean isSubScope(Scope s1, Scope s2) { - for (Scope.Entry e = s2.elems; e != Scope.Entry.NONE; e = e.next) { - Symbol sym2 = e.sym; + for (Scope.SymbolIterator it = s2.iterator(); it.hasNext(); ) { + Symbol sym2 = it.next(); Symbol sym1 = s1.lookup(sym2.name); if (sym1.kind != sym2.kind || !sym1.info().isSameAs( @@ -2166,17 +2196,17 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { Type[] rtps = new Type[tps.length]; Type[] rlbs = new Type[tps.length]; for (int i = 0; i < allBaseTypes.length; i++) { - for (Scope.Entry e = allBaseTypes[i].members().elems; - e != Scope.Entry.NONE; - e = e.next) { - Name name = e.sym.name; - if ((e.sym.flags & PRIVATE) == 0 && lubType.lookup(name) == e.sym) { - Type symType = memberTp(lubThisType, e.sym); - Type symLoBound = lubThisType.memberLoBound(e.sym); + for (Scope.SymbolIterator it = allBaseTypes[i].members().iterator(); + it.hasNext(); ) { + Symbol sym = it.next(); + Name name = sym.name; + if ((sym.flags & PRIVATE) == 0 && lubType.lookup(name) == sym) { + Type symType = memberTp(lubThisType, sym); + Type symLoBound = lubThisType.memberLoBound(sym); int j = 0; while (j < tps.length) { rsyms[j] = tps[j].lookupNonPrivate(name); - if (rsyms[j] == e.sym) break; + if (rsyms[j] == sym) break; if (rsyms[j].isMethod()) break; // since methods cannot // appear in refinements. rtps[j] = memberTp(tps[j], rsyms[j]) @@ -2190,7 +2220,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { if (j == tps.length) { Symbol lubSym = lub(rsyms, rtps, rlbs, lubType.symbol()); if (lubSym.kind != NONE && - !(lubSym.kind == e.sym.kind && + !(lubSym.kind == sym.kind && lubSym.info().isSameAs(symType) && lubSym.loBound().isSameAs(symType))) members.enter(lubSym); @@ -2199,7 +2229,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { } } //System.out.print("lub "); System.out.print(ArrayApply.toString(tps)); System.out.println(" = " + lubType);//DEBUG - if (leastBaseTypes.length == 1 && members.elems == Scope.Entry.NONE) + if (leastBaseTypes.length == 1 && members.isEmpty()) return leastBaseTypes[0]; else return lubType; } @@ -2254,7 +2284,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { treftl = new Type.List(tps[i], treftl); break; case CompoundType(Type[] parents, Scope members): - if (members.elems != Scope.Entry.NONE) + if (!members.isEmpty()) comptl = new Type.List(tps[i], comptl); for (int j = 0; j < parents.length; j++) treftl = new Type.List(parents[i], treftl); @@ -2286,7 +2316,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { // eliminate redudant typerefs Type[] treftypes = elimRedundant(treftl.toArrayReverse(), false); - if (treftypes.length != 1 || glbType.members.elems != Scope.Entry.NONE) { + if (treftypes.length != 1 || !glbType.members.isEmpty()) { // step 4: replace all abstract types by their lower bounds. boolean hasAbstract = false; for (int i = 0; i < treftypes.length; i++) { @@ -2321,7 +2351,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { if (lb != NoType) return lb; } - if (treftypes.length == 1 && glbType.members.elems == Scope.Entry.NONE) { + if (treftypes.length == 1 && glbType.members.isEmpty()) { return treftypes[0]; } else { glbType.parts = treftypes; @@ -2359,8 +2389,8 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ private static boolean setGlb(Scope result, Scope[] ss, Type glbThisType) { for (int i = 0; i < ss.length; i++) - for (Scope.Entry e = ss[i].elems; e != Scope.Entry.NONE; e = e.next) - if (!addMember(result, e.sym, glbThisType)) return false; + for (Scope.SymbolIterator it = ss[i].iterator(); it.hasNext(); ) + if (!addMember(result, it.next(), glbThisType)) return false; return true; } @@ -2634,16 +2664,6 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { return h; } - public static int hashCode(Scope.Entry elems) { - int h = 0; - for (Scope.Entry e = elems; e != Scope.Entry.NONE; e = e.next) - h = h * 41 - + e.sym.kind - + e.sym.name.hashCode() - + e.sym.info().hashCode(); - return h; - } - // todo: change in relation to needs. public boolean equals(Object other) { diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java index 67b396ec2e..9e3a497c80 100644 --- a/sources/scalac/transformer/LambdaLift.java +++ b/sources/scalac/transformer/LambdaLift.java @@ -444,9 +444,13 @@ public class LambdaLift extends OwnerTransformer (sym.kind == TYPE || (sym.kind == VAL && !sym.isMethod()))) { sym = descr.proxy(sym, currentOwner); } - Tree tree1 = copy.Ident(tree, sym).setType( - sym.nextType()); - if (name != sym.name) ((Ident)tree1).name = sym.name; + Tree tree1 = (sym.owner().kind == CLASS) + ? gen.mkRef(tree.pos, sym) + : copy.Ident(tree, sym).setType(sym.nextType()); + if (name != sym.name) { + if (tree1 instanceof Ident) ((Ident)tree1).name = sym.name; + else ((Select)tree1).selector = sym.name; + } if ((sym.flags & CAPTURED) != 0) return gen.Select(tree1, Names.elem); else return tree1; diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 55da4c5f88..fc53218f5e 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -369,7 +369,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if ((bsym.flags & FINAL) != 0) { error(constrs[i].pos, "illegal inheritance from final class"); } else if (bsym.isSealed() || - bsym.isSubClass(definitions.ANYVAL_CLASS)) { + bsym.isSubClass(definitions.ANYVAL_CLASS) || + bsym.isSubClass(definitions.ARRAY_CLASS)) { // are we in same scope as base type definition? Scope.Entry e = context.scope.lookupEntry(bsym.name); if (e.sym != bsym || e.owner != context.scope) { @@ -859,7 +860,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } context.scope.unlink(e); context.scope.enter(sym); - } else if (sym.kind == VAL && other.kind == VAL) { + } else if (context.owner.kind == CLASS && + sym.kind == VAL && other.kind == VAL && + ((sym.flags & ACCESSOR) == 0 || + (other.flags & ACCESSOR) == 0)) { // it's an overloaded definition /* if (((sym.flags ^ other.flags) & SOURCEFLAGS) != 0) { @@ -873,9 +877,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { */ e.setSymbol(other.overloadWith(sym)); } else { - error(sym.pos, - sym.nameString() + " is already defined as " + - other + other.locationString()); + if (context.owner.kind == CLASS) + error(sym.pos, + sym.nameString() + " is already defined as " + + other + other.locationString()); + else + error(sym.pos, + sym.nameString() + + " is already defined in local scope"); } } else { context.scope.enter(sym); @@ -2075,7 +2084,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { .isSameAs(sym1.type())) refinement.enter(sym1); } - if (refinement.elems == Scope.Entry.NONE && + if (refinement.isEmpty() && parentTypes.length == 1) owntype = parentTypes[0]; else @@ -2187,8 +2196,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } else { // it was an alias type // todo: handle overloaded constructors - fn1 = gen.TypeApply( - fn1, gen.mkTypes(fn1.pos, argtypes)); + if (argtypes.length != 0) + fn1 = gen.TypeApply( + fn1, gen.mkTypes(fn1.pos, argtypes)); if (tsym.typeParams().length != 0 && !(fn0 instanceof AppliedType)) fn1.type = Type.PolyType( diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java index c14515f841..5dcf9bf0db 100644 --- a/sources/scalac/typechecker/Infer.java +++ b/sources/scalac/typechecker/Infer.java @@ -65,23 +65,6 @@ public class Infer implements Modifiers, Kinds { (sym == null ? "expression" : sym) + " of type " + tp; } -// Helper definitions --------------------------------------------------------- - - /** Is type `tp' a polymorphic method type? - */ - private boolean isPolymorphic(Type tp) { - return tp.typeParams().length > 0; - } - - /** Is type `tp' a parameterized method type? - */ - boolean isParameterized(Type tp) { - switch (tp) { - case MethodType(_, _): return true; - default: return isPolymorphic(tp); - } - } - // Tree Substitution ------------------------------------------------------------- static class Substituter extends Transformer { @@ -954,8 +937,8 @@ public class Infer implements Modifiers, Kinds { } //where private boolean improves(Type tp1, Type tp2) { - return isParameterized(tp2) && - (!isParameterized(tp1) || specializes(tp1, tp2)); + return tp2.isParameterized() && + (!tp1.isParameterized() || specializes(tp1, tp2)); } /** Assign `tree' the type of an alternative diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java index 24c452cf70..d3a603642a 100644 --- a/sources/scalac/typechecker/RefCheck.java +++ b/sources/scalac/typechecker/RefCheck.java @@ -69,14 +69,14 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { for (Scope.SymbolIterator it = closure[i].members().iterator(true); it.hasNext();) { Symbol other = it.next(); - Symbol members = ((other.flags & PRIVATE) != 0) ? other + Symbol member = ((other.flags & PRIVATE) != 0) ? other : clazz.info().lookup(other.name); - 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 (member.owner() == other.owner()) + member = other; + else if (member.type() instanceof Type.OverloadedType) + member = findOverriding(pos, clazz, member, other); + if (member.kind != NONE && member != other) + checkOverride(pos, clazz, member, other); if (clazz.kind == CLASS && (clazz.flags & ABSTRACTCLASS) == 0) { if ((member.flags & DEFERRED) != 0) { abstractClassError( @@ -116,21 +116,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { clazz.flags |= ABSTRACTCLASS; } - /** Check that all conditions for overriding `other' by `member' are met. - * That is for overriding member M and overridden member O: - * - * 1. M must have the same or stronger access privileges as O. - * 2. O must not be final. - * 3. O is deferred, or M has `override' modifier. - * 4. O is not a class, nor a class constructor. - * 5. If O is a type alias, then M is an alias of O. - * 6. If O is an abstract type then - * either M is an abstract type, and M's bounds are sharper than O's bounds. - * or M is a type alias or class which conforms to O's bounds. - * 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. - */ - Symbol checkOverride(int pos, Symbol clazz, Symbol members, Symbol other) { + Symbol findOverriding(int pos, Symbol clazz, Symbol members, Symbol other) { Type self = clazz.thisType(); Symbol member = members; Type memberinfo = normalizedInfo(self, member); @@ -153,10 +139,29 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } } } - if (member == members) { - } } - if (member.owner() == clazz) pos = member.pos; + return member; + } + + /** Check that all conditions for overriding `other' by `member' are met. + * That is for overriding member M and overridden member O: + * + * 1. M must have the same or stronger access privileges as O. + * 2. O must not be final. + * 3. O is deferred, or M has `override' modifier. + * 4. O is not a class, nor a class constructor. + * 5. If O is a type alias, then M is an alias of O. + * 6. If O is an abstract type then + * either M is an abstract type, and M's bounds are sharper than O's bounds. + * or M is a type alias or class which conforms to O's bounds. + * 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) { + 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"); @@ -177,6 +182,7 @@ 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"); @@ -189,7 +195,8 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { if (other.isConstructor()) overrideError(pos, member, other, "cannot override a class constructor"); - if (!memberinfo.isSubType(otherinfo)) + if (!normalizedInfo(self, member).isSubType( + normalizedInfo(self, other))) overrideTypeError(pos, member, other, self, false); if (member.kind == TYPE && !self.memberLoBound(other).isSubType( @@ -198,7 +205,6 @@ public class RefCheck extends Transformer implements Modifiers, Kinds { } } - return member; } void overrideError(int pos, Symbol member, Symbol other, String msg) { diff --git a/test/files/neg/bug97.check b/test/files/neg/bug97.check index 5d4fcacb1b..cc620b3650 100644 --- a/test/files/neg/bug97.check +++ b/test/files/neg/bug97.check @@ -1,4 +1,4 @@ -test/neg/bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List +bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List case List(y) => "zero" ^ one error found diff --git a/test/neg/bug97.check b/test/neg/bug97.check index 5d4fcacb1b..cc620b3650 100644 --- a/test/neg/bug97.check +++ b/test/neg/bug97.check @@ -1,4 +1,4 @@ -test/neg/bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List +bug97.scala:3: expected pattern type scala.Any does not conform to sequence trait scala.List case List(y) => "zero" ^ one error found -- cgit v1.2.3