summaryrefslogtreecommitdiff
path: root/sources/scalac/typechecker
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac/typechecker')
-rw-r--r--sources/scalac/typechecker/Analyzer.java29
-rw-r--r--sources/scalac/typechecker/DeSugarize.java25
-rw-r--r--sources/scalac/typechecker/Infer.java82
3 files changed, 73 insertions, 63 deletions
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 5190f2da97..f4d2ed8fa0 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -213,9 +213,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// Name resolution -----------------------------------------------------------
String decode(Name name) {
- if (name.isTypeName()) return "type " + name;
- else if (name.isConstrName()) return "constructor " + name;
- else return "value " + name.toString();
+ if (name.isTypeName()) return "type " + NameTransformer.decode(name);
+ else if (name.isConstrName()) return "constructor " + NameTransformer.decode(name);
+ else return "value " + NameTransformer.decode(name);
}
/** Is `sym' accessible as a member of tree `site' in current context?
@@ -692,9 +692,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
*/
int flip(Symbol base, Symbol tvar) {
Symbol clazz = tvar.owner().primaryConstructorClass();
- Symbol sym = clazz;
+ Symbol sym = base;
int flip = CoVariance;
while (sym != clazz && flip != AnyVariance) {
+ //System.out.println("flip: " + sym + " " + sym.isParameter());//DEBUG
if (sym.isParameter()) flip = -flip;
else if (sym.owner().kind != CLASS) flip = AnyVariance;
else if (sym.kind == ALIAS) flip = NoVariance;
@@ -723,10 +724,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if (sym.variance() != 0) {
int f = flip(base, sym);
if (f != AnyVariance && sym.variance() != f * variance) {
- error(sym.pos,
+ //System.out.println("flip(" + base + "," + sym + ") = " + f);//DEBUG
+ error(base.pos,
varianceString(sym.variance()) + " " + sym +
- " occurs in " + f * variance +
- " position in type " + all);
+ " occurs in " + varianceString(f * variance) +
+ " position in type " + all + " of " + base);
}
}
validateVariance(base, all, pre, variance);
@@ -753,7 +755,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
void validateVariance(Symbol base, Type all, Type[] tps, int variance, Symbol[] tparams) {
for (int i = 0; i < tps.length; i++)
- validateVariance(base, all, tps[i], variance * tparams[i].variance());
+ if (tps[i] != tparams[i].type())
+ validateVariance(base, all, tps[i], variance * tparams[i].variance());
}
// Entering Symbols ----------------------------------------------------------
@@ -1108,8 +1111,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// enter all members
Scope members = new Scope();
pushContext(templ, clazz, members);
- if ((clazz.flags & CASE) != 0)
- templ.body = desugarize.addCaseMethods(templ.body, clazz, parents);
templ.body = desugarize.Statements(templ.body, false);
enterSyms(templ.body);
popContext();
@@ -1954,11 +1955,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case TypeDef(_, _, Tree rhs, Tree lobound):
pushContext(tree, sym, new Scope(context.scope));
int mode = TYPEmode;
- if (sym.kind == ALIAS) mode |= FUNmode;
+ int variance = CoVariance;
+ if (sym.kind == ALIAS) {
+ mode |= FUNmode;
+ variance = NoVariance;
+ }
Tree rhs1 = transform(rhs, mode);
Tree lobound1 = transform(lobound, TYPEmode);
popContext();
- validateVariance(sym, sym.info(), NoVariance);
+ validateVariance(sym, sym.info(), variance);
return copy.TypeDef(tree, sym, rhs1, lobound1)
.setType(definitions.UNIT_TYPE);
diff --git a/sources/scalac/typechecker/DeSugarize.java b/sources/scalac/typechecker/DeSugarize.java
index 07c2e4a234..fdf4b0b542 100644
--- a/sources/scalac/typechecker/DeSugarize.java
+++ b/sources/scalac/typechecker/DeSugarize.java
@@ -701,31 +701,6 @@ public class DeSugarize implements Kinds, Modifiers {
return stats.toArray();
}
- /** Does list of types inherit from class scala.Algebraic?
- */
- boolean inheritsAlgebraic(Type[] tps) {
- Type algebraic = global.definitions.getType(Names.scala_Algebraic);
- for (int i = 0; i < tps.length; i++) {
- if (tps[i].isSubType(algebraic)) return true;
- }
- return false;
- }
-
- /** Add toString, hashCode and == if class inherts from scala.Algebraic.
- */
- Tree[] addCaseMethods(Tree[] body, Symbol clazz, Type[] parents) {
- if (inheritsAlgebraic(parents)) {
- /* todo uncomment and implement
- TreeList stats = new TreeList(body);
- Symbol[] params = clazz.constructor().firstParams();
- stats.append(toStringMethod(clazz, params));
- stats.append(hashcodeMethod(clazz, params));
- stats.append(equalsMethod(clazz, params));
- */
- }
- return body;
- }
-
//debug
void print(Tree tree, String conv, Tree result) {
if (global.log()) {
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index ab8c98e544..0ccbcc1e8d 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -214,7 +214,6 @@ public class Infer implements Modifiers, Kinds {
}
}
-
/** Do type arguments `targs' conform to formal parameters `tparams'?
*/
private boolean isWithinBounds(Symbol[] tparams, Type[] targs) {
@@ -298,14 +297,47 @@ public class Infer implements Modifiers, Kinds {
private void minimizeVar(Type tp) {
switch (tp) {
case TypeVar(Type origin, Type.Constraint constr):
- if (constr.inst == Type.NoType && constr.lobounds != Type.List.EMPTY)
- constr.inst = Type.lub(constr.lobounds.toArray());
+ if (constr.inst == Type.NoType)
+ if (constr.lobounds != Type.List.EMPTY) {
+ constr.inst = Type.lub(constr.lobounds.toArray());
+ } else {
+ constr.inst = global.definitions.ALL_TYPE;
+ }
return;
default:
throw new ApplicationError();
}
}
+ private void maximizeVars(Symbol[] tparams, Type[] tvars, int i)
+ throws NoInstance {
+ if (tvars[i] != Type.NoType) {
+ 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].info();
+ boolean cyclic = false;
+ for (int j = 0; j < tvars.length; j++) {
+ if (bound.contains(tparams[j])) {
+ cyclic |= tvars[j] == Type.NoType;
+ maximizeVars(tparams, tvars, j);
+ }
+ }
+ if (!cyclic)
+ constr.hibounds = new Type.List(
+ bound.subst(tparams, tvars), constr.hibounds);
+ maximizeVar(tvar);
+ tvars[i] = ((Type.TypeVar) tvar).constr.inst;
+ }
+ if (tvars[i] == Type.AnyType) tvars[i] = definitions.ANY_TYPE;
+ }
+ }
+ }
+
private Type[] freshVars(Symbol[] tparams) {
Type[] tvars = new Type[tparams.length];
for (int i = 0; i < tvars.length; i++) {
@@ -373,7 +405,7 @@ public class Infer implements Modifiers, Kinds {
* If no maximal type variables exists that make the
* instantiated type a subtype of `pt' and `lastTry' is true, return `null'.
*/
- private Type[] instTypeArgs(Symbol[] tparams, Type restype, Type pt) {
+ private Type[] exprTypeArgs(Symbol[] tparams, Type restype, Type pt) {
Type[] tvars = freshVars(tparams);
// add all bounds except F-bounds to upper bounds of type variable.
for (int i = 0; i < tvars.length; i++) {
@@ -389,7 +421,7 @@ public class Infer implements Modifiers, Kinds {
try {
Type[] targs = new Type[tvars.length];
for (int i = 0; i < tvars.length; i++) {
- maximizeVar(tvars[i]);
+ minimizeVar(tvars[i]);
targs[i] = instantiate(tvars[i]);
}
return targs;
@@ -399,7 +431,7 @@ public class Infer implements Modifiers, Kinds {
return null;
}
- /** As before, but: don't maximize. Instead map all unistantiated
+ /** As before, but: don't minimize. Instead map all unistantiated
* type vars to AnyType.
*/
public Type[] protoTypeArgs(Symbol[] tparams, Type restype, Type pt,
@@ -556,7 +588,8 @@ public class Infer implements Modifiers, Kinds {
Type[] targs = new Type[tvars.length];
for (int i = 0; i < tvars.length; i++) {
minimizeVar(tvars[i]);
- targs[i] = (((Type.TypeVar) tvars[i]).constr.inst == Type.NoType)
+ Type instType = ((Type.TypeVar) tvars[i]).constr.inst;
+ targs[i] = (instType == Type.NoType || instType == global.definitions.ALL_TYPE)
? Type.NoType
: instantiate(tvars[i]);
}
@@ -611,9 +644,9 @@ public class Infer implements Modifiers, Kinds {
return argumentTypeInstance(tparams2, restype1, pt1, pt2);
default:
if (tparams.length != 0) {
- Type[] targs = instTypeArgs(tparams, restype, pt1);
+ Type[] targs = exprTypeArgs(tparams, restype, pt1);
if (targs == null)
- targs = instTypeArgs(tparams, restype, pt2);
+ targs = exprTypeArgs(tparams, restype, pt2);
if (targs == null)
throw new Type.Error(
typeErrorMsg(
@@ -639,7 +672,7 @@ public class Infer implements Modifiers, Kinds {
System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
return exprInstance(tree, tparams2, restype1, pt);
}
- Type[] targs = instTypeArgs(tparams, restype, pt);
+ Type[] targs = exprTypeArgs(tparams, restype, pt);
if (targs == null)
throw new Type.Error(
"polymorphic expression of type " + tree.type +
@@ -703,23 +736,20 @@ public class Infer implements Modifiers, Kinds {
Type restype1 = restype.subst(tparams, tvars);
Type ctpe1 = restype1.resultType();
if (ctpe1.isSubType(pt)) {
- Type[] targs = new Type[tparams.length];
- for (int i = 0; i < tvars.length; i++) {
- try {
- targs[i] = instantiateUpper(tvars[i], true);
- if (targs[i] == Type.AnyType)
- targs[i] = definitions.ANY_TYPE;
- } catch (NoInstance ex) {
- throw new Type.Error(
- "constructor of type " + ctpe1 +
- " can be instantiated in more than one way to expected type " +
- pt +
- "\n --- because ---\n" + ex.getMessage());
+ try {
+ for (int i = 0; i < tvars.length; i++) {
+ maximizeVars(tparams, tvars, i);
}
+ checkBounds(tparams, tvars, "inferred ");
+ tree.setType(restype.subst(tparams, tvars));
+ //System.out.println("inferred constructor type: " + tree.type);//DEBUG
+ } catch (NoInstance ex) {
+ throw new Type.Error(
+ "constructor of type " + ctpe1 +
+ " can be instantiated in more than one way to expected type " +
+ pt +
+ "\n --- because ---\n" + ex.getMessage());
}
- checkBounds(tparams, targs, "inferred ");
- tree.setType(restype.subst(tparams, targs));
- //System.out.println("inferred constructor type: " + tree.type);//DEBUG
} else {
throw new Type.Error(
typeErrorMsg(
@@ -749,7 +779,7 @@ public class Infer implements Modifiers, Kinds {
Symbol[] uninstantiated = normalizeArgs(targs, tparams);
return
isWithinBounds(tparams, targs) &&
- instTypeArgs(uninstantiated, restpe.subst(tparams, targs), pt)
+ exprTypeArgs(uninstantiated, restpe.subst(tparams, targs), pt)
!= null;
}
} catch (NoInstance ex) {