summaryrefslogtreecommitdiff
path: root/sources/scalac/typechecker/Analyzer.java
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac/typechecker/Analyzer.java')
-rw-r--r--sources/scalac/typechecker/Analyzer.java1088
1 files changed, 418 insertions, 670 deletions
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
index 1e8ec9daa9..c4b404cc9a 100644
--- a/sources/scalac/typechecker/Analyzer.java
+++ b/sources/scalac/typechecker/Analyzer.java
@@ -23,6 +23,8 @@ import scalac.symtab.*;
import Tree.*;
import java.util.HashMap;
+/** The main attribution phase.
+ */
public class Analyzer extends Transformer implements Modifiers, Kinds {
private final Definitions definitions;
@@ -131,39 +133,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// expressions may be packages and
// Java statics modules.
- static final int baseModes = EXPRmode | PATTERNmode | CONSTRmode;
-
-// Helper definitions ---------------------------------------------------------
+ static final int SUPERmode = 0x080; // orthogonal to above. When set
+ // we are checking a superclass
+ // constructor invocation.
- /** The qualifier type of a potential application of the `match' method.
- * or NoType, if this is something else.
- */
- private Type matchQualType(Tree fn) {
- switch (fn) {
- case Select(Tree qual, _):
- if (fn.symbol() == definitions.OBJECT_TYPE.lookup(Names.match))
- return qual.type.widen();
- break;
- case TypeApply(Tree fn1, _):
- return matchQualType(fn1);
- case Ident(_):
- if (fn.symbol() == definitions.OBJECT_TYPE.lookup(Names.match))
- return context.enclClass.owner.typeOfThis();
- break;
- }
- return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType;
- }
+ static final int baseModes = EXPRmode | PATTERNmode | CONSTRmode;
- private Type value2Type(Object value) {
- if (value instanceof Character) return definitions.CHAR_TYPE;
- else if (value instanceof Integer) return definitions.INT_TYPE;
- else if (value instanceof Long) return definitions.LONG_TYPE;
- else if (value instanceof Float) return definitions.FLOAT_TYPE;
- else if (value instanceof Double) return definitions.DOUBLE_TYPE;
- else if (value instanceof String) return definitions.JAVA_STRING_TYPE;
- else if (value instanceof Boolean) return definitions.BOOLEAN_TYPE;
- else throw new ApplicationError();
- }
+// Diagnostics ----------------------------------------------------------------
Tree errorTree(int pos) {
return make.Bad(pos).setSymbol(Symbol.ERROR).setType(Type.ErrorType);
@@ -174,14 +150,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return errorTree(pos);
}
- void explainTypes(Type found, Type required) {
- if (global.explaintypes) {
- Type.explainSwitch = true;
- found.isSubType(required);
- Type.explainSwitch = false;
- }
- }
-
void typeError(int pos, Type found, Type req) {
String msg = infer.typeErrorMsg("type mismatch", found, req);
Type foundResult = found.resultType();
@@ -266,7 +234,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
* - no conflicting modifiers
* - `abstract' modifier only for classes
* - `override' modifier never for classes
- * - def and `*' modifiers only in methods
+ * - `def' modifier never for parameters of case classes
* - declarations only in traits or abstract classes
* - symbols with `override' modifier override some other symbol.
*/
@@ -283,18 +251,23 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
if ((sym.flags & OVERRIDE) != 0 && sym.kind == CLASS) {
error(sym.pos, "`override' modifier not allowed for classes");
}
- if ((sym.flags & DEF) != 0 && sym.owner().isPrimaryConstructor()) {
- error(sym.pos, "`def' modifier not allowed for class parameters");
+ if ((sym.flags & DEF) != 0 && sym.owner().isPrimaryConstructor() &&
+ (sym.owner().primaryConstructorClass().flags & CASE) != 0) {
+ error(sym.pos, "`def' modifier not allowed for case class parameters");
}
+ /*!!!
if ((sym.flags & REPEATED) != 0 && sym.owner().isPrimaryConstructor()) {
error(sym.pos, "`*' modifier not allowed for class parameters");
}
+ */
if ((sym.flags & DEFERRED) != 0) {
if (sym.owner().kind != CLASS ||
(sym.owner().flags & MODUL) != 0 ||
sym.owner().isAnonymousClass()) {
- error(sym.pos, abstractVarNote(sym,
- "only classes can have declared but undefined members"));
+ error(sym.pos,
+ "only classes can have declared but undefined members" +
+ (((sym.flags & MUTABLE) == 0) ? ""
+ : "\n(Note that variables need to be initialized to be defined)"));
sym.flags &= ~DEFERRED;
}
}
@@ -571,206 +544,128 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
- /** Check all members of class `clazz' for overriding conditions.
- */
- void checkAllOverrides(Symbol clazz) {
- Type[] closure = clazz.closure();
- for (int i = 0; i < closure.length; i++) {
- for (Scope.SymbolIterator it = closure[i].members().iterator();
- it.hasNext();) {
- Symbol other = it.next();
- Symbol member = clazz.info().lookup(other.name);
- if (other != member && (other.flags & PRIVATE) == 0 &&
- member.kind != NONE)
- checkOverride(clazz, member, other);
- if ((member.flags & DEFERRED) != 0 &&
- clazz.kind == CLASS &&
- (clazz.flags & ABSTRACTCLASS) == 0) {
- if (clazz.isAnonymousClass())
- error(clazz.pos, "object creation impossible, since " +
- member + member.locationString() + " is not defined");
- else
- error(clazz.pos,
- clazz + abstractVarNote(
- member, " needs to be abstract; it does not define " +
- member + member.locationString()));
- clazz.flags |= ABSTRACTCLASS;
- }
- }
- }
- }
-
- /** Check that all conditions for overriding `other' by `member' are met.
+ /** Check that all subtrees have their types defined.
+ * Used for asserting an internal invariant
*/
- void checkOverride(Symbol clazz, Symbol member, Symbol other) {
- int pos;
- if (member.owner() == clazz) pos = member.pos;
- else if (!member.owner().isSubClass(other.owner())) pos = context.tree.pos;
- else return; // everything was already checked elsewhere
-
- if ((member.flags & PRIVATE) != 0) {
- overrideError(pos, member, other, "has weaker access privileges; it should not be private");
- } else if ((member.flags & PROTECTED) != 0 && (other.flags & PROTECTED) == 0) {
- overrideError(pos, member, other, "has weaker access privileges; it should not be protected");
- } else if ((other.flags & FINAL) != 0) {
- overrideError(pos, member, other, "cannot override final member");
- } else if ((other.flags & DEFERRED) == 0 && ((member.flags & OVERRIDE) == 0)) {
- overrideError(pos, member, other, "needs `override' modifier");
- } else if (other.isStable() && !member.isStable()) {
- overrideError(pos, member, other, "needs to be an immutable value");
- } else {
- Type self = clazz.thisType();
- switch (other.kind) {
- case CLASS:
- overrideError(pos, member, other, "cannot override a class");
- break;
- case ALIAS:
- if (!self.memberType(member).isSameAs(self.memberType(other)))
- overrideTypeError(pos, member, other, self, false);
- break;
- default:
- if (other.isConstructor())
- overrideError(pos, member, other,
- "cannot override a class constructor");
- Type selftype = normalizedInfo(self, member);
- Type othertype = normalizedInfo(self, other);
- if (!selftype.isSubType(othertype))
- overrideTypeError(pos, member, other, self, false);
- if (member.kind == TYPE &&
- !self.memberLoBound(other).isSubType(
- self.memberLoBound(member)))
- overrideTypeError(pos, member, other, self, true);
-
- }
+ private static class CheckDefined extends Traverser {
+ Tree all;
+ public void traverse(Tree tree) {
+ assert tree.type != null : tree + " in " + all;
+ if (tree.type != Type.ErrorType)
+ super.traverse(tree);
}
}
- void overrideError(int pos, Symbol member, Symbol other, String msg) {
- if (other.type() != Type.ErrorType && member.type() != Type.ErrorType)
- error(pos,
- "error overriding " + other + other.locationString() +
- ";\n " + member + member.locationString() + " " + msg);
- }
-
- void overrideTypeError(int pos, Symbol member, Symbol other, Type site,
- boolean lobound) {
- if (other.type() != Type.ErrorType && member.type() != Type.ErrorType) {
- Type memberInfo = lobound ? site.memberLoBound(member)
- : normalizedInfo(site, member);
- Type otherInfo = lobound ? site.memberLoBound(other)
- : normalizedInfo(site, other);
- error(pos,
- member + member.locationString() +
- infoString(member, memberInfo, lobound) +
- "\n cannot override " + other + other.locationString() +
- infoString(other, otherInfo, lobound));
- explainTypes(memberInfo, otherInfo);
- }
- }
+ private static CheckDefined checkDefined = new CheckDefined();
- Type normalizedInfo(Type site, Symbol sym) {
- Type tp = site.memberInfo(sym);
- if (sym.kind == VAL && (sym.flags & STABLE) != 0) tp = tp.resultType();
- return tp;
- }
+// Helper definitions for calculating types -----------------------------------------
- String infoString(Symbol sym, Type symtype, boolean lobound) {
- switch (sym.kind) {
- case ALIAS: return ", which equals " + symtype;
- case TYPE: return " bounded" + (lobound ? " from below" : "") + " by " + symtype;
- case VAL: return " of type " + symtype;
- default: return "";
+ /** The qualifier type of a potential application of the `match' method.
+ * or NoType, if this is something else.
+ */
+ private Type matchQualType(Tree fn) {
+ switch (fn) {
+ case Select(Tree qual, _):
+ if (fn.symbol() == definitions.OBJECT_TYPE.lookup(Names.match))
+ return qual.type.widen();
+ break;
+ case TypeApply(Tree fn1, _):
+ return matchQualType(fn1);
+ case Ident(_):
+ if (fn.symbol() == definitions.OBJECT_TYPE.lookup(Names.match))
+ return context.enclClass.owner.typeOfThis();
+ break;
}
+ return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType;
}
- String abstractVarNote(Symbol member, String msg) {
- String note = ((member.flags & MUTABLE) == 0) ? ""
- : "\n(Note that variables need to be initialized to be defined)";
- return msg + note;
+ private Type value2Type(Object value) {
+ if (value instanceof Character) return definitions.CHAR_TYPE;
+ else if (value instanceof Integer) return definitions.INT_TYPE;
+ else if (value instanceof Long) return definitions.LONG_TYPE;
+ else if (value instanceof Float) return definitions.FLOAT_TYPE;
+ else if (value instanceof Double) return definitions.DOUBLE_TYPE;
+ else if (value instanceof String) return definitions.JAVA_STRING_TYPE;
+ else if (value instanceof Boolean) return definitions.BOOLEAN_TYPE;
+ else throw new ApplicationError();
}
-// Variance Checking --------------------------------------------------------
-
- private final int
- ContraVariance = -1,
- NoVariance = 0,
- CoVariance = 1,
- AnyVariance = 2;
+// Contexts -------------------------------------------------------------------
- private String varianceString(int variance) {
- if (variance == 1) return "covariant";
- else if (variance == -1) return "contravariant";
- else return "invariant";
+ /** Push new context associated with given tree, owner, and scope on stack.
+ * Fields `imports' and, possibly, `enclClass' are inherited from parent.
+ */
+ void pushContext(Tree tree, Symbol owner, Scope scope) {
+ context = new Context(tree, owner, scope, context);
}
- /** The variance of symbol `base' relative to the class which defines `tvar'.
+ /** Pop context from stack.
*/
- int flip(Symbol base, Symbol tvar) {
- Symbol clazz = tvar.owner().primaryConstructorClass();
- 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;
- sym = sym.owner();
- }
- return flip;
+ void popContext() {
+ context = context.outer;
}
- /** Check variance of type variables in this type
+// Lazy Types ------------------------------------------------------------------
+
+ /** A lazy type which, when forced returns the type of a symbol defined
+ * in `tree'.
*/
- void validateVariance(Symbol base, Type tp, int variance) {
- validateVariance(base, tp, tp, variance);
+ class LazyTreeType extends Type.LazyType {
+ Tree tree;
+ Unit u;
+ Context c;
+
+ LazyTreeType(Tree tree) {
+ this.tree = tree;
+ this.u = unit;
+ this.c = context;
+ }
+ public void complete(Symbol sym) {
+ //System.out.println("completing " + sym);//DEBUG
+ //if (sym.isConstructor()) sym.constructorClass().initialize();
+ //else if (sym.isModule()) sym.moduleClass().initialize();
+ defineSym(tree, u, c);
+ }
}
- void validateVariance(Symbol base, Type all, Type tp, int variance) {
- switch (tp) {
- case ErrorType:
- case AnyType:
- case NoType:
- case ThisType(Symbol sym):
- break;
- case SingleType(Type pre, Symbol sym):
- validateVariance(base, all, pre, variance);
- break;
- case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym.variance() != 0) {
- int f = flip(base, sym);
- if (f != AnyVariance && sym.variance() != f * variance) {
- //System.out.println("flip(" + base + "," + sym + ") = " + f);//DEBUG
- error(base.pos,
- varianceString(sym.variance()) + " " + sym +
- " occurs in " + varianceString(f * variance) +
- " position in type " + all + " of " + base);
+ /** A lazy type for case constructor methods (whose name is a term name)
+ * which sets the method's type to the class constructor type.
+ */
+ class LazyConstrMethodType extends LazyTreeType {
+ LazyConstrMethodType(Tree tree) {
+ super(tree);
+ }
+ public void complete(Symbol sym) {
+ Type constrtype = tree.symbol().constructor().type().instanceType();
+ switch (tree) {
+ case ClassDef(_, _, _, ValDef[][] vparams, _, _):
+ if (vparams.length == 0) {
+ constrtype = removeMethod(constrtype);
}
}
- validateVariance(base, all, pre, variance);
- validateVariance(base, all, args, variance, sym.typeParams());
- break;
- case CompoundType(Type[] parts, Scope members):
- validateVariance(base, all, parts, variance);
- break;
- case MethodType(Symbol[] vparams, Type result):
- validateVariance(base, all, result, variance);
- break;
- case PolyType(Symbol[] tparams, Type result):
- validateVariance(base, all, result, variance);
- break;
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- validateVariance(base, all, alttypes, variance);
+ sym.setInfo(constrtype);
+ }
+ private Type removeMethod(Type tp) {
+ switch (tp) {
+ case MethodType(_, Type restp):
+ return restp;
+ case PolyType(Symbol[] tparams, Type restp):
+ return Type.PolyType(tparams, removeMethod(restp));
+ default:
+ return tp;
+ }
}
}
- void validateVariance(Symbol base, Type all, Type[] tps, int variance) {
- for (int i = 0; i < tps.length; i++)
- validateVariance(base, all, tps[i], variance);
- }
-
- 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());
+ /** A lazy type for self types
+ */
+ class LazySelfType extends LazyTreeType {
+ LazySelfType(Tree tree) {
+ super(tree);
+ }
+ public void complete(Symbol sym) {
+ defineSelfType(sym, tree, u, c);
+ }
}
// Entering Symbols ----------------------------------------------------------
@@ -966,6 +861,42 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
enterSym(stats[i]);
}
+ Symbol[] enterParams(Tree[] params) {
+ for (int i = 0; i < params.length; i++) {
+ enterSym(params[i]);
+ switch (params[i]) {
+ case ValDef(int mods, _, _, _):
+ if ((mods & REPEATED) != 0 && params.length > 1)
+ error(params[i].pos,
+ "`*' parameter must be the only parameter of a `('...`)' section");
+ }
+ }
+ return Tree.symbolOf(params);
+ }
+
+ Symbol[][] enterParams(Tree[][] vparams) {
+ Symbol[][] vparamSyms = new Symbol[vparams.length][];
+ for (int i = 0; i < vparams.length; i++) {
+ vparamSyms[i] = enterParams(vparams[i]);
+ }
+ return vparamSyms;
+ }
+
+ /** Re-enter type parameters in current scope.
+ */
+ void reenterParams(Tree[] params) {
+ for (int i = 0; i < params.length; i++) {
+ context.scope.enter(params[i].symbol());
+ }
+ }
+
+ /** Re-enter value parameters in current scope.
+ */
+ void reenterParams(Tree[][] vparams) {
+ for (int i = 0; i < vparams.length; i++)
+ reenterParams(vparams[i]);
+ }
+
// Definining Symbols -------------------------------------------------------
/** Define symbol associated with `tree' using given `unit' and `context'.
@@ -986,12 +917,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Type owntype;
switch (tree) {
case ClassDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
- // todo: check why this is necessary
- if ((mods & LOCKED) != 0 && !sym.isAnonymousClass()) {
- sym.setInfo(Type.ErrorType);
- throw new CyclicReference(sym, Type.NoType);
- }
- ((ClassDef) tree).mods |= LOCKED;
pushContext(tree, sym.constructor(), new Scope(context.scope));
Symbol[] tparamSyms = enterParams(tparams);
Symbol[][] vparamSyms = enterParams(vparams);
@@ -1021,12 +946,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Symbol clazz = sym.moduleClass();
defineTemplate(templ, clazz);
clazz.setInfo(templ.type);
- if (tpe == Tree.Empty) owntype = clazz.type();
- else owntype = transform(tpe, TYPEmode).type;
+ ((ModuleDef) tree).tpe = tpe = transform(tpe, TYPEmode);
+ owntype = (tpe == Tree.Empty) ? clazz.type() : tpe.type;
break;
case ValDef(int mods, Name name, Tree tpe, Tree rhs):
- if (tpe == Tree.Empty) {
+ if (tpe != Tree.Empty) {
+ ((ValDef) tree).tpe = tpe = transform(tpe, TYPEmode);
+ } else {
pushContext(tree, sym, context.scope);
if (rhs == Tree.Empty) {
if ((sym.owner().flags & ACCESSOR) != 0) {
@@ -1039,20 +966,13 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
((ValDef) tree).tpe = tpe =
gen.mkType(tree.pos, Type.ErrorType);
}
- owntype = tpe.type;
} else {
- if ((mods & CASEACCESSOR) != 0) {
- //rhs was already attributed
- assert rhs.type != null;
- } else {
- ((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode);
- }
- owntype = rhs.type;
+ ((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode);
+ ((ValDef) tree).tpe = tpe = gen.mkType(tree.pos, rhs.type);
}
popContext();
- } else {
- owntype = transform(tpe, TYPEmode).type;
}
+ owntype = tpe.type;
checkNonCyclic(tree.pos, owntype);
break;
@@ -1060,43 +980,41 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
pushContext(tree, sym, new Scope(context.scope));
Symbol[] tparamSyms = enterParams(tparams);
Symbol[][] vparamSyms = enterParams(vparams);
- Type restpe;
- if (tpe == Tree.Empty) {
+ if (tpe != Tree.Empty) {
+ ((DefDef) tree).tpe = tpe = transform(tpe, TYPEmode);
+ } else {
int rhsmode = name.isConstrName() ? CONSTRmode : EXPRmode;
((DefDef) tree).rhs = rhs = transform(rhs, rhsmode);
- restpe = checkNoEscape(rhs.pos, rhs.type);
- } else {
- restpe = checkNoEscape(
- tpe.pos, transform(tpe, TYPEmode).type);
+ ((DefDef) tree).tpe = tpe = gen.mkType(tree.pos, rhs.type);
}
+ Type restype = checkNoEscape(tpe.pos, tpe.type);
popContext();
- checkNonCyclic(tree.pos, restpe);
- owntype = makeMethodType(tparamSyms, vparamSyms, restpe);
+ checkNonCyclic(tree.pos, restype);
+ owntype = makeMethodType(tparamSyms, vparamSyms, restype);
//System.out.println("methtype " + name + ":" + owntype);//DEBUG
break;
case TypeDef(int mods, Name name, Tree rhs, Tree lobound):
if (sym.kind == TYPE) {
- //can't have `sym' as onwer since checkNonCyclic would fail.
- pushContext(rhs, context.owner, context.scope);
- context.delayArgs = true;
- owntype = transform(rhs, TYPEmode).type;
- sym.setLoBound(transform(lobound, TYPEmode).type);
- owntype.symbol().initialize();//to detect cycles
- popContext();
+ //can't have `sym' as owner since checkNonCyclic would fail.
+ ((TypeDef) tree).rhs = rhs = transform(rhs, TYPEmode);
+ ((TypeDef) tree).lobound = lobound = transform(lobound, TYPEmode);
+ owntype = rhs.type;
+ sym.setLoBound(lobound.type);
+ owntype.symbol().initialize();//to detect cycles todo: needed?
} else { // sym.kind == ALIAS
pushContext(tree, sym, context.scope);
- owntype = transform(rhs, TYPEmode | FUNmode).type;
+ ((TypeDef) tree).rhs = rhs = transform(rhs, TYPEmode | FUNmode);
+ owntype = rhs.type;
popContext();
}
checkNonCyclic(tree.pos, owntype);
break;
case Import(Tree expr, Name[] selectors):
- Tree expr1 = transform(expr, EXPRmode | QUALmode);
- ((Import) tree).expr = expr1;
- checkStable(expr1);
- owntype = expr1.type;
+ ((Import) tree).expr = expr = transform(expr, EXPRmode | QUALmode);
+ checkStable(expr);
+ owntype = expr.type;
break;
default:
@@ -1122,13 +1040,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
*/
void defineTemplate(Tree.Template templ, Symbol clazz) {
// attribute parent constructors
- Tree[] constrs = transformConstrInvocations(
- templ.pos, templ.parents, true);
-
- Type[] parents = new Type[constrs.length];
- for (int i = 0; i < parents.length; i++) {
- parents[i] = constrs[i].type;
- }
+ Tree[] constrs = transformConstrInvocations(templ.pos, templ.parents);
+ Type[] parents = Tree.typeOf(constrs);
// enter all members
Scope members = new Scope();
@@ -1136,31 +1049,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
templ.body = desugarize.Statements(templ.body, false);
enterSyms(templ.body);
popContext();
-
templ.type = Type.compoundType(parents, members, clazz);
}
- Symbol[] enterParams(Tree[] params) {
- for (int i = 0; i < params.length; i++) {
- enterSym(params[i]);
- switch (params[i]) {
- case ValDef(int mods, _, _, _):
- if ((mods & REPEATED) != 0 && params.length > 1)
- error(params[i].pos,
- "`*' parameter must be the only parameter of a `('...`)' section");
- }
- }
- return Tree.symbolOf(params);
- }
-
- Symbol[][] enterParams(Tree[][] vparams) {
- Symbol[][] vparamSyms = new Symbol[vparams.length][];
- for (int i = 0; i < vparams.length; i++) {
- vparamSyms[i] = enterParams(vparams[i]);
- }
- return vparamSyms;
- }
-
Type makeMethodType(Symbol[] tparams, Symbol[][] vparams, Type restpe) {
if (tparams.length == 0 && vparams.length == 0) {
return Type.PolyType(tparams, restpe);
@@ -1174,7 +1065,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
-
Tree makeStableId(int pos, Type tp) {
if (tp.symbol().isCompoundSym())
return make.This(pos, Tree.Empty).setType(tp);
@@ -1182,21 +1072,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return gen.mkStableId(pos, tp);
}
- /** Re-enter type parameters in current scope.
- */
- void reenterParams(Tree[] params) {
- for (int i = 0; i < params.length; i++) {
- context.scope.enter(params[i].symbol());
- }
- }
-
- /** Re-enter value parameters in current scope.
- */
- void reenterParams(Tree[][] vparams) {
- for (int i = 0; i < vparams.length; i++)
- reenterParams(vparams[i]);
- }
-
/** Define self type of class or module `sym'
* associated with `tree' using given `unit' and `context'.
*/
@@ -1214,6 +1089,147 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// Attribution and Transform -------------------------------------------------
+ /** Adapt tree to given mode and given prototype
+ */
+ Tree adapt(Tree tree, int mode, Type pt) {
+ //new TextTreePrinter().Print(tree).print(" adapt " + pt).println().end();//DEBUG
+ switch (tree.type) {
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ // resolve overloading
+ if ((mode & FUNmode) == 0) {
+ try {
+ infer.exprAlternative(tree, alts, alttypes, pt);
+ } catch (Type.Error ex) {
+ error(tree.pos, ex.msg);
+ }
+ switch (tree.type) {
+ case OverloadedType(_, _):
+ // overload resolution failed bcs no alternative matched prototype.
+ typeError(tree.pos, tree.type, pt);
+ tree.setSymbol(Symbol.ERROR).setType(Type.ErrorType);
+ break;
+ default:
+ return adapt(tree, mode, pt);
+ }
+ }
+ break;
+
+ case PolyType(Symbol[] tparams, Type restp):
+ // apply parameterless functions
+ // instantiate polymorphic expressions
+ if (tparams.length == 0) {
+ return adapt(tree.setType(restp), mode, pt);
+ } else if ((mode & (FUNmode | POLYmode)) == 0) {
+ try {
+ tree = infer.exprInstance(tree, tparams, restp, pt);
+ } catch (Type.Error ex) {
+ tree = error(tree.pos, ex.msg);
+ }
+ return adapt(tree, mode, pt);
+ }
+ break;
+
+ case MethodType(_, _):
+ // convert unapplied methods to functions.
+ if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
+ infer.isCompatible(tree.type, pt)) {
+ checkEtaExpandable(tree.pos, tree.type);
+ return transform(desugarize.etaExpand(tree, tree.type), mode, pt);
+ } else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
+ return error(tree.pos, "missing arguments for class constructor");
+ }
+ }
+ if ((mode & PATTERNmode) != 0) {
+ if (tree.isType()) {
+ Symbol clazz = tree.type.unalias().symbol();
+ if (clazz.isCaseClass()) {
+ // set type to instantiated case class constructor
+ tree.type = clazz.constructor().type();
+ switch (tree.type) {
+ case PolyType(Symbol[] tparams, Type restp):
+ try {
+ infer.constructorInstance(tree, tparams, restp, pt);
+ } catch (Type.Error ex) {
+ if (pt != Type.ErrorType) error(tree.pos, ex.msg);
+ return tree.setType(Type.ErrorType);
+ }
+/*
+ if (!(tree.type instanceof Type.MethodType))
+ tree = make.Apply(tree.pos, tree, Tree.EMPTY_ARRAY)
+ .setType(tree.type);
+*/
+ }
+ } else if (clazz.isSubClass(definitions.SEQ_CLASS)) {
+ // set type to instantiated sequence class constructor
+ // todo: should we admit even supertypes of the target type?
+ Type seqtp = pt.baseType(clazz);
+ if (seqtp != Type.NoType) {
+ tree.type = seqConstructorType(seqtp, pt);
+ } else {
+ error(tree.pos, "expected pattern type " + pt +
+ " does not conform to sequence " + clazz);
+ }
+ } else if (tree.type != Type.ErrorType) {
+ error(tree.pos, tree.type.symbol() +
+ " is neither a case class constructor nor a sequence class constructor");
+ }
+ }
+ if ((mode & FUNmode) != 0) {
+ return tree;
+ } else {
+ Symbol sym = tree.symbol();
+ // check that idents or selects are stable.
+ switch (tree) {
+ case Ident(_):
+ case Select(_, _):
+ checkStable(tree);
+ }
+ }
+ } else if ((mode & EXPRmode) != 0) {
+ if ((mode & FUNmode) != 0) {
+ if (tree.type.isObjectType()) {
+ // insert apply method
+ Symbol applyMeth = tree.type.lookup(Names.apply);
+ if (applyMeth != Symbol.NONE && isAccessible(applyMeth, tree)) {
+ applyMeth.flags |= (ACCESSED | SELECTOR);
+ tree = make.Select(tree.pos, tree, Names.apply)
+ .setSymbol(applyMeth)
+ .setType(tree.type.memberType(applyMeth));
+ return adapt(tree, mode, pt);
+ }
+ }
+ } else if ((mode & QUALmode) == 0) {
+ // check that packages and static modules are not used as values
+ Symbol sym = tree.symbol();
+ if (tree.isTerm() &&
+ sym != null && sym.kind != ERROR && !sym.isValue()) {
+ error(tree.pos, tree.symbol() + " is not a value");
+ }
+ }
+ }
+
+ Type owntype = tree.type;
+ if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode)) {
+ owntype = owntype.instanceType();
+ // this works as for superclass constructor calls the expected
+ // type `pt' is always AnyType (see transformConstrInvocations).
+ }
+ if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) {
+ typeError(tree.pos, owntype, pt);
+ Type.explainTypes(owntype, pt);
+ tree.type = Type.ErrorType;
+ }
+ return tree;
+ }
+ //where
+ Type seqConstructorType(Type paramtp, Type resulttp) {
+ Symbol constr = resulttp.symbol().constructor();
+ Symbol param = new TermSymbol(
+ Position.NOPOS, Names.WILDCARD, constr, PARAM | REPEATED).setInfo(
+ paramtp.baseType(definitions.SEQ_CLASS));
+ return Type.MethodType(new Symbol[]{param}, resulttp);
+ }
+
/** Attribute an identifier consisting of a simple name or an outer reference.
* @param tree The tree representing the identifier.
* @param name The name of the identifier.
@@ -1354,14 +1370,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
sym.isStable() && qual.type.isStable())
symtype = Type.singleType(qual.type, sym);
//System.out.println(qual.type + ".member: " + sym + ":" + symtype);//DEBUG
- switch (tree) {
- case Select(_, _):
- return copy.Select(tree, sym, qual).setType(symtype);
- case SelectFromType(_, _):
- return make.TypeTerm(tree.pos).setType(symtype);
- default:
- throw new ApplicationError();
- }
+ return copy.Select(tree, sym, qual).setType(symtype);
}
}
@@ -1412,7 +1421,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
Tree stat1;
int mode = TreeInfo.isDefinition(stat) ? NOmode : EXPRmode;
- if (exprOwner.kind != NONE && !TreeInfo.isOwnerDefinition(stat)) {
+ if (exprOwner.kind != NONE && !TreeInfo.isDefinition(stat)) {
pushContext(stat, exprOwner, context.scope);
stat1 = transform(stat, mode);
popContext();
@@ -1432,47 +1441,56 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** Attribute a sequence of constructor invocations.
*/
- Tree[] transformConstrInvocations(int pos, Tree[] constrs, boolean delayArgs) {
+ Tree[] transformConstrInvocations(int pos, Tree[] constrs) {
for (int i = 0; i < constrs.length; i++) {
- pushContext(constrs[i], context.owner, context.scope);
- context.delayArgs = delayArgs;
- constrs[i] = transform(constrs[i], CONSTRmode, Type.AnyType);
+ //!!!pushContext(constrs[i], context.owner, context.scope);
+ constrs[i] = transform(constrs[i], CONSTRmode | SUPERmode, Type.AnyType);
Symbol f = TreeInfo.methSymbol(constrs[i]);
if (f != null) {
Symbol c = f.primaryConstructorClass();
if (c.kind == CLASS) c.initialize();//to detect cycles
}
- popContext();
+ //!!!popContext();
}
return constrs;
}
+ void transformConstrInvocationArgs(Tree[] constrs) {
+ for (int i = 0; i < constrs.length; i++) {
+ switch (constrs[i]) {
+ case Apply(Tree fn, Tree[] args):
+ if (fn.type instanceof Type.MethodType)
+ transformArgs(
+ constrs[i].pos, TreeInfo.methSymbol(fn), Symbol.EMPTY_ARRAY,
+ fn.type, EXPRmode, args, Type.AnyType);
+ }
+ }
+ }
+
/** Attribute a template
*/
public Tree.Template transformTemplate(Tree.Template templ, Symbol owner) {
if (global.debug) global.log("transforming " + owner);//debug
//System.out.println(owner.info());//DEBUG
- Tree[] parents1 = transformConstrInvocations(
- templ.pos, templ.parents, false);
+ Tree[] parents = templ.parents;
+ transformConstrInvocationArgs(parents);
if (owner.kind != ERROR) {
- validateParentClasses(
- templ.parents, owner.info().parents(), owner.typeOfThis());
+ validateParentClasses(parents, owner.info().parents(), owner.typeOfThis());
validateBaseTypes(owner);
}
pushContext(templ, owner, owner.members());
templ.setSymbol(gen.localDummy(templ.pos, owner));
Tree[] body1 = transformStatSeq(templ.body, templ.symbol());
- checkAllOverrides(owner);
popContext();
if (owner.isTrait()) {
- for (int i = 0; i < templ.parents.length; i++) {
- checkPureConstr(parents1[i], owner);
- if (i >= 1) checkTrait(parents1[i], owner);
+ for (int i = 0; i < parents.length; i++) {
+ checkPureConstr(parents[i], owner);
+ if (i >= 1) checkTrait(parents[i], owner);
}
for (int i = 0; i < templ.body.length; i++)
checkPureDef(body1[i], owner);
}
- Tree.Template templ1 = copy.Template(templ, parents1, body1);
+ Tree.Template templ1 = copy.Template(templ, parents, body1);
templ1.setType(owner.type());
return templ1;
}
@@ -1582,142 +1600,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return tree1;
}
- Tree adapt(Tree tree, int mode, Type pt) {
- //new TextTreePrinter().print(tree).print(" adapt " + pt).println().end();//DEBUG
- switch (tree.type) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- // resolve overloading
- if ((mode & FUNmode) == 0) {
- try {
- infer.exprAlternative(tree, alts, alttypes, pt);
- } catch (Type.Error ex) {
- error(tree.pos, ex.msg);
- }
- switch (tree.type) {
- case OverloadedType(_, _):
- // overload resolution failed bcs no alternative matched prototype.
- typeError(tree.pos, tree.type, pt);
- tree.setSymbol(Symbol.ERROR).setType(Type.ErrorType);
- break;
- default:
- return adapt(tree, mode, pt);
- }
- }
- break;
-
- case PolyType(Symbol[] tparams, Type restp):
- // apply parameterless functions
- // instantiate polymorphic expressions
- if (tparams.length == 0) {
- return adapt(tree.setType(restp), mode, pt);
- } else if ((mode & (FUNmode | POLYmode)) == 0) {
- try {
- tree = infer.exprInstance(tree, tparams, restp, pt);
- } catch (Type.Error ex) {
- tree = error(tree.pos, ex.msg);
- }
- return adapt(tree, mode, pt);
- }
- break;
-
- case MethodType(_, _):
- // convert unapplied methods to functions.
- if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
- infer.isCompatible(tree.type, pt)) {
- checkEtaExpandable(tree.pos, tree.type);
- return transform(desugarize.etaExpand(tree, tree.type), mode, pt);
- } else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
- return error(tree.pos, "missing arguments for class constructor");
- }
- }
- if ((mode & PATTERNmode) != 0) {
- if (tree.isType()) {
- Symbol clazz = tree.type.unalias().symbol();
- if (clazz.isCaseClass()) {
- // set type to instantiated case class constructor
- tree.type = clazz.constructor().type();
- switch (tree.type) {
- case PolyType(Symbol[] tparams, Type restp):
- try {
- infer.constructorInstance(tree, tparams, restp, pt);
- } catch (Type.Error ex) {
- if (pt != Type.ErrorType) error(tree.pos, ex.msg);
- return tree.setType(Type.ErrorType);
- }
-/*
- if (!(tree.type instanceof Type.MethodType))
- tree = make.Apply(tree.pos, tree, Tree.EMPTY_ARRAY)
- .setType(tree.type);
-*/
- }
- } else if (clazz.isSubClass(definitions.SEQ_CLASS)) {
- // set type to instantiated sequence class constructor
- // todo: should we admit even supertypes of the target type?
- Type seqtp = pt.baseType(clazz);
- if (seqtp != Type.NoType) {
- tree.type = seqConstructorType(seqtp, pt);
- } else {
- error(tree.pos, "expected pattern type " + pt +
- " does not conform to sequence " + clazz);
- }
- } else if (tree.type != Type.ErrorType) {
- error(tree.pos, tree.type.symbol() +
- " is neither a case class constructor nor a sequence class constructor");
- }
- }
- if ((mode & FUNmode) != 0) {
- return tree;
- } else {
- Symbol sym = tree.symbol();
- // check that idents or selects are stable.
- switch (tree) {
- case Ident(_):
- case Select(_, _):
- checkStable(tree);
- }
- }
- } else if ((mode & EXPRmode) != 0) {
- if ((mode & FUNmode) != 0) {
- if (tree.type.isObjectType()) {
- // insert apply method
- Symbol applyMeth = tree.type.lookup(Names.apply);
- if (applyMeth != Symbol.NONE && isAccessible(applyMeth, tree)) {
- applyMeth.flags |= (ACCESSED | SELECTOR);
- tree = make.Select(tree.pos, tree, Names.apply)
- .setSymbol(applyMeth)
- .setType(tree.type.memberType(applyMeth));
- return adapt(tree, mode, pt);
- }
- }
- } else if ((mode & QUALmode) == 0) {
- // check that packages and static modules are not used as values
- Symbol sym = tree.symbol();
- if (sym != null && sym.kind != ERROR && !sym.isValue() &&
- tree.isTerm()) {
- error(tree.pos, tree.symbol() + " is not a value");
- }
- }
- }
-
- Type owntype = tree.type;
- if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode))
- owntype = owntype.instanceType();
- if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) {
- typeError(tree.pos, owntype, pt);
- explainTypes(owntype, pt);
- tree.type = Type.ErrorType;
- }
- return tree;
- }
- //where
- Type seqConstructorType(Type paramtp, Type resulttp) {
- Symbol constr = resulttp.symbol().constructor();
- Symbol param = new TermSymbol(
- Position.NOPOS, Names.WILDCARD, constr, PARAM | REPEATED).setInfo(
- paramtp);
- return Type.MethodType(new Symbol[]{param}, resulttp);
- }
-
/** Transform expression or type with a given mode.
*/
public Tree transform(Tree tree, int mode) {
@@ -1730,6 +1612,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
this.mode = savedMode;
if ((mode & TYPEmode) != 0) {
+ // todo: generalize to type constructors?
Symbol sym = tree1.symbol();
if ((mode & FUNmode) == 0 && sym != null && sym.typeParams().length != 0)
return error(tree.pos, sym + " takes type parameters.");
@@ -1748,7 +1631,11 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
/** The main attribution function
*/
public Tree transform(Tree tree) {
- //new TextTreePrinter().print("transforming ").print(tree).println().end();//DEBUG
+ //System.out.println("transforming " + tree);//DEBUG
+ if (tree.type != null) {
+ checkDefined.all = tree; checkDefined.traverse(tree);//debug
+ return tree;
+ }
Symbol sym = tree.symbol();
if (sym != null && !sym.isInitialized()) sym.initialize();
if (global.debug && TreeInfo.isDefinition(tree)) global.log("transforming " + sym);
@@ -1787,38 +1674,22 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Tree tpe1 = transform(tpe);
Tree.Template templ1 = transformTemplate(templ, sym);
popContext();
- validateVariance(sym, sym.info(), CoVariance);
- validateVariance(sym, sym.typeOfThis(), CoVariance);
return copy.ClassDef(tree, sym, tparams1, vparams1, tpe1, templ1)
.setType(definitions.UNIT_TYPE);
case ModuleDef(_, _, Tree tpe, Tree.Template templ):
- Tree tpe1 = transform(tpe, TYPEmode);
Tree.Template templ1 = transformTemplate(templ, sym.moduleClass());
- validateVariance(sym.moduleClass(), sym.type(), CoVariance);
- validateVariance(sym.moduleClass(), sym.moduleClass().info(), CoVariance);
- return copy.ModuleDef(tree, sym, tpe1, templ1)
+ return copy.ModuleDef(tree, sym, tpe, templ1)
.setType(definitions.UNIT_TYPE);
case ValDef(_, _, Tree tpe, Tree rhs):
- Tree tpe1 = transform(tpe, TYPEmode);
Tree rhs1 = rhs;
- if (tpe1 == Tree.Empty) {
- tpe1 = gen.mkType(rhs.pos, rhs.type);
- // rhs already attributed by defineSym in this case
- } else if (rhs != Tree.Empty) {
- if ((sym.flags & CASEACCESSOR) != 0) {
- //rhs was already attributed
- } else {
- pushContext(tree, sym, context.scope);
- rhs1 = transform(rhs, EXPRmode, sym.type());
- popContext();
- }
+ if (rhs != Tree.Empty) {
+ pushContext(tree, sym, context.scope);
+ rhs1 = transform(rhs, EXPRmode, tpe.type);
+ popContext();
}
- validateVariance(
- sym, sym.type(),
- ((sym.flags & MUTABLE) != 0) ? NoVariance : CoVariance);
- return copy.ValDef(tree, sym, tpe1, rhs1)
+ return copy.ValDef(tree, sym, tpe, rhs1)
.setType(definitions.UNIT_TYPE);
case DefDef(_, _, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
@@ -1827,34 +1698,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Tree.TypeDef[] tparams1 = transform(tparams);
reenterParams(vparams);
Tree.ValDef[][] vparams1 = transform(vparams);
- Tree tpe1 = transform(tpe, TYPEmode);
Tree rhs1 = rhs;
- if (tpe1 == Tree.Empty) {
- tpe1 = gen.mkType(rhs1.pos, rhs1.type);
- //System.out.println("infer " + sym + ":" + rhs.type);//DEBUG
- //rhs already attributed by defineSym in this case
- } else if (rhs != Tree.Empty) {
- rhs1 = transform(rhs, EXPRmode,
- tpe1.type == Type.NoType ? Type.AnyType : tpe1.type);
- }
+ if (rhs != Tree.Empty)
+ rhs1 = transform(rhs, EXPRmode, tpe.type);
popContext();
- validateVariance(sym, sym.type(), CoVariance);
- return copy.DefDef(tree, sym, tparams1, vparams1, tpe1, rhs1)
+ return copy.DefDef(tree, sym, tparams1, vparams1, tpe, rhs1)
.setType(definitions.UNIT_TYPE);
- case TypeDef(_, _, Tree rhs, Tree lobound):
- pushContext(tree, sym, new Scope(context.scope));
- int mode = TYPEmode;
- 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(), variance);
- return copy.TypeDef(tree, sym, rhs1, lobound1)
+ case TypeDef(_, _, _, _):
+ return tree
.setType(definitions.UNIT_TYPE);
case Import(Tree expr, Name[] selectors):
@@ -1869,29 +1721,33 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
context.imports = context.outer.imports;
for (int i = 0; i < stats1.length - 1; i++)
stats1[i] = transform(stats1[i], EXPRmode);
- Type tp;
+ Type owntype;
if (stats1.length > 0) {
stats1[stats1.length - 1] =
transform(stats1[stats1.length - 1], lastmode, pt);
- tp = checkNoEscape(tree.pos, stats1[stats1.length - 1].type);
+ owntype = checkNoEscape(tree.pos, stats1[stats1.length - 1].type);
} else {
- tp = definitions.UNIT_TYPE;
+ owntype = definitions.UNIT_TYPE;
}
popContext();
return copy.Block(tree, stats1)
- .setType(tp);
+ .setType(owntype);
case Visitor(Tree.CaseDef[] cases):
if (pt.symbol().isSubClass(definitions.PARTIALFUNCTION_CLASS)) {
Type pft = pt.baseType(definitions.PARTIALFUNCTION_CLASS);
Type[] pftargs = pft.typeArgs();
- if (pft.typeArgs().length == 2 && infer.isFullyDefined(pftargs[0])) {
- Type pattpe = pftargs[0];
- Type restpe = pftargs[1];
- Tree tree1 = transformVisitor(tree, pattpe, restpe);
- if (!infer.isFullyDefined(restpe)) restpe = tree1.type;
- return transform(
- desugarize.partialFunction(tree, pattpe, restpe));
+ if (pftargs.length == 2 && infer.isFullyDefined(pftargs[0])) {
+ Type pattype = pftargs[0];
+ Type restype = pftargs[1];
+ Tree isDefinedAtVisitor = transformVisitor(
+ desugarize.isDefinedAtVisitor(tree),
+ pattype, definitions.BOOLEAN_TYPE);
+ Tree applyVisitor = transformVisitor(tree, pattype, restype);
+ if (!infer.isFullyDefined(restype)) restype = applyVisitor.type;
+ return gen.mkPartialFunction(
+ tree.pos, applyVisitor, isDefinedAtVisitor,
+ pattype, restype, context.owner);
} else {
return error(tree.pos, "expected pattern type of cases could not be determined");
}
@@ -1899,7 +1755,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return transform(desugarize.Visitor(tree));
}
- case Assign(Apply(Tree funarray, Tree[] vparam), Tree rhs):
+ case Assign(Apply(_, _), _):
return transform(desugarize.Update(tree));
case Assign(Tree lhs, Tree rhs):
@@ -1917,29 +1773,27 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case If(Tree cond, Tree thenp, Tree elsep):
Tree cond1 = transform(cond, EXPRmode, definitions.BOOLEAN_TYPE);
+ Tree thenp1, elsep1;
if (elsep == Tree.Empty) {
- Tree thenp1 =
- transform(thenp, EXPRmode, definitions.UNIT_TYPE);
- Tree elsep1 = make.Block(tree.pos, Tree.EMPTY_ARRAY)
- .setType(definitions.UNIT_TYPE);
- return copy.If(tree, cond1, thenp1, elsep1)
+ thenp1 = transform(thenp, EXPRmode, definitions.UNIT_TYPE);
+ elsep1 = make.Block(tree.pos, Tree.EMPTY_ARRAY)
.setType(definitions.UNIT_TYPE);
} else {
- Tree thenp1 = transform(thenp, EXPRmode, pt);
- Tree elsep1 = transform(elsep, EXPRmode, pt);
- return copy.If(tree, cond1, thenp1, elsep1)
- .setType(Type.lub(new Type[]{thenp1.type, elsep1.type}));
+ thenp1 = transform(thenp, EXPRmode, pt);
+ elsep1 = transform(elsep, EXPRmode, pt);
}
+ return copy.If(tree, cond1, thenp1, elsep1)
+ .setType(Type.lub(new Type[]{thenp1.type, elsep1.type}));
case New(Tree.Template templ):
switch (templ) {
case Template(Tree[] parents, Tree[] body):
if (parents.length == 1 && body.length == 0) {
Tree parent1 = transform(parents[0], CONSTRmode, pt);
+ Type owntype = parent1.type;
Tree.Template templ1 = (Tree.Template)
copy.Template(templ, Symbol.NONE, new Tree[]{parent1}, body)
- .setType(parent1.type);
- Type owntype = parent1.type;
+ .setType(owntype);
checkInstantiatable(tree.pos, owntype);
return copy.New(tree, templ1)
.setType(owntype.instanceType());
@@ -1963,7 +1817,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
Type[] parentTypes = clazz.info().parents();
Scope refinement = new Scope();
Type base = Type.compoundType(parentTypes, Scope.EMPTY);
- Type tp = Type.compoundType(
+ Type owntype = Type.compoundType(
parentTypes, refinement, clazz);
Scope.SymbolIterator it = clazz.members().iterator();
while (it.hasNext()) {
@@ -1976,21 +1830,19 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
if (refinement.elems == Scope.Entry.NONE &&
parentTypes.length == 1)
- tp = parentTypes[0];
+ owntype = parentTypes[0];
else
- tp = checkNoEscape(tree.pos, tp);
-
- Tree alloc =
- gen.Typed(
- gen.New(
- gen.Apply(
- gen.mkRef(tree.pos,
- Type.localThisType, clazz.constructor()),
- Tree.EMPTY_ARRAY)),
- tp);
+ owntype = checkNoEscape(tree.pos, owntype);
+
+ Tree alloc = gen.New(
+ gen.Apply(
+ gen.mkRef(tree.pos,
+ Type.localThisType, clazz.constructor()),
+ Tree.EMPTY_ARRAY))
+ .setType(owntype);
popContext();
return make.Block(tree.pos, new Tree[]{cd, alloc})
- .setType(tp);
+ .setType(owntype);
}
default:
throw new ApplicationError();
@@ -1999,18 +1851,18 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case Typed(Tree expr, Tree tpe):
Tree tpe1 = transform(tpe, TYPEmode);
Tree expr1 = transform(expr, mode & baseModes, tpe1.type);
- return copy.Typed(tree, expr1, tpe1)
- .setType(tpe1.type);
+ return copy.Typed(tree, expr1, tpe1).setType(tpe1.type);
case Function(Tree.ValDef[] vparams, Tree body):
pushContext(tree, context.owner, new Scope(context.scope));
Type restype = desugarize.preFunction(vparams, pt);
enterParams(vparams);
+ Tree.ValDef[] vparams1 = transform(vparams);
Tree body1 = transform(body, EXPRmode, restype);
if (!infer.isFullyDefined(restype)) restype = body1.type;
popContext();
- Tree tree1 = copy.Function(tree, vparams, body1);
- return transform(desugarize.Function(tree1, restype));
+ return gen.mkFunction(
+ tree.pos, vparams1, body1, restype, context.owner);
case TypeApply(Tree fn, Tree[] args):
Tree fn1 = transform(fn, EXPRmode | FUNmode, Type.AnyType);
@@ -2030,20 +1882,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// match against arguments
switch (fn1.type) {
case PolyType(Symbol[] tparams, Type restp):
- if (tparams.length == argtypes.length) {
- int i = 0;
- while (i < tparams.length &&
- (context.delayArgs ||
- (argtypes[i].isSubType(
- tparams[i].info().subst(tparams, argtypes)) &&
- tparams[i].loBound().subst(tparams, argtypes)
- .isSubType(argtypes[i]))))
- i++;
- if (i == tparams.length) {
- return copy.TypeApply(tree, fn1, args1)
- .setType(restp.subst(tparams, argtypes));
- }
- }
+ if (tparams.length == argtypes.length)
+ return copy.TypeApply(tree, fn1, args1)
+ .setType(restp.subst(tparams, argtypes));
break;
case ErrorType:
return tree.setType(Type.ErrorType);
@@ -2110,14 +1951,10 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
}
}
- // return prematurely if delayArgs is true and no type arguments
- // need to be inferred.
- if (context.delayArgs) {
- switch (fn1.type) {
- case MethodType(_, Type restp):
- return copy.Apply(tree, fn1, args).setType(restp);
- }
- }
+ // return prematurely if function is a superclass constructor
+ // and no type arguments need to be inferred.
+ if ((mode & SUPERmode) != 0 && fn1.type instanceof Type.MethodType)
+ return copy.Apply(tree, fn1, args).setType(fn1.type.resultType());
// type arguments with formals as prototypes if they exist.
fn1.type = infer.freshInstance(fn1.type);
@@ -2150,6 +1987,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
// infer instance, and adapt arguments to instantiated formals
try {
fn1 = infer.methodInstance(fn1, tparams, restp, argtypes, pt);
+ //System.out.println(fn1 + ":" + fn1.type);//DEBUG
} catch (Type.Error ex) {
error(tree.pos, ex.msg);
}
@@ -2258,7 +2096,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
case SingletonType(Tree ref):
Tree ref1 = transform(ref, EXPRmode | QUALmode, Type.AnyType);
- return make.TypeTerm(tree.pos)
+ return copy.SingletonType(tree, ref1)
.setType(checkObjectType(tree.pos, ref1.type.resultType()));
case SelectFromType(Tree qual, Name name):
@@ -2277,9 +2115,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
enterSym(refinements[i]).flags |= OVERRIDE;
}
Tree[] refinements1 = transformStatSeq(refinements, Symbol.NONE);
- checkAllOverrides(clazz);
popContext();
- return make.TypeTerm(tree.pos)
+ return copy.CompoundType(tree, parents1, refinements1)
.setType(self);
case AppliedType(Tree tpe, Tree[] args):
@@ -2293,25 +2130,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
: Symbol.EMPTY_ARRAY;
Type owntype = Type.ErrorType;
if (tpe1.type != Type.ErrorType) {
- if (tparams.length == args.length) {
- try {
- if (!context.delayArgs)
- infer.checkBounds(tparams, argtypes, "");
- owntype = Type.appliedType(tpe1.type, argtypes);
- } catch (Type.Error ex) {
- error(tree.pos, ex.msg);
- }
- } else {
- if (tparams.length == 0)
- error(tree.pos, tpe1.type +
- " does not take type parameters");
- else
- error(tree.pos,
- "wrong number of type arguments for " +
- tpe1.type);
- }
+ if (tparams.length == args.length)
+ owntype = Type.appliedType(tpe1.type, argtypes);
+ else if (tparams.length == 0)
+ error(tree.pos, tpe1.type + " does not take type parameters");
+ else error(tree.pos, "wrong number of type arguments for " +
+ tpe1.type);
}
- return make.TypeTerm(tree.pos).setType(owntype);
+ return copy.AppliedType(tree, tpe1, args1).setType(owntype);
case FunType(_, _):
return transform(desugarize.FunType(tree));
@@ -2326,83 +2152,5 @@ public class Analyzer extends Transformer implements Modifiers, Kinds {
return tree;
}
}
-
-// Contexts -------------------------------------------------------------------
-
- /** Push new context associated with given tree, owner, and scope on stack.
- * Fields `imports' and, possibly, `enclClass' are inherited from parent.
- */
- void pushContext(Tree tree, Symbol owner, Scope scope) {
- context = new Context(tree, owner, scope, context);
- }
-
- /** Pop context from stack.
- */
- void popContext() {
- context = context.outer;
- }
-
-// Lazy Types ------------------------------------------------------------------
-
- /** A lazy type which, when forced returns the type of a symbol defined
- * in `tree'.
- */
- class LazyTreeType extends Type.LazyType {
- Tree tree;
- Unit u;
- Context c;
-
- LazyTreeType(Tree tree) {
- this.tree = tree;
- this.u = unit;
- this.c = context;
- }
- public void complete(Symbol sym) {
- //System.out.println("completing " + sym);//DEBUG
- //if (sym.isConstructor()) sym.constructorClass().initialize();
- //else if (sym.isModule()) sym.moduleClass().initialize();
- defineSym(tree, u, c);
- }
- }
-
- /** A lazy type for case constructor methods (whose name is a term name)
- * which sets the method's type to the class constructor type.
- */
- class LazyConstrMethodType extends LazyTreeType {
- LazyConstrMethodType(Tree tree) {
- super(tree);
- }
- public void complete(Symbol sym) {
- Type constrtype = tree.symbol().constructor().type().instanceType();
- switch (tree) {
- case ClassDef(_, _, _, ValDef[][] vparams, _, _):
- if (vparams.length == 0) {
- constrtype = removeMethod(constrtype);
- }
- }
- sym.setInfo(constrtype);
- }
- private Type removeMethod(Type tp) {
- switch (tp) {
- case MethodType(_, Type restp):
- return restp;
- case PolyType(Symbol[] tparams, Type restp):
- return Type.PolyType(tparams, removeMethod(restp));
- default:
- return tp;
- }
- }
- }
-
- /** A lazy type for self types
- */
- class LazySelfType extends LazyTreeType {
- LazySelfType(Tree tree) {
- super(tree);
- }
- public void complete(Symbol sym) {
- defineSelfType(sym, tree, u, c);
- }
- }
}