diff options
Diffstat (limited to 'sources/scalac/symtab')
-rw-r--r-- | sources/scalac/symtab/Definitions.java | 38 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 56 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 109 | ||||
-rw-r--r-- | sources/scalac/symtab/classfile/AttributeParser.java | 2 |
4 files changed, 178 insertions, 27 deletions
diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java index 93ab003055..5f2bf4735c 100644 --- a/sources/scalac/symtab/Definitions.java +++ b/sources/scalac/symtab/Definitions.java @@ -92,6 +92,16 @@ public class Definitions { public final Symbol OBJECT_CLASS; public final Type OBJECT_TYPE; + /** the scala.All class + */ + public final Symbol ALL_CLASS; + public final Type ALL_TYPE; + + /** the scala.AllRef class + */ + public final Symbol ALLREF_CLASS; + public final Type ALLREF_TYPE; + /** the primitive types */ public final Symbol BYTE_CLASS; @@ -220,6 +230,22 @@ public class Definitions { ANYVAL_CLASS = getClass(Names.scala_AnyVal); ANYVAL_TYPE = ANYVAL_CLASS.typeConstructor(); + // the scala.ALL class + ALL_CLASS = new ClassSymbol( + Position.NOPOS, Names.All.toTypeName(), SCALA_CLASS, 0); + SCALA_CLASS.members().enter(ALL_CLASS); + ALL_TYPE = ALL_CLASS.typeConstructor(); + ALL_CLASS.setInfo(Type.compoundType(new Type[]{ANY_TYPE}, new Scope(), ALL_CLASS)); + ALL_CLASS.constructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, ALL_TYPE)); + + // the scala.ALLREF class + ALLREF_CLASS = new ClassSymbol( + Position.NOPOS, Names.AllRef.toTypeName(), SCALA_CLASS, 0); + SCALA_CLASS.members().enter(ALLREF_CLASS); + ALLREF_TYPE = ALLREF_CLASS.typeConstructor(); + ALLREF_CLASS.setInfo(Type.compoundType(new Type[]{ANYREF_TYPE}, new Scope(), ALLREF_CLASS)); + ALLREF_CLASS.constructor().setInfo(Type.MethodType(Symbol.EMPTY_ARRAY, ALLREF_TYPE)); + // the primitive types DOUBLE_CLASS = getClass(Names.scala_Double); DOUBLE_TYPE = DOUBLE_CLASS.typeConstructor(); @@ -248,8 +274,7 @@ public class Definitions { JAVA_THROWABLE_TYPE = JAVA_THROWABLE_CLASS.typeConstructor(); THROW = new TermSymbol( Position.NOPOS, Names.throw_, JAVA_THROWABLE_CLASS, Modifiers.FINAL); - Symbol tvar = newTypeParameter(THROW, ANY_TYPE); - THROW.setInfo(Type.PolyType(new Symbol[]{tvar}, tvar.type())); + THROW.setInfo(ALL_TYPE); JAVA_THROWABLE_CLASS.members().enter(THROW); // add the java.lang.String class to the scala package @@ -292,7 +317,7 @@ public class Definitions { AS = new TermSymbol( Position.NOPOS, Names.as, ANY_CLASS, Modifiers.FINAL); - tvar = newTypeParameter(AS, ANY_TYPE); + Symbol tvar = newTypeParameter(AS, ANY_TYPE); AS.setInfo(Type.PolyType(new Symbol[]{tvar}, tvar.type())); ANY_CLASS.members().enter(AS); @@ -327,8 +352,7 @@ public class Definitions { // add a null value to the root scope NULL = new TermSymbol( Position.NOPOS, Names.null_, ROOT_CLASS, 0); - tvar = newTypeParameter(NULL, ANYREF_TYPE); - NULL.setInfo(Type.PolyType(new Symbol[]{tvar}, tvar.type())); + NULL.setInfo(ALLREF_TYPE); ROOT.members().enter(NULL); } @@ -338,8 +362,8 @@ public class Definitions { } private Symbol newTypeParameter(Symbol owner, Type bound) { - return new TypeSymbol( - Kinds.TYPE, Position.NOPOS, Name.fromString("T").toTypeName(), owner, Modifiers.PARAM) + return new AbsTypeSymbol( + Position.NOPOS, Name.fromString("T").toTypeName(), owner, Modifiers.PARAM) .setInfo(bound); } diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index f2e387c67b..eeb4d6e647 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -141,6 +141,12 @@ public abstract class Symbol implements Modifiers, Kinds { return this; } + /** Set the low bound of this type variable + */ + public Symbol setLoBound(Type lobound) { + throw new ApplicationError("setLoBound inapplicable for " + this); + } + // Symbol classification ---------------------------------------------------- /** Does this symbol denote a type? */ @@ -341,6 +347,14 @@ public abstract class Symbol implements Modifiers, Kinds { } } + /** The variance of this symbol as an integer + */ + public int variance() { + if ((flags & COVARIANT) != 0) return 1; + else if ((flags & CONTRAVARIANT) != 0) return -1; + else return 0; + } + // Symbol names ---------------------------------------------------------------- /** Get the fully qualified name of this Symbol @@ -592,6 +606,12 @@ public abstract class Symbol implements Modifiers, Kinds { throw new ApplicationError("typeConstructor inapplicable for " + this); } + /** The low bound of this type variable + */ + public Type loBound() { + throw new ApplicationError("loBound inapplicable for " + this); + } + /** Get this.type corresponding to this symbol */ public Type thisType() { @@ -1107,6 +1127,7 @@ public class TypeSymbol extends Symbol { private void computeClosure() { assert closures.closure != BAD_CLOSURE : this; closures.closure = BAD_CLOSURE; // to catch cycles. + // todo: why can't we do: inclClosure(SymSet.EMPTY, this) ? SymSet closureClassSet = inclClosureBases(SymSet.EMPTY, this); Symbol[] closureClasses = new Symbol[closureClassSet.size() + 1]; closureClasses[0] = this; @@ -1116,6 +1137,7 @@ public class TypeSymbol extends Symbol { //System.out.println(ArrayApply.toString(closures.closure));//DEBUG adjustType(type()); //System.out.println("closure(" + this + ") at " + Global.instance.currentPhase.name() + " = " + ArrayApply.toString(closures.closure));//DEBUG + } //where @@ -1151,6 +1173,36 @@ public class TypeSymbol extends Symbol { } } +public class AbsTypeSymbol extends TypeSymbol { + + private Type lobound = null; + + /** Constructor */ + public AbsTypeSymbol(int pos, Name name, Symbol owner, int flags) { + super(TYPE, pos, name, owner, flags); + } + + /** Return a fresh symbol with the same fields as this one. + */ + public Symbol cloneSymbol() { + if (Global.instance.debug) System.out.println("cloning " + this + this.locationString() + " in phase " + Global.instance.currentPhase.name()); + TypeSymbol other = new AbsTypeSymbol(pos, name, owner(), flags); + other.setInfo(info()); + other.setLoBound(loBound()); + return other; + } + + public Type loBound() { + initialize(); + return lobound == null ? Global.instance.definitions.ALL_TYPE : lobound; + } + + public Symbol setLoBound(Type lobound) { + this.lobound = lobound; + return this; + } +} + /** A class for class symbols. It has JavaClassSymbol as a subclass. */ public class ClassSymbol extends TypeSymbol { @@ -1377,6 +1429,10 @@ public final class ErrorSymbol extends Symbol { return this; } + public Type loBound() { + return Type.ErrorType; + } + public void reset(Type completer) { } } diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index d532db05c4..80e0823f97 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -489,6 +489,7 @@ public class Type implements Modifiers, Kinds, TypeTags { } /** Is this type a reference to an object type? + * todo: replace by this.isSubType(global.definitions.ANY_TYPE)? */ public boolean isObjectType() { switch (unalias()) { @@ -1266,7 +1267,10 @@ public class Type implements Modifiers, Kinds, TypeTags { case TypeRef(Type pre1, Symbol sym1, Type[] args1): switch (this) { case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym == sym1 && pre.isSameAs(pre1) && isSubArgs(args, args1)) + if (sym == sym1 && pre.isSameAs(pre1) && + isSubArgs(args, args1, sym.typeParams()) + || + sym.kind == TYPE && pre.memberInfo(sym).isSubType(that)) return true; break; } @@ -1355,11 +1359,26 @@ public class Type implements Modifiers, Kinds, TypeTags { return constr.inst.isSubType(that); } else { constr.hibounds = new List(that.dropVariance(), constr.hibounds); + assert that.dropVariance().symbol() != Global.instance.definitions.ALL_CLASS;//debug return true; } case TypeRef(_, Symbol sym, _): - if (sym.kind == ALIAS) return this.unalias().isSubType(that); + switch (that) { + case TypeRef(Type pre1, Symbol sym1, _): + if (sym1.kind == TYPE && + this.isSubType( + sym1.loBound().asSeenFrom(pre1, sym1.owner()))) + return true; + } + if (sym.kind == ALIAS) + return this.unalias().isSubType(that); + else if (sym == Global.instance.definitions.ALL_CLASS) + return that.isSubType(Global.instance.definitions.ANY_TYPE); + else if (sym == Global.instance.definitions.ALLREF_CLASS) + return + that.isSameAs(Global.instance.definitions.ANY_TYPE) || + that.isSubType(Global.instance.definitions.ANYREF_TYPE); break; case OverloadedType(Symbol[] alts, Type[] alttypes): @@ -1390,7 +1409,7 @@ public class Type implements Modifiers, Kinds, TypeTags { /** Are types `these' arguments types conforming to corresponding types `those'? */ - static boolean isSubArgs(Type[] these, Type[] those) { + static boolean isSubArgs(Type[] these, Type[] those, Symbol[] tparams) { if (these.length != those.length) return false; for (int i = 0; i < these.length; i++) { switch (those[i]) { @@ -1404,8 +1423,12 @@ public class Type implements Modifiers, Kinds, TypeTags { } break; default: - if (these[i].isCovarType() || !these[i].isSameAs(those[i])) - return false; + if (these[i].isCovarType()) return false; + if ((tparams[i].flags & COVARIANT) != 0) { + if (!these[i].isSubType(those[i])) return false; + } else { + if (!these[i].isSameAs(those[i])) return false; + } } } return true; @@ -1811,7 +1834,8 @@ public class Type implements Modifiers, Kinds, TypeTags { static Type arglub(Type[] types) { Type pre = types[0].prefix(); Symbol sym = types[0].symbol(); - Type[] args = new Type[sym.typeParams().length]; + Symbol[] tparams = sym.typeParams(); + Type[] args = new Type[tparams.length]; Type[][] argss = new Type[args.length][types.length]; for (int i = 0; i < types.length; i++) { switch (types[i]) { @@ -1828,9 +1852,15 @@ public class Type implements Modifiers, Kinds, TypeTags { } } for (int j = 0; j < args.length; j++) { - args[j] = commonType(argss[j]); - if (args[j] == NoType) - args[j] = CovarType(lub(argss[j])); + if ((tparams[j].flags & COVARIANT) != 0) { + args[j] = commonType(argss[j]); + if (args[j] == NoType) + args[j] = lub(argss[j]); + } else { //todo: test if all same, return notype otherwise. + args[j] = commonType(argss[j]); + if (args[j] == NoType) + args[j] = CovarType(lub(argss[j])); + } } return typeRef(pre, sym, args); } @@ -1861,16 +1891,55 @@ public class Type implements Modifiers, Kinds, TypeTags { */ public static Type lub(Type[] tps) { //System.out.println("lub" + ArrayApply.toString(tps));//DEBUG + + // remove All and AllRef types + boolean all = false; + boolean allref = false; + for (int i = 0; i < tps.length; i++) { + if (!tps[i].isObjectType()) { + System.out.println("not an object type"); + return Type.NoType;//todo: change + } + all |= tps[i].symbol() == Global.instance.definitions.ALL_CLASS; + allref |= tps[i].symbol() == Global.instance.definitions.ALLREF_CLASS; + } + + if (all | allref) { + Type.List tl = Type.List.EMPTY; + for (int i = 0; i < tps.length; i++) { + if (tps[i].symbol() != Global.instance.definitions.ALL_CLASS && + tps[i].symbol() != Global.instance.definitions.ALLREF_CLASS) { + if (allref && + !tps[i].isSubType(Global.instance.definitions.ANYREF_TYPE)) + return Global.instance.definitions.ANY_TYPE; + else + tl = new Type.List(tps[i], tl); + } + } + if (tl == Type.List.EMPTY) { + return allref ? Global.instance.definitions.ALLREF_TYPE + : Global.instance.definitions.ALL_TYPE; + } + tps = tl.toArrayReverse(); + } + + // fast path if all types agree. Type lubType = commonType(tps); if (lubType != NoType) return lubType; + + // intersect closures and build frontier. Type[][] closures = new Type[tps.length][]; for (int i = 0; i < tps.length; i++) { - if (!tps[i].isObjectType()) return Type.NoType;//todo: change closures[i] = tps[i].closure(); } Type[] allBaseTypes = intersection(closures); Type[] leastBaseTypes = frontier(allBaseTypes); - if (leastBaseTypes.length == 0) return Type.NoType; + if (leastBaseTypes.length == 0) { + //System.out.println("empty intersection");//DEBUG + return Type.NoType; + } + + // add refinements where necessary Scope members = new Scope(); lubType = compoundType(leastBaseTypes, members); Type lubThisType = lubType.narrow(); @@ -1936,7 +2005,7 @@ public class Type implements Modifiers, Kinds, TypeTags { lubSym = new TermSymbol(syms[0].pos, syms[0].name, owner, 0); break; case TYPE: case ALIAS: case CLASS: - lubSym = new TypeSymbol(TYPE, syms[0].pos, syms[0].name, owner, 0); + lubSym = new AbsTypeSymbol(syms[0].pos, syms[0].name, owner, 0); break; default: throw new ApplicationError(); @@ -2022,10 +2091,9 @@ public class Type implements Modifiers, Kinds, TypeTags { Name fullname = sym.fullName(); if (fullname == Names.scala_Array && args.length == 1 /*&& args[0].unalias().symbol().kind != TYPE Q: why needed?*/) { - Global global = Global.instance; Type bound = args[0].bound(); - if (bound.symbol() != global.definitions.ANY_CLASS && - bound.symbol() != global.definitions.ANYVAL_CLASS) + if (bound.symbol() != Global.instance.definitions.ANY_CLASS && + bound.symbol() != Global.instance.definitions.ANYVAL_CLASS) { return UnboxedArrayType(args[0].erasure()); } @@ -2051,10 +2119,13 @@ public class Type implements Modifiers, Kinds, TypeTags { return pre.memberInfo(sym).erasure(); case CLASS: - if (Global.instance.definitions.UNIT_CLASS == sym) return this; - if (sym.fullName() == Names.java_lang_Object || - sym.fullName() == Names.scala_AnyRef || - sym.fullName() == Names.scala_AnyVal) + if (sym == Global.instance.definitions.UNIT_CLASS) return this; + Name fullname = sym.fullName(); + if (fullname == Names.java_lang_Object || + fullname == Names.scala_AnyRef || + fullname == Names.scala_AnyVal || + fullname == Names.scala_All || + fullname == Names.scala_AllRef) return Global.instance.definitions.ANY_TYPE; else { Type this1 = unbox(); diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java index a6ae0a9083..dba5daa3de 100644 --- a/sources/scalac/symtab/classfile/AttributeParser.java +++ b/sources/scalac/symtab/classfile/AttributeParser.java @@ -187,7 +187,7 @@ public class AttributeParser implements ClassfileConstants { } Symbol s = tvars.lookup(Name.fromString(name).toTypeName()); if (s == Symbol.NONE) { - s = new TypeSymbol(Kinds.TYPE, + s = new AbsTypeSymbol( Position.NOPOS, Name.fromString(token).toTypeName(), owner, |