diff options
Diffstat (limited to 'sources')
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 21 | ||||
-rw-r--r-- | sources/scalac/symtab/SymbolTablePrinter.java | 12 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 60 | ||||
-rw-r--r-- | sources/scalac/transformer/Erasure.java | 2 | ||||
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 2 | ||||
-rw-r--r-- | sources/scalac/typechecker/Infer.java | 86 |
6 files changed, 143 insertions, 40 deletions
diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 1b3ee71659..4c2080fd40 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -630,7 +630,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** The low bound of this type variable */ public Type loBound() { - throw new ApplicationError("loBound inapplicable for " + this); + return Global.instance.definitions.ALL_TYPE; } /** Get this.type corresponding to this symbol @@ -719,7 +719,12 @@ public abstract class Symbol implements Modifiers, Kinds { * of `c' as indirect base class? */ public boolean isSubClass(Symbol c) { - return this == c || c.kind == Kinds.ERROR || closurePos(c) >= 0; + return this == c || + c.kind == Kinds.ERROR || + closurePos(c) >= 0 || + this == Global.instance.definitions.ALL_CLASS || + (this == Global.instance.definitions.ALLREF_CLASS && + c.isSubClass(Global.instance.definitions.ANYREF_CLASS)); } /** Get base types of this symbol */ @@ -1004,8 +1009,8 @@ public class TypeSymbol extends Symbol { /** 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 TypeSymbol(kind, pos, name, owner(), flags); + if (Global.instance.debug) System.out.println("cloning " + this + this.locationString() + " to " + other + " in phase " + Global.instance.currentPhase.name()); other.setInfo(info()); return other; } @@ -1137,8 +1142,8 @@ public class AbsTypeSymbol extends TypeSymbol { /** 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); + if (Global.instance.debug) System.out.println("cloning " + this + this.locationString() + " to " + other + " in phase " + Global.instance.currentPhase.name()); other.setInfo(info()); other.setLoBound(loBound()); return other; @@ -1287,8 +1292,12 @@ public class ClassSymbol extends TypeSymbol { /** Get type */ public Type type() { if (template == null || template.typeArgs().length != typeParams().length) { - template = Type.TypeRef( - owner().thisType(), this, type(typeParams())); + Symbol[] tparams = typeParams(); + if (tparams.length == 0) + template = typeConstructor(); + else + template = Type.TypeRef( + owner().thisType(), this, type(typeParams())); } return template; } diff --git a/sources/scalac/symtab/SymbolTablePrinter.java b/sources/scalac/symtab/SymbolTablePrinter.java index b502942224..fdfeb0d95a 100644 --- a/sources/scalac/symtab/SymbolTablePrinter.java +++ b/sources/scalac/symtab/SymbolTablePrinter.java @@ -363,7 +363,7 @@ public class SymbolTablePrinter { type = type.typeArgs()[0]; star = true; } - printType(type, inner); + printType(type, inner); if (star) print("*"); return this; } @@ -386,7 +386,9 @@ public class SymbolTablePrinter { String keyword = getSymbolKeyword(symbol); if (keyword != null) print(keyword).space(); String inner = getSymbolInnerString(symbol); - return printSymbolName(symbol).printSymbolType(symbol, inner); + return printSymbolName(symbol) + .printType(symbol.loBound(), ">:") + .printSymbolType(symbol, inner); } //######################################################################## @@ -449,7 +451,11 @@ public class SymbolTablePrinter { /** Prints the given type with the given inner string. */ public SymbolTablePrinter printType(Type type, String inner) { - return printType0(getTypeToPrintForType(type), inner); + if ("<:".equals(inner) && type.symbol() == global.definitions.ANY_CLASS || + ">:".equals(inner) && type.symbol() == global.definitions.ALL_CLASS) + return this; + else + return printType0(getTypeToPrintForType(type), inner); } public SymbolTablePrinter printType0(Type type, String inner) { switch (type) { diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 15c3d47649..28e8d14468 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -27,10 +27,14 @@ public class Type implements Modifiers, Kinds, TypeTags { public case ThisType(Symbol sym); public case TypeRef(Type pre, Symbol sym, Type[] args) { + //assert sym != Global.instance.definitions.ALL_CLASS || + // Global.instance.definitions.ALL_TYPE == null; assert pre.isLegalPrefix() || pre == ErrorType : pre + "#" + sym; } public case SingleType(Type pre, Symbol sym) { + // assert sym != Global.instance.definitions.SCALA || + // Global.instance.definitions.SCALA_TYPE == null; assert this instanceof ExtSingleType; } @@ -667,6 +671,8 @@ public class Type implements Modifiers, Kinds, TypeTags { } for (int i = 0; i < syms2.length; i++) { syms2[i].setInfo(syms1[i].info().subst(syms1, syms2)); + if (syms2[i].kind == TYPE) + syms2[i].setLoBound(syms1[i].loBound().subst(syms1, syms2)); } for (int i = 0; i < syms2.length; i++) { members2.enter(syms2[i]); @@ -701,8 +707,14 @@ public class Type implements Modifiers, Kinds, TypeTags { public Symbol map(Symbol sym) { Type tp = sym.info(); Type tp1 = apply(tp); - if (tp == tp1) return sym; - else return sym.cloneSymbol().setInfo(tp1); + Symbol sym1 = (tp == tp1) ? sym : sym.cloneSymbol().setInfo(tp1); + if (sym1.kind == TYPE) { + Type lb = sym.loBound(); + Type lb1 = apply(lb); + if (lb != lb1) + sym1 = sym1.cloneSymbol().setLoBound(lb1); + } + return sym1; } public Type[] map(Type[] tps) { @@ -740,6 +752,8 @@ public class Type implements Modifiers, Kinds, TypeTags { } for (int i = 0; i < syms1.length; i++) { syms1[i].setInfo(syms1[i].info().subst(syms, syms1)); + if (syms1[i].kind == TYPE) + syms1[i].setLoBound(syms1[i].loBound().subst(syms, syms1)); } } return syms1; @@ -940,6 +954,10 @@ public class Type implements Modifiers, Kinds, TypeTags { return tp1; } + public Type memberLoBound(Symbol sym) { + return sym.loBound().asSeenFrom(this, sym.owner()); + } + // Substitutions --------------------------------------------------------------- /** A common map superclass for symbol/symbol and type/symbol substitutions. @@ -1873,6 +1891,7 @@ public class Type implements Modifiers, Kinds, TypeTags { Symbol[] rsyms = new Symbol[tps.length]; 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; @@ -1881,17 +1900,21 @@ public class Type implements Modifiers, Kinds, TypeTags { if ((e.sym.flags & PRIVATE) == 0 && lubType.lookup(name) == e.sym) { //todo: not memberType? Type symType = lubThisType.memberInfo(e.sym); + Type symLoBound = lubThisType.memberLoBound(e.sym); int j = 0; while (j < tps.length) { rsyms[j] = tps[j].lookupNonPrivate(name); if (rsyms[j] == e.sym) break; rtps[j] = tps[j].memberType(rsyms[j]) .substThis(tps[j].symbol(), lubThisType); - if (rtps[j].isSameAs(symType)) break; + rlbs[j] = tps[j].memberLoBound(rsyms[j]) + .substThis(tps[j].symbol(), lubThisType); + if (rtps[j].isSameAs(symType) && + rlbs[j].isSameAs(symLoBound)) break; j++; } if (j == tps.length) { - Symbol lubSym = lub(rsyms, rtps, lubType.symbol()); + Symbol lubSym = lub(rsyms, rtps, rlbs, lubType.symbol()); if (lubSym.kind != NONE && !lubSym.info().isSameAs(symType)) members.enter(lubSym); } @@ -1910,7 +1933,7 @@ public class Type implements Modifiers, Kinds, TypeTags { else return NoType; } - private static Symbol lub(Symbol[] syms, Type[] tps, Symbol owner) { + 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; for (int i = 1; i < syms.length; i++) { @@ -1930,6 +1953,7 @@ public class Type implements Modifiers, Kinds, TypeTags { break; case TYPE: case ALIAS: case CLASS: lubSym = new AbsTypeSymbol(syms[0].pos, syms[0].name, owner, 0); + lubSym.setLoBound(glb(lbs)); break; default: throw new ApplicationError(); @@ -2009,7 +2033,7 @@ public class Type implements Modifiers, Kinds, TypeTags { Type lb = NoType; for (int i = 0; i < treftypes.length && - lb != Global.instance.definitions.ALL_TYPE; + lb.symbol() != Global.instance.definitions.ALL_CLASS; i++) { for (int j = 0; j < i; j++) { if (treftypes[j].symbol() == treftypes[i].symbol()) @@ -2036,33 +2060,40 @@ public class Type implements Modifiers, Kinds, TypeTags { private static boolean addMember(Scope s, Symbol sym, Type glbThisType) { Type syminfo = sym.info().substThis(sym.owner(), glbThisType); + Type symlb = sym.loBound().substThis(sym.owner(), glbThisType); Scope.Entry e = s.lookupEntry(sym.name); if (e == Scope.Entry.NONE) { Symbol sym1 = sym.cloneSymbol(); sym1.setOwner(glbThisType.symbol()); sym1.setInfo(syminfo); + if (sym1.kind == TYPE) sym1.setLoBound(symlb); s.enter(sym1); - return true; } else { Type einfo = e.sym.info(); if (einfo.isSameAs(syminfo)) { - return true; } else if (einfo.isSubType(syminfo) && sym.kind != ALIAS) { - return true; } else if (syminfo.isSubType(einfo) && e.sym.kind != ALIAS) { e.sym.setInfo(syminfo); - return true; } else if (sym.kind == VAL && e.sym.kind == VAL || sym.kind == TYPE && e.sym.kind == TYPE) { e.sym.setInfo(glb(new Type[]{einfo, syminfo})); - return true; } else { return false; } + if (e.sym.kind == TYPE && sym.kind == TYPE) { + Type elb = e.sym.loBound(); + if (elb.isSameAs(symlb)) { + } else if (symlb.isSubType(elb)) { + } else if (elb.isSubType(symlb)) { + e.sym.setLoBound(symlb); + } else { + e.sym.setLoBound(lub(new Type[]{elb, symlb})); + } + } } + return true; } - // Erasure -------------------------------------------------------------------------- public static Map erasureMap = new MapOnlyTypes() { @@ -2404,6 +2435,11 @@ public class Type implements Modifiers, Kinds, TypeTags { return ts; } + public String toString() { + if (this == EMPTY) return "List()"; + else return head + "::" + tail; + } + public static List EMPTY = new List(null, null); public static List append(List l, Type tp) { diff --git a/sources/scalac/transformer/Erasure.java b/sources/scalac/transformer/Erasure.java index 40e56a1580..1167a40521 100644 --- a/sources/scalac/transformer/Erasure.java +++ b/sources/scalac/transformer/Erasure.java @@ -154,6 +154,8 @@ public class Erasure extends Transformer implements Modifiers { case UnboxedArrayType(Type elemtp1): return !(elemtp1 instanceof Type.UnboxedType) && isSubType(elemtp1, elemtp2); + default: + return tp1.isSubType(tp2); } } switch (tp1) { diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 2bec0ab167..cf8accc05c 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -1835,6 +1835,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { /** The main attribution function */ public Tree transform(Tree tree) { + if ((mode & PATTERNmode) != 0) + new TextTreePrinter().print("transofrming(" + pt + ")").print(tree).println().end();//debug Symbol sym = tree.symbol(); if (sym != null && !sym.isInitialized()) sym.initialize(); if (global.debug && TreeInfo.isDefinition(tree)) global.log("transforming " + sym); diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java index 0ccbcc1e8d..c08852766d 100644 --- a/sources/scalac/typechecker/Infer.java +++ b/sources/scalac/typechecker/Infer.java @@ -299,7 +299,10 @@ public class Infer implements Modifiers, Kinds { case TypeVar(Type origin, Type.Constraint constr): if (constr.inst == Type.NoType) if (constr.lobounds != Type.List.EMPTY) { + //System.out.println("LOBOUNDS = " + constr.lobounds);//DEBUG constr.inst = Type.lub(constr.lobounds.toArray()); + //System.out.println("MIN = " + constr.inst);//DEBUG + } else { constr.inst = global.definitions.ALL_TYPE; } @@ -309,7 +312,7 @@ public class Infer implements Modifiers, Kinds { } } - private void maximizeVars(Symbol[] tparams, Type[] tvars, int i) + private void solveUpper(Symbol[] tparams, Type[] tvars, int i) throws NoInstance { if (tvars[i] != Type.NoType) { switch (tvars[i]) { @@ -322,9 +325,10 @@ public class Infer implements Modifiers, Kinds { Type bound = tparams[i].info(); boolean cyclic = false; for (int j = 0; j < tvars.length; j++) { - if (bound.contains(tparams[j])) { + if (bound.contains(tparams[j]) || + tparams[j].loBound().isSameAs(tparams[i].type())) { cyclic |= tvars[j] == Type.NoType; - maximizeVars(tparams, tvars, j); + solveUpper(tparams, tvars, j); } } if (!cyclic) @@ -338,6 +342,39 @@ public class Infer implements Modifiers, Kinds { } } + private void solveLower(Symbol[] tparams, Type[] tvars, int i) + throws NoInstance { + if (tvars[i] != Type.NoType) { + //System.out.println("solve lower " + tparams[i]);//DEBUG + switch (tvars[i]) { + case TypeVar(Type origin, Type.Constraint constr): + if (constr.inst != Type.NoType) { + constr.inst = tvars[i] = instantiate(constr.inst); + } else { + Type tvar = tvars[i]; + tvars[i] = Type.NoType; + Type bound = tparams[i].loBound(); + if (bound != Global.instance.definitions.ALL_TYPE) { + boolean cyclic = false; + for (int j = 0; j < tvars.length; j++) { + if (bound.contains(tparams[j]) || + tparams[j].info().isSameAs(tparams[i].type())) { + cyclic |= tvars[j] == Type.NoType; + solveLower(tparams, tvars, j); + } + } + assert !cyclic; + if (!cyclic) + constr.lobounds = new Type.List( + bound.subst(tparams, tvars), constr.lobounds); + } + minimizeVar(tvar); + tvars[i] = ((Type.TypeVar) tvar).constr.inst; + } + } + } + } + private Type[] freshVars(Symbol[] tparams) { Type[] tvars = new Type[tparams.length]; for (int i = 0; i < tvars.length; i++) { @@ -350,14 +387,30 @@ public class Infer implements Modifiers, Kinds { public Type apply(Type t) { switch (t) { case PolyType(Symbol[] tparams, Type restp): + Type restp1 = apply(restp); + Symbol[] tparams1 = Symbol.EMPTY_ARRAY; + Symbol[] newparams1 = Symbol.EMPTY_ARRAY; + switch (restp1) { + case PolyType(_, _): + tparams1 = restp.typeParams(); + newparams1 = restp1.typeParams(); + } Symbol[] newparams = new Symbol[tparams.length]; for (int i = 0; i < tparams.length; i++) newparams[i] = tparams[i].cloneSymbol(); - for (int i = 0; i < tparams.length; i++) + for (int i = 0; i < tparams.length; i++) { newparams[i].setInfo( - newparams[i].info().subst(tparams, newparams)); + newparams[i].info() + .subst(tparams, newparams) + .subst(tparams1, newparams1)); + newparams[i].setLoBound( + newparams[i].loBound() + .subst(tparams, newparams) + .subst(tparams1, newparams1)); + } return Type.PolyType( - newparams, apply(restp).subst(tparams, newparams)); + newparams, restp1.subst(tparams, newparams)); + case OverloadedType(_, _): return map(t); default: @@ -392,7 +445,7 @@ public class Infer implements Modifiers, Kinds { private Symbol[] normalizeArgs(Type[] targs, Symbol[] tparams) { Type.List uninstantiated = Type.List.EMPTY; for (int i = 0; i < targs.length; i++) { - if (targs[i] == Type.NoType) { + if (targs[i] == Global.instance.definitions.ALL_TYPE) { targs[i] = tparams[i].type(); uninstantiated = Type.List.append(uninstantiated, targs[i]); } @@ -421,10 +474,9 @@ public class Infer implements Modifiers, Kinds { try { Type[] targs = new Type[tvars.length]; for (int i = 0; i < tvars.length; i++) { - minimizeVar(tvars[i]); - targs[i] = instantiate(tvars[i]); + solveLower(tparams, tvars, i); } - return targs; + return tvars; } catch (NoInstance ex) { } } @@ -537,7 +589,7 @@ public class Infer implements Modifiers, Kinds { * argument types, result type and expected result type. * If this is not possible, throw a `NoInstance' exception, or, if * `needToSucceed' is false alternatively return `null'. - * Undetermined type arguments are represented by `NoType'. + * Undetermined type arguments are represented by `definitions.ALL_TYPE'. * No check that inferred parameters conform to their bounds is made here. */ private Type[] methTypeArgs(Symbol[] tparams, @@ -587,14 +639,10 @@ public class Infer implements Modifiers, Kinds { } Type[] targs = new Type[tvars.length]; for (int i = 0; i < tvars.length; i++) { - minimizeVar(tvars[i]); - Type instType = ((Type.TypeVar) tvars[i]).constr.inst; - targs[i] = (instType == Type.NoType || instType == global.definitions.ALL_TYPE) - ? Type.NoType - : instantiate(tvars[i]); + solveLower(tparams, tvars, i); } - //System.out.println(" = " + ArrayApply.toString(targs));//DEBUG - return targs; + //System.out.println(" = " + ArrayApply.toString(tvars));//DEBUG + return tvars; } /** Create and attribute type application node. Pass arguments for that @@ -738,7 +786,7 @@ public class Infer implements Modifiers, Kinds { if (ctpe1.isSubType(pt)) { try { for (int i = 0; i < tvars.length; i++) { - maximizeVars(tparams, tvars, i); + solveUpper(tparams, tvars, i); } checkBounds(tparams, tvars, "inferred "); tree.setType(restype.subst(tparams, tvars)); |