summaryrefslogtreecommitdiff
path: root/sources/scalac/typechecker/Infer.java
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac/typechecker/Infer.java')
-rw-r--r--sources/scalac/typechecker/Infer.java86
1 files changed, 67 insertions, 19 deletions
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));