summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-05-21 15:53:09 +0000
committerMartin Odersky <odersky@gmail.com>2003-05-21 15:53:09 +0000
commit2cc25288dd36b43c66ee4448856851ede5e8d6b2 (patch)
tree2511e78517123c3db740fe7dba7886ac1be0d488 /sources
parent22d0a607cd8cc270f66657c2ad3b71d1ecb77698 (diff)
downloadscala-2cc25288dd36b43c66ee4448856851ede5e8d6b2.tar.gz
scala-2cc25288dd36b43c66ee4448856851ede5e8d6b2.tar.bz2
scala-2cc25288dd36b43c66ee4448856851ede5e8d6b2.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scalac/symtab/Symbol.java21
-rw-r--r--sources/scalac/symtab/SymbolTablePrinter.java12
-rw-r--r--sources/scalac/symtab/Type.java60
-rw-r--r--sources/scalac/transformer/Erasure.java2
-rw-r--r--sources/scalac/typechecker/Analyzer.java2
-rw-r--r--sources/scalac/typechecker/Infer.java86
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));