summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-05-25 16:29:18 +0000
committerMartin Odersky <odersky@gmail.com>2005-05-25 16:29:18 +0000
commitb5c59169585faf8c352ed105db969e8deb590cf7 (patch)
tree0672dc159471047b9d55e38af31a976845a674fa /sources/scala/tools/nsc/typechecker/Typers.scala
parent6e45b64b7c55dd92da686418f65e1a415c346bf7 (diff)
downloadscala-b5c59169585faf8c352ed105db969e8deb590cf7.tar.gz
scala-b5c59169585faf8c352ed105db969e8deb590cf7.tar.bz2
scala-b5c59169585faf8c352ed105db969e8deb590cf7.zip
a
Diffstat (limited to 'sources/scala/tools/nsc/typechecker/Typers.scala')
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala446
1 files changed, 239 insertions, 207 deletions
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 559d5c83be..a413a75476 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -24,7 +24,7 @@ abstract class Typers: Analyzer {
def name = "typer";
val global: Typers.this.global.type = Typers.this.global;
def apply(unit: CompilationUnit): unit =
- unit.body = newTyper(startContext.make(unit)).transformExpr(unit.body)
+ unit.body = newTyper(startContext.make(unit)).typed(unit.body)
}
def newTyper(context: Context): Typer = new Typer(context);
@@ -60,34 +60,34 @@ abstract class Typers: Analyzer {
namerCache
}
- var context = context0;
+ private var context = context0;
/** Mode constants
- */
- private val NOmode = 0x000;
- private val EXPRmode = 0x001; // these 3 modes are mutually exclusive.
- private val PATTERNmode = 0x002;
- private val TYPEmode = 0x004;
+ */
+ val NOmode = 0x000;
+ val EXPRmode = 0x001; // these 3 modes are mutually exclusive.
+ val PATTERNmode = 0x002;
+ val TYPEmode = 0x004;
- private val INCONSTRmode = 0x008; // orthogonal to above. When set we are
- // in the body of a constructor
+ val INCONSTRmode = 0x008; // orthogonal to above. When set we are
+ // in the body of a constructor
- private val FUNmode = 0x10; // orthogonal to above. When set
- // we are looking for a method or constructor
+ val FUNmode = 0x10; // orthogonal to above. When set
+ // we are looking for a method or constructor
- private val POLYmode = 0x020; // orthogonal to above. When set
- // expression types can be polymorphic.
+ val POLYmode = 0x020; // orthogonal to above. When set
+ // expression types can be polymorphic.
- private val QUALmode = 0x040; // orthogonal to above. When set
- // expressions may be packages and
- // Java statics modules.
+ val QUALmode = 0x040; // orthogonal to above. When set
+ // expressions may be packages and
+ // Java statics modules.
- private val TAPPmode = 0x080; // Set for the function/type constructor part
- // of a type application. When set we do not
- // decompose PolyTypes.
+ val TAPPmode = 0x080; // Set for the function/type constructor part
+ // of a type application. When set we do not
+ // decompose PolyTypes.
- private val SUPERCONSTRmode = 0x100;// Set for the `super' in a superclass constructor call
- // super.<init>
+ val SUPERCONSTRmode = 0x100; // Set for the `super' in a superclass constructor call
+ // super.<init>
private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode;
@@ -234,10 +234,8 @@ abstract class Typers: Analyzer {
*/
// def adapt(tree: Tree, mode: int, pt: Type): Tree = {
private def adapt(tree: Tree, mode: int, pt: Type): Tree = tree.tpe match {
- case ConstantType(base, value) if (constfold.fold(tree, value) != tree) => // (0)
- adapt(constfold.fold(tree, value), mode, pt)
- case PolyType(List(), restp @ ConstantType(base, value)) => // (0)
- adapt(constfold.fold(tree, value), mode, pt)
+ case ct @ ConstantType(base, value) if (ct <:< pt) => // (0)
+ copy.Literal(tree, value)
case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1)
inferExprAlternative(tree, pt);
adapt(tree, mode, pt)
@@ -255,11 +253,11 @@ abstract class Typers: Analyzer {
context.undetparams = context.undetparams ::: tparams1;
adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt)
case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode) => // (4.1)
- transform(applyImplicitArgs(tree), mode, pt)
+ typed(applyImplicitArgs(tree), mode, pt)
case mt: MethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
isCompatible(tree.tpe, pt)) => // (4.2)
if (tree.symbol.isConstructor) errorTree(tree, "missing arguments for " + tree.symbol)
- else transform(etaExpand(tree), mode, pt)
+ else typed(etaExpand(tree), mode, pt)
case _ =>
if (tree.isType) {
val clazz = tree.tpe.symbol;
@@ -299,37 +297,34 @@ abstract class Typers: Analyzer {
} else if ((mode & (EXPRmode | FUNmode)) == (EXPRmode | FUNmode) &&
((mode & TAPPmode) == 0 || tree.tpe.typeParams.isEmpty) &&
tree.tpe.member(nme.apply).filter(m => m.tpe.paramSectionCount > 0) != NoSymbol) { // (8)
- transform(Select(tree, nme.apply) setPos tree.pos, mode, pt)
+ typed(Select(tree, nme.apply) setPos tree.pos, mode, pt)
} else if (!context.undetparams.isEmpty & (mode & POLYmode) == 0) { // (9)
val tparams = context.undetparams;
context.undetparams = List();
inferExprInstance(tree, tparams, pt);
tree
} else if (tree.tpe <:< pt) {
- tree
+ tree
} else {
val tree1 = constfold(tree, pt); // (10) (11)
- if (tree1 != tree) adapt(tree1, mode, pt);
+ if (tree1.tpe <:< pt) adapt(tree1, mode, pt)
else {
if ((mode & (EXPRmode | FUNmode)) == EXPRmode) {
- assert(pt != null);
- assert(tree1.tpe != null, tree1);
pt match {
case TypeRef(_, sym, _) =>
// note: was if (pt.symbol == UnitClass) but this leads to a potentially
// infinite expansion if pt is constant type ()
- if (sym == UnitClass && tree1.tpe <:< AnyClass.tpe) // (12)
- return transform(atPos(tree.pos)(Block(List(tree), Literal(()))), mode, pt)
+ if (sym == UnitClass && tree.tpe <:< AnyClass.tpe) // (12)
+ return typed(atPos(tree.pos)(Block(List(tree), Literal(()))), mode, pt)
case _ =>
}
if (context.reportGeneralErrors) { // (13); the condition prevents chains of views
val coercion = inferView(tree.pos, tree.tpe, pt, true);
if (coercion != EmptyTree)
- return transform(Apply(coercion, List(tree)) setPos tree.pos, mode, pt);
+ return typed(Apply(coercion, List(tree)) setPos tree.pos, mode, pt);
}
}
System.out.println(tree);
- System.out.println(constfold(tree));
typeErrorTree(tree, tree.tpe, pt)
}
}
@@ -343,18 +338,18 @@ abstract class Typers: Analyzer {
namer.enterValueParams(context.owner, vparamss);
val newTree = New(supertpt) setType
PolyType(tparams, appliedType(supertpt.tpe, tparams map (.tpe)));
- val tree = transformExpr(atPos(supertpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)));
+ val tree = typed(atPos(supertpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)));
if (settings.debug.value) System.out.println("superconstr " + tree + " co = " + context.owner);//debug
tree.tpe
}
def parentTypes(templ: Template): List[Tree] = {
- var supertpt = transform(templ.parents.head, TYPEmode | FUNmode, WildcardType);
- var mixins = templ.parents.tail map transformType;
+ var supertpt = typedTypeConstructor(templ.parents.head);
+ var mixins = templ.parents.tail map typedType;
// If first parent is trait, make it first mixin and add its superclass as first parent
- if (supertpt.tpe.symbol != null && supertpt.tpe.symbol.initialize.isTrait) {
- mixins = transformType(supertpt) :: mixins;
- supertpt = gen.TypeTree(supertpt.tpe.parents.head) setPos supertpt.pos;
+ while (supertpt.tpe.symbol != null && supertpt.tpe.symbol.initialize.isTrait) {
+ mixins = typedType(supertpt) :: mixins;
+ supertpt = TypeTree(supertpt.tpe.parents.head) setPos supertpt.pos;
}
if (supertpt.hasSymbol) {
val tparams = supertpt.symbol.typeParams;
@@ -362,7 +357,7 @@ abstract class Typers: Analyzer {
val constr @ DefDef(_, _, _, vparamss, _, Apply(_, superargs)) =
treeInfo.firstConstructor(templ.body);
val outercontext = context.outer.outer;
- supertpt = gen.TypeTree(
+ supertpt = TypeTree(
newTyper(context.outer.outer.makeNewScope(constr, context.outer.outer.owner))
.completeSuperType(
supertpt,
@@ -426,20 +421,20 @@ abstract class Typers: Analyzer {
}
}
- def transformClassDef(cdef: ClassDef): Tree = {
+ def typedClassDef(cdef: ClassDef): Tree = {
val clazz = cdef.symbol;
reenterTypeParams(cdef.tparams);
- val tparams1 = List.mapConserve(cdef.tparams)(transformAbsTypeDef);
- val tpt1 = checkNoEscaping.privates(clazz.thisSym, transformType(cdef.tpt));
+ val tparams1 = List.mapConserve(cdef.tparams)(typedAbsTypeDef);
+ val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(cdef.tpt));
val impl1 = newTyper(context.make(cdef.impl, clazz, new Scope()))
- .transformTemplate(cdef.impl);
+ .typedTemplate(cdef.impl);
copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl1) setType NoType
}
- def transformModuleDef(mdef: ModuleDef): Tree = {
+ def typedModuleDef(mdef: ModuleDef): Tree = {
val clazz = mdef.symbol.moduleClass;
val impl1 = newTyper(context.make(mdef.impl, clazz, new Scope()))
- .transformTemplate(mdef.impl);
+ .typedTemplate(mdef.impl);
copy.ModuleDef(mdef, mdef.mods, mdef.name, impl1) setType NoType
}
@@ -450,7 +445,7 @@ abstract class Typers: Analyzer {
val sym = vdef.symbol;
val getter = sym.owner.info.decls.lookup(name).suchThat(.hasFlag(ACCESSOR));
val result = atPos(vdef.pos)(
- gen.DefDef(getter, vparamss =>
+ DefDef(getter, vparamss =>
if ((mods & DEFERRED) != 0) EmptyTree
else stabilize(gen.mkRef(sym), sym.owner.thisType, EXPRmode, sym.tpe)));
checkNoEscaping.privates(result.symbol, result.tpt);
@@ -460,9 +455,9 @@ abstract class Typers: Analyzer {
val sym = vdef.symbol;
val setter = sym.owner.info.decls.lookup(nme.SETTER_NAME(name)).suchThat(.hasFlag(ACCESSOR));
atPos(vdef.pos)(
- gen.DefDef(setter, vparamss =>
+ DefDef(setter, vparamss =>
if ((mods & DEFERRED) != 0) EmptyTree
- else transformExpr(Assign(gen.mkRef(getter.symbol), gen.mkRef(vparamss.head.head)))))
+ else typed(Assign(gen.mkRef(getter.symbol), gen.mkRef(vparamss.head.head)))))
}
val gs = if ((mods & MUTABLE) != 0) List(getter, setter) else List(getter);
if ((mods & DEFERRED) != 0) gs else vdef :: gs
@@ -474,7 +469,7 @@ abstract class Typers: Analyzer {
List(stat)
}
- def transformTemplate(templ: Template): Template = {
+ def typedTemplate(templ: Template): Template = {
if (templ.symbol == NoSymbol)
templ setSymbol context.owner.newLocalDummy(templ.pos);
val parents1 = parentTypes(templ);
@@ -484,27 +479,27 @@ abstract class Typers: Analyzer {
else context.owner.typeOfThis;
validateParentClasses(parents1, selfType);
val body1 = templ.body flatMap addGetterSetter;
- val body2 = transformStats(body1, templ.symbol);
+ val body2 = typedStats(body1, templ.symbol);
copy.Template(templ, parents1, body2) setType context.owner.tpe
}
- def transformValDef(vdef: ValDef): ValDef = {
+ def typedValDef(vdef: ValDef): ValDef = {
val sym = vdef.symbol;
- var tpt1 = checkNoEscaping.privates(sym, transformType(vdef.tpt));
+ var tpt1 = checkNoEscaping.privates(sym, typedType(vdef.tpt));
val rhs1 =
if (vdef.rhs.isEmpty) vdef.rhs
- else newTyper(context.make(vdef, sym)).transform(vdef.rhs, EXPRmode, tpt1.tpe);
+ else newTyper(context.make(vdef, sym)).typed(vdef.rhs, tpt1.tpe);
copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, rhs1) setType NoType
}
- def transformDefDef(ddef: DefDef): DefDef = {
+ def typedDefDef(ddef: DefDef): DefDef = {
val meth = ddef.symbol;
reenterTypeParams(ddef.tparams);
reenterValueParams(ddef.vparamss);
- val tparams1 = List.mapConserve(ddef.tparams)(transformAbsTypeDef);
+ val tparams1 = List.mapConserve(ddef.tparams)(typedAbsTypeDef);
val vparamss1 = List.mapConserve(ddef.vparamss)(vparams1 =>
- List.mapConserve(vparams1)(transformValDef));
- var tpt1 = checkNoEscaping.privates(meth, transformType(ddef.tpt));
+ List.mapConserve(vparams1)(typedValDef));
+ var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt));
val rhs1 =
if (ddef.name == nme.CONSTRUCTOR) {
if (!meth.hasFlag(SYNTHETIC) &&
@@ -514,48 +509,48 @@ abstract class Typers: Analyzer {
meth.owner.isRefinementClass))
error(ddef.pos, "constructor definition not allowed here " + meth.owner);//debug
context.enclClass.owner.setFlag(INCONSTRUCTOR);
- val result = transform(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe);
+ val result = typed(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe);
context.enclClass.owner.resetFlag(INCONSTRUCTOR);
result
} else {
- transform(ddef.rhs, EXPRmode, tpt1.tpe);
+ typed(ddef.rhs, tpt1.tpe);
}
copy.DefDef(ddef, ddef.mods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
- def transformAbsTypeDef(tdef: AbsTypeDef): AbsTypeDef = {
- val lo1 = checkNoEscaping.privates(tdef.symbol, transformType(tdef.lo));
- val hi1 = checkNoEscaping.privates(tdef.symbol, transformType(tdef.hi));
+ def typedAbsTypeDef(tdef: AbsTypeDef): AbsTypeDef = {
+ val lo1 = checkNoEscaping.privates(tdef.symbol, typedType(tdef.lo));
+ val hi1 = checkNoEscaping.privates(tdef.symbol, typedType(tdef.hi));
copy.AbsTypeDef(tdef, tdef.mods, tdef.name, lo1, hi1) setType NoType
}
- def transformAliasTypeDef(tdef: AliasTypeDef): AliasTypeDef = {
+ def typedAliasTypeDef(tdef: AliasTypeDef): AliasTypeDef = {
reenterTypeParams(tdef.tparams);
- val tparams1 = List.mapConserve(tdef.tparams)(transformAbsTypeDef);
- val rhs1 = checkNoEscaping.privates(tdef.symbol, transformType(tdef.rhs));
+ val tparams1 = List.mapConserve(tdef.tparams)(typedAbsTypeDef);
+ val rhs1 = checkNoEscaping.privates(tdef.symbol, typedType(tdef.rhs));
copy.AliasTypeDef(tdef, tdef.mods, tdef.name, tparams1, rhs1) setType NoType
}
- def transformLabelDef(ldef: LabelDef): LabelDef = {
+ def typedLabelDef(ldef: LabelDef): LabelDef = {
var lsym = ldef.symbol;
if (lsym == NoSymbol)
lsym = namer.enterInScope(
context.owner.newLabel(ldef.pos, ldef.name) setInfo MethodType(List(), UnitClass.tpe));
- val rhs1 = transform(ldef.rhs, EXPRmode, UnitClass.tpe);
+ val rhs1 = typed(ldef.rhs, UnitClass.tpe);
copy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setSymbol lsym setType UnitClass.tpe
}
- def transformBlock(block: Block, mode: int, pt: Type): Block = {
+ def typedBlock(block: Block, mode: int, pt: Type): Block = {
namer.enterSyms(block.stats);
val stats1 =
if ((mode & INCONSTRmode) != 0) {
- val constrCall = transform(block.stats.head, mode, WildcardType);
+ val constrCall = typed(block.stats.head, mode, WildcardType);
context.enclClass.owner.resetFlag(INCONSTRUCTOR);
- constrCall :: transformStats(block.stats.tail, context.owner);
+ constrCall :: typedStats(block.stats.tail, context.owner);
} else {
- transformStats(block.stats, context.owner)
+ typedStats(block.stats, context.owner)
}
- val expr1 = transform(block.expr, mode & ~(FUNmode | QUALmode), pt);
+ val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt);
val block1 = copy.Block(block, stats1, expr1)
setType (if (treeInfo.isPureExpr(block)) expr1.tpe else expr1.tpe.deconst);
if (block1.tpe.symbol.isAnonymousClass)
@@ -563,15 +558,15 @@ abstract class Typers: Analyzer {
if (isFullyDefined(pt)) block1 else checkNoEscaping.locals(context.scope, block1)
}
- def transformCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = {
- val pat1: Tree = transform(cdef.pat, PATTERNmode, pattpe);
+ def typedCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = {
+ val pat1: Tree = typedPattern(cdef.pat, pattpe);
val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree
- else transform(cdef.guard, EXPRmode, BooleanClass.tpe);
- val body1: Tree = transform(cdef.body, EXPRmode, pt);
+ else typed(cdef.guard, BooleanClass.tpe);
+ val body1: Tree = typed(cdef.body, pt);
copy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe
}
- def transformFunction(fun: Function, mode: int, pt: Type): Function = {
+ def typedFunction(fun: Function, mode: int, pt: Type): Function = {
val Triple(clazz, argpts, respt) = pt match {
case TypeRef(_, sym, argtps)
if (fun.vparams.length <= MaxFunctionArity && sym == FunctionClass(fun.vparams.length) ||
@@ -591,19 +586,19 @@ abstract class Typers: Analyzer {
namer.enterSym(vparam);
vparam.symbol
}
- val vparams1 = List.mapConserve(fun.vparams)(transformValDef);
- val body1 = transform(fun.body, EXPRmode, respt);
+ val vparams1 = List.mapConserve(fun.vparams)(typedValDef);
+ val body1 = typed(fun.body, respt);
copy.Function(fun, vparams1, body1)
setType typeRef(clazz.tpe.prefix, clazz, (vparamSyms map (.tpe)) ::: List(body1.tpe))
}
- def transformRefinement(stats: List[Tree]): List[Tree] = {
+ def typedRefinement(stats: List[Tree]): List[Tree] = {
namer.enterSyms(stats);
for (val stat <- stats) stat.symbol setFlag OVERRIDE;
- transformStats(stats, NoSymbol);
+ typedStats(stats, NoSymbol);
}
- def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
+ def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
List.mapConserve(stats) { stat =>
if (context.owner.isRefinementClass && !treeInfo.isDeclaration(stat))
errorTree(stat, "only declarations allowed here");
@@ -613,23 +608,23 @@ abstract class Typers: Analyzer {
EmptyTree
case _ =>
(if (exprOwner != context.owner && (!stat.isDef || stat.isInstanceOf[LabelDef]))
- newTyper(context.make(stat, exprOwner)) else this).transformExpr(stat)
+ newTyper(context.make(stat, exprOwner)) else this).typed(stat)
}
}
- private def transform1(tree: Tree, mode: int, pt: Type): Tree = {
+ private def typed1(tree: Tree, mode: int, pt: Type): Tree = {
def funmode = mode & stickyModes | FUNmode | POLYmode;
- def transformCases(cases: List[CaseDef], pattp: Type): List[CaseDef] = {
+ def typedCases(cases: List[CaseDef], pattp: Type): List[CaseDef] = {
List.mapConserve(cases)(cdef =>
- newTyper(context.makeNewScope(tree, context.owner)).transformCase(cdef, pattp, pt))
+ newTyper(context.makeNewScope(tree, context.owner)).typedCase(cdef, pattp, pt))
}
- def transformTypeApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
+ def typedTypeApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
case OverloadedType(pre, alts) =>
inferPolyAlternatives(fun, args.length);
- transformTypeApply(fun, args)
+ typedTypeApply(fun, args)
case PolyType(tparams, restpe) if (tparams.length != 0) =>
if (tparams.length == args.length) {
val targs = args map (.tpe);
@@ -646,12 +641,12 @@ abstract class Typers: Analyzer {
errorTree(tree, treeSymTypeMsg(fun) + " does not take type parameters.");
}
- def transformApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
+ def typedApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
case OverloadedType(pre, alts) =>
val args1 = List.mapConserve(args)(arg =>
- transform(arg, mode & stickyModes, WildcardType));
+ typed(arg, mode & stickyModes, WildcardType));
inferMethodAlternative(fun, context.undetparams, args1 map (.tpe.deconst), pt);
- transformApply(adapt(fun, funmode, WildcardType), args1);
+ typedApply(adapt(fun, funmode, WildcardType), args1);
case MethodType(formals0, restpe) =>
val formals = formalTypes(formals0, args.length);
if (formals.length != args.length) {
@@ -662,23 +657,20 @@ abstract class Typers: Analyzer {
context.undetparams = List();
if (tparams.isEmpty) {
val args1 = List.map2(args, formals) ((arg, formal) =>
- transform(arg, mode & stickyModes, formal));
+ typed(arg, mode & stickyModes, formal));
def ifPatternSkipFormals(tp: Type) = tp match {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
case _ => tp
}
- val tree1 = copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe));
- val tree2 = constfold(tree1);
- if (tree2 != tree1) tree1.tpe = null;
- tree2
+ constfold(copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe)));
} else {
assert((mode & PATTERNmode) == 0); // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, restpe, pt);
val strictTargs = List.map2(lenientTargs, tparams)((targ, tparam) =>
if (targ == WildcardType) tparam.tpe else targ);
- def transformArg(tree: Tree, formal: Type): Tree = {
+ def typedArg(tree: Tree, formal: Type): Tree = {
val lenientPt = formal.subst(tparams, lenientTargs);
- val tree1 = transform(tree, mode & stickyModes | POLYmode, lenientPt);
+ val tree1 = typed(tree, mode & stickyModes | POLYmode, lenientPt);
val argtparams = context.undetparams;
context.undetparams = List();
if (!argtparams.isEmpty) {
@@ -687,12 +679,12 @@ abstract class Typers: Analyzer {
}
tree1
}
- val args1 = List.map2(args, formals)(transformArg);
+ val args1 = List.map2(args, formals)(typedArg);
if (args1 exists (.tpe.isError)) setError(tree)
else {
if (settings.debug.value) System.out.println("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(.tpe.bounds.lo));//debug
val undetparams = inferMethodInstance(fun, tparams, args1, pt);
- val result = transformApply(fun, args1);
+ val result = typedApply(fun, args1);
context.undetparams = undetparams;
result
}
@@ -725,7 +717,7 @@ abstract class Typers: Analyzer {
/** Attribute a selection where `tree' is `qual.name'.
* `qual' is already attributed.
*/
- def transformSelect(qual: Tree, name: Name): Tree = {
+ def typedSelect(qual: Tree, name: Name): Tree = {
val sym =
if (tree.symbol != NoSymbol) {
val alts = qual.tpe.member(name).alternatives;
@@ -738,14 +730,15 @@ abstract class Typers: Analyzer {
if (sym == NoSymbol && qual.isTerm && (qual.symbol == null || qual.symbol.isValue)) {
val coercion = inferView(qual.pos, qual.tpe, name, true);
if (coercion != EmptyTree)
- return transform(
+ return typed(
copy.Select(tree, Apply(coercion, List(qual)) setPos qual.pos, name), mode, pt)
}
if (sym.info == NoType) {
- System.out.println(qual);
- System.out.println(qual.tpe.members);//debug
- System.out.println(qual.tpe.member(name));//debug
- errorTree(tree, decode(name) + " is not a member of " + qual.tpe.widen)
+ if (settings.debug.value) System.out.println("qual = " + qual + "\nmembers = " + qual.tpe.members);
+ errorTree(tree,
+ decode(name) + " is not a member of " + qual.tpe.widen +
+ (if (Position.line(tree.pos) > Position.line(qual.pos))
+ "\npossible cause: maybe a semicolon is missing before `" + name + "'?" else ""))
} else {
val tree1 = tree match {
case Select(_, _) => copy.Select(tree, qual, name)
@@ -761,7 +754,7 @@ abstract class Typers: Analyzer {
* Transformations: (1) Prefix class members with this.
* (2) Change imported symbols to selections
*/
- def transformIdent(name: Name): Tree = {
+ def typedIdent(name: Name): Tree = {
def ambiguousError(msg: String) =
error(tree.pos, "reference to " + name + " is ambiguous;\n" + msg);
@@ -832,8 +825,10 @@ abstract class Typers: Analyzer {
qual = imports.head.qual;
pre = qual.tpe;
} else {
- System.out.println(context);//debug
- System.out.println(context.imports);//debug
+ if (settings.debug.value) {
+ System.out.println(context);//debug
+ System.out.println(context.imports);//debug
+ }
error(tree.pos, "not found: " + decode(name));
defSym = context.owner.newErrorSymbol(name);
}
@@ -846,40 +841,40 @@ abstract class Typers: Analyzer {
stabilize(checkAccessible(tree1, defSym, pre, qual), pre, mode, pt)
}
- // begin transform1
+ // begin typed1
val sym: Symbol = tree.symbol;
if (sym != null) sym.initialize;
- //if (settings.debug.value && tree.isDef) global.log("transforming definition of " + sym);//DEBUG
+ //if (settings.debug.value && tree.isDef) global.log("typing definition of " + sym);//DEBUG
tree match {
case PackageDef(name, stats) =>
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
- .transformStats(stats, NoSymbol);
+ .typedStats(stats, NoSymbol);
copy.PackageDef(tree, name, stats1) setType NoType
case cdef @ ClassDef(_, _, _, _, _) =>
- newTyper(context.makeNewScope(tree, sym)).transformClassDef(cdef)
+ newTyper(context.makeNewScope(tree, sym)).typedClassDef(cdef)
case mdef @ ModuleDef(_, _, _) =>
- transformModuleDef(mdef)
+ typedModuleDef(mdef)
case vdef @ ValDef(_, _, _, _) =>
- transformValDef(vdef)
+ typedValDef(vdef)
case ddef @ DefDef(_, _, _, _, _, _) =>
- newTyper(context.makeNewScope(tree, sym)).transformDefDef(ddef)
+ newTyper(context.makeNewScope(tree, sym)).typedDefDef(ddef)
case tdef @ AbsTypeDef(_, _, _, _) =>
- transformAbsTypeDef(tdef)
+ newTyper(context.makeNewScope(tree, sym)).typedAbsTypeDef(tdef)
case tdef @ AliasTypeDef(_, _, _, _) =>
- newTyper(context.makeNewScope(tree, sym)).transformAliasTypeDef(tdef)
+ newTyper(context.makeNewScope(tree, sym)).typedAliasTypeDef(tdef)
case ldef @ LabelDef(_, List(), _) =>
- newTyper(context.makeNewScope(tree, context.owner)).transformLabelDef(ldef)
+ newTyper(context.makeNewScope(tree, context.owner)).typedLabelDef(ldef)
case Attributed(attr, defn) =>
- val attr1 = transform(attr, EXPRmode, AttributeClass.tpe);
- val defn1 = transform(defn, mode, pt);
+ val attr1 = typed(attr, AttributeClass.tpe);
+ val defn1 = typed(defn, mode, pt);
val existing = attributes.get(defn1.symbol) match {
case None => List()
case Some(attrs) => attrs
@@ -888,18 +883,18 @@ abstract class Typers: Analyzer {
defn1
case DocDef(comment, defn) =>
- transform(defn, mode, pt);
+ typed(defn, mode, pt);
case block @ Block(_, _) =>
newTyper(context.makeNewScope(tree, context.owner))
- .transformBlock(block, mode, pt)
+ .typedBlock(block, mode, pt)
case Sequence(elems) =>
- val elems1 = List.mapConserve(elems)(elem => transform(elem, mode, pt));
+ val elems1 = List.mapConserve(elems)(elem => typed(elem, mode, pt));
copy.Sequence(tree, elems1) setType pt
case Alternative(alts) =>
- val alts1 = List.mapConserve(alts)(alt => transform(alt, mode, pt));
+ val alts1 = List.mapConserve(alts)(alt => typed(alt, mode, pt));
copy.Alternative(tree, alts1) setType pt
case Bind(name, body) =>
@@ -909,31 +904,31 @@ abstract class Typers: Analyzer {
if (vble.name != nme.WILDCARD) namer.enterInScope(vble);
}
vble.setInfo(pt);
- val body1 = transform(body, mode, pt);
+ val body1 = typed(body, mode, pt);
vble.setInfo(if (treeInfo.isSequenceValued(body)) seqType(body1.tpe) else body1.tpe);
copy.Bind(tree, name, body1) setSymbol vble setType pt
case fun @ Function(_, _) =>
newTyper(context.makeNewScope(tree, context.owner))
- .transformFunction(fun, mode, pt)
+ .typedFunction(fun, mode, pt)
case Assign(lhs, rhs) =>
def isGetter(sym: Symbol) = sym.info match {
case PolyType(List(), _) => sym.owner.isClass && !sym.isStable
case _ => false
}
- val lhs1 = transformExpr(lhs);
+ val lhs1 = typed(lhs);
val varsym = lhs1.symbol;
if (varsym != null && isGetter(varsym)) {
lhs1 match {
case Select(qual, name) =>
- transform(
+ typed(
Apply(
Select(qual, nme.SETTER_NAME(name)) setPos lhs.pos,
List(rhs)) setPos tree.pos, mode, pt)
}
} else if (varsym != null && varsym.isVariable) {
- val rhs1 = transform(rhs, EXPRmode, lhs1.tpe);
+ val rhs1 = typed(rhs, lhs1.tpe);
copy.Assign(tree, lhs1, rhs1) setType UnitClass.tpe;
} else {
System.out.println("" + lhs1 + " " + varsym + " " + flagsToString(varsym.flags));//debug
@@ -942,19 +937,19 @@ abstract class Typers: Analyzer {
}
case If(cond, thenp, elsep) =>
- val cond1 = transform(cond, EXPRmode, BooleanClass.tpe);
+ val cond1 = typed(cond, BooleanClass.tpe);
if (elsep.isEmpty) {
- val thenp1 = transform(thenp, EXPRmode, UnitClass.tpe);
+ val thenp1 = typed(thenp, UnitClass.tpe);
copy.If(tree, cond1, thenp1, elsep) setType UnitClass.tpe
} else {
- val thenp1 = transform(thenp, EXPRmode, pt);
- val elsep1 = transform(elsep, EXPRmode, pt);
+ val thenp1 = typed(thenp, pt);
+ val elsep1 = typed(elsep, pt);
copy.If(tree, cond1, thenp1, elsep1) setType lub(List(thenp1.tpe, elsep1.tpe));
}
case Match(selector, cases) =>
- val selector1 = transformExpr(selector);
- val cases1 = transformCases(cases, selector1.tpe);
+ val selector1 = typed(selector);
+ val cases1 = typedCases(cases, selector1.tpe);
copy.Match(tree, selector1, cases1) setType lub(cases1 map (.tpe))
case Return(expr) =>
@@ -964,24 +959,24 @@ abstract class Typers: Analyzer {
else if (!context.owner.hasFlag(INITIALIZED))
errorTree(tree, "method " + context.owner + " has return statement; needs result type")
else {
- val expr1: Tree = transform(expr, EXPRmode, enclFun.tpe.resultType);
+ val expr1: Tree = typed(expr, enclFun.tpe.resultType);
copy.Return(tree, expr1) setSymbol enclFun setType AllClass.tpe;
}
case Try(block, catches, finalizer) =>
- val block1 = transform(block, EXPRmode, pt);
- val catches1 = transformCases(catches, ThrowableClass.tpe);
+ val block1 = typed(block, pt);
+ val catches1 = typedCases(catches, ThrowableClass.tpe);
val finalizer1 = if (finalizer.isEmpty) finalizer
- else transform(finalizer, EXPRmode, UnitClass.tpe);
+ else typed(finalizer, UnitClass.tpe);
copy.Try(tree, block1, catches1, finalizer1)
setType lub(block1.tpe :: (catches1 map (.tpe)))
case Throw(expr) =>
- val expr1 = transform(expr, EXPRmode, ThrowableClass.tpe);
+ val expr1 = typed(expr, ThrowableClass.tpe);
copy.Throw(tree, expr1) setType AllClass.tpe
case New(tpt: Tree) =>
- var tpt1 = transform(tpt, TYPEmode | FUNmode, WildcardType);
+ var tpt1 = typedTypeConstructor(tpt);
if (tpt1.hasSymbol && !tpt1.symbol.typeParams.isEmpty) {
context.undetparams = cloneSymbols(tpt1.symbol.unsafeTypeParams);
tpt1 = TypeTree()
@@ -991,7 +986,7 @@ abstract class Typers: Analyzer {
copy.New(tree, tpt1).setType(tpt1.tpe)
case Typed(expr, tpt @ Ident(name)) if (name == nme.WILDCARD_STAR.toTypeName) =>
- val expr1 = transform(expr, mode & stickyModes, seqType(pt));
+ val expr1 = typed(expr, mode & stickyModes, seqType(pt));
expr1.tpe.baseType(SeqClass) match {
case TypeRef(_, _, List(elemtp)) =>
copy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
@@ -999,18 +994,18 @@ abstract class Typers: Analyzer {
setError(tree)
}
case Typed(expr, tpt) =>
- val tpt1 = transformType(tpt);
- val expr1 = transform(expr, mode & stickyModes, tpt1.tpe);
+ val tpt1 = typedType(tpt);
+ val expr1 = typed(expr, mode & stickyModes, tpt1.tpe);
copy.Typed(tree, expr1, tpt1) setType tpt1.tpe
case TypeApply(fun, args) =>
- val args1 = List.mapConserve(args)(transformType);
+ val args1 = List.mapConserve(args)(typedType);
// do args first in order to maintain conext.undetparams on the function side.
- transformTypeApply(transform(fun, funmode | TAPPmode, WildcardType), args1)
+ typedTypeApply(typed(fun, funmode | TAPPmode, WildcardType), args1)
case Apply(fun, args) =>
val funpt = if ((mode & PATTERNmode) != 0) pt else WildcardType;
- var fun1 = transform(fun, funmode, funpt);
+ var fun1 = typed(fun, funmode, funpt);
// if function is overloaded, filter all alternatives that match
// number of arguments and expected result type.
// if (settings.debug.value) System.out.println("trans app " + fun1 + ":" + fun1.symbol + ":" + fun1.tpe + " " + args);//DEBUG
@@ -1023,7 +1018,7 @@ abstract class Typers: Analyzer {
fun1 = adapt(fun1 setSymbol sym setType pre.memberType(sym), funmode, WildcardType)
}
appcnt = appcnt + 1;
- transformApply(fun1, args)
+ typedApply(fun1, args)
case Super(qual, mix) =>
val clazz = if (tree.symbol != NoSymbol) tree.symbol else qualifyingClass(qual);
@@ -1054,51 +1049,51 @@ abstract class Typers: Analyzer {
}
case Select(qual @ Super(_, _), nme.CONSTRUCTOR) =>
- val qual1 = transform(qual, EXPRmode | QUALmode | POLYmode | SUPERCONSTRmode, WildcardType);
+ val qual1 = typed(qual, EXPRmode | QUALmode | POLYmode | SUPERCONSTRmode, WildcardType);
// the qualifier type of a supercall constructor is its first parent class
- transformSelect(qual1, nme.CONSTRUCTOR);
+ typedSelect(qual1, nme.CONSTRUCTOR);
case Select(qual, name) =>
selcnt = selcnt + 1;
assert (name != nme.CONSTRUCTOR || !qual.isInstanceOf[Super], tree);//debug
- var qual1 = transform(qual, EXPRmode | QUALmode | POLYmode, WildcardType);
+ var qual1 = typedQualifier(qual);
if (name.isTypeName) qual1 = checkStable(qual1);
- transformSelect(qual1, name);
+ typedSelect(qual1, name);
case Ident(name) =>
idcnt = idcnt + 1;
if (name == nme.WILDCARD && (mode & (PATTERNmode | FUNmode)) == PATTERNmode)
tree setType pt
else
- transformIdent(name);
+ typedIdent(name);
case Literal(value) =>
tree setType
(if (value == ()) UnitClass.tpe else ConstantType(constfold.literalType(value), value))
case SingletonTypeTree(ref) =>
- val ref1 = checkStable(transform(ref, EXPRmode | QUALmode, AnyRefClass.tpe));
+ val ref1 = checkStable(typed(ref, EXPRmode | QUALmode, AnyRefClass.tpe));
tree setType ref1.tpe.resultType;
case SelectFromTypeTree(qual, selector) =>
- tree setType transformSelect(transformType(qual), selector).tpe
+ tree setType typedSelect(typedType(qual), selector).tpe
case CompoundTypeTree(templ: Template) =>
tree setType {
- val parents1 = List.mapConserve(templ.parents)(transformType);
+ val parents1 = List.mapConserve(templ.parents)(typedType);
if (parents1 exists (.tpe.isError)) ErrorType
else {
val decls = new Scope();
val self = refinedType(parents1 map (.tpe), context.enclClass.owner, decls);
- newTyper(context.make(tree, self.symbol, new Scope())).transformRefinement(templ.body);
+ newTyper(context.make(tree, self.symbol, new Scope())).typedRefinement(templ.body);
self
}
}
case AppliedTypeTree(tpt, args) =>
- val tpt1 = transform(tpt, mode | FUNmode | TAPPmode, WildcardType);
+ val tpt1 = typed(tpt, mode | FUNmode | TAPPmode, WildcardType);
val tparams = tpt1.tpe.symbol.typeParams;
- val args1 = List.mapConserve(args)(transformType);
+ val args1 = List.mapConserve(args)(typedType);
if (tpt1.tpe.isError)
setError(tree)
else if (tparams.length == args1.length)
@@ -1110,13 +1105,13 @@ abstract class Typers: Analyzer {
}
}
- def transform(tree: Tree, mode: int, pt: Type): Tree =
+ def typed(tree: Tree, mode: int, pt: Type): Tree =
try {
if (settings.debug.value) {
assert(pt != null, tree);//debug
- //System.out.println("transforming " + tree);//DEBUG
+ //System.out.println("typing " + tree);//DEBUG
}
- val tree1 = if (tree.tpe != null) tree else transform1(tree, mode, pt);
+ val tree1 = if (tree.tpe != null) tree else typed1(tree, mode, pt);
if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
} catch {
case ex: TypeError =>
@@ -1124,13 +1119,22 @@ abstract class Typers: Analyzer {
setError(tree)
case ex: Throwable =>
if (true || settings.debug.value)//!!!
- System.out.println("exception when transforming " + tree + ", pt = " + pt);
+ System.out.println("exception when typing " + tree + ", pt = " + pt);
throw(ex)
}
- def transformExpr(tree: Tree): Tree = transform(tree, EXPRmode, WildcardType);
- def transformQualExpr(tree: Tree): Tree = transform(tree, EXPRmode | QUALmode, WildcardType);
- def transformType(tree: Tree) = transform(tree, TYPEmode, WildcardType);
+ def typed(tree: Tree): Tree =
+ typed(tree, EXPRmode, WildcardType);
+ def typed(tree: Tree, pt: Type): Tree =
+ typed(tree, EXPRmode, pt);
+ def typedQualifier(tree: Tree): Tree =
+ typed(tree, EXPRmode | QUALmode | POLYmode, WildcardType);
+ def typedPattern(tree: Tree, pt: Type): Tree =
+ typed(tree, PATTERNmode, pt);
+ def typedType(tree: Tree): Tree =
+ typed(tree, TYPEmode, WildcardType);
+ def typedTypeConstructor(tree: Tree): Tree =
+ typed(tree, TYPEmode | FUNmode, WildcardType);
/* -- Views --------------------------------------------------------------- */
@@ -1139,61 +1143,89 @@ abstract class Typers: Analyzer {
case _ => tp
}
- private def transformImplicit(pos: int, info: ImplicitInfo, pt: Type): Tree =
+ private def typedImplicit(pos: int, info: ImplicitInfo, pt: Type, local: boolean): Tree =
if (isCompatible(depoly(info.tpe), pt)) {
implcnt = implcnt + 1;
var tree: Tree = EmptyTree;
+ def fail(reason: String): Tree = {
+ if (settings.debug.value)
+ System.out.println(tree.toString() + " is not a valid implicit value because:\n" + reason);
+ EmptyTree
+ }
try {
- tree = transform1(Ident(info.name) setPos pos, EXPRmode, pt);
- if (settings.debug.value) System.out.println("transformed implicit " + tree + ":" + tree.tpe + ", pt = " + pt);//debug
+ tree = Ident(info.name) setPos pos;
+ if (!local) tree setSymbol info.sym;
+ tree = typed1(tree, EXPRmode, pt);
+ if (settings.debug.value) System.out.println("typed implicit " + tree + ":" + tree.tpe + ", pt = " + pt);//debug
val tree1 = adapt(tree, EXPRmode, pt);
if (settings.debug.value) System.out.println("adapted implicit " + tree.symbol + ":" + info.sym);//debug
- if (info.sym == tree.symbol) tree1 else EmptyTree
+ if (info.sym == tree.symbol) tree1
+ else fail("syms differ: " + tree.symbol + " " + info.sym)
} catch {
- case ex: TypeError =>
- if (settings.debug.value)
- System.out.println(tree.toString() + " is not a valid implicit value because:\n" + ex.getMessage());
- EmptyTree
+ case ex: TypeError => fail(ex.getMessage())
}
} else EmptyTree;
private def inferImplicit(pos: int, pt: Type, isView: boolean, reportAmbiguous: boolean): Tree = {
+
def isBetter(sym1: Symbol, tpe1: Type, sym2: Symbol, tpe2: Type): boolean =
+ sym2.isError ||
(sym1.owner != sym2.owner) && (sym1.owner isSubClass sym2.owner) && (tpe1 matches tpe2);
+
val tc = newTyper(context.makeImplicit(reportAmbiguous));
- var iss = context.implicitss;
- var tree: Tree = EmptyTree;
- while (tree == EmptyTree && !iss.isEmpty) {
- var is = iss.head;
- //System.out.println("testing " + is.head.sym + is.head.sym.locationString + ":" + is.head.tpe);//DEBUG
- iss = iss.tail;
- while (!is.isEmpty) {
- tree = tc.transformImplicit(pos, is.head, pt);
- val is0 = is;
- is = is.tail;
- if (tree != EmptyTree) {
- while (!is.isEmpty) {
- val tree1 = tc.transformImplicit(pos, is.head, pt);
- if (tree1 != EmptyTree) {
- if (isBetter(is.head.sym, tree1.tpe, is0.head.sym, tree.tpe))
- tree = tree1
- else if (!isBetter(is0.head.sym, tree.tpe, is.head.sym, tree1.tpe))
- error(
- pos,
- "ambiguous implicit value:\n" +
- " both " + is0.head.sym + is0.head.sym.locationString + " of type " + tree.tpe +
- "\n and" + is.head.sym + is.head.sym.locationString + " of type " + tree1.tpe +
- (if (isView)
- "\n are possible conversion functions from " +
- pt.typeArgs(0) + " to " + pt.typeArgs(1)
- else
- "\n match expected type " + pt));
+
+ def searchImplicit(implicitInfoss: List[List[ImplicitInfo]], local: boolean): Tree = {
+ var iss = implicitInfoss;
+ var tree: Tree = EmptyTree;
+ while (tree == EmptyTree && !iss.isEmpty) {
+ var is = iss.head;
+ iss = iss.tail;
+ while (!is.isEmpty) {
+ tree = tc.typedImplicit(pos, is.head, pt, local);
+ if (settings.debug.value) System.out.println("tested " + is.head.sym + is.head.sym.locationString + ":" + is.head.tpe + "=" + tree);//debug
+ val is0 = is;
+ is = is.tail;
+ if (tree != EmptyTree) {
+ while (!is.isEmpty) {
+ val tree1 = tc.typedImplicit(pos, is.head, pt, local);
+ if (tree1 != EmptyTree) {
+ if (isBetter(is.head.sym, tree1.tpe, is0.head.sym, tree.tpe))
+ tree = tree1
+ else if (!isBetter(is0.head.sym, tree.tpe, is.head.sym, tree1.tpe))
+ error(
+ pos,
+ "ambiguous implicit value:\n" +
+ " both " + is0.head.sym + is0.head.sym.locationString + " of type " + tree.tpe +
+ "\n and" + is.head.sym + is.head.sym.locationString + " of type " + tree1.tpe +
+ (if (isView)
+ "\n are possible conversion functions from " +
+ pt.typeArgs(0) + " to " + pt.typeArgs(1)
+ else
+ "\n match expected type " + pt));
+ }
+ is = is.tail
}
- is = is.tail
}
}
}
+ tree
+ }
+
+ def implicitsOfType(tp: Type): List[List[ImplicitInfo]] = {
+ val tp1 =
+ if (tp.typeArgs.length - 1 <= MaxFunctionArity &&
+ tp.symbol == FunctionClass(tp.typeArgs.length - 1))
+ intersectionType(tp.typeArgs.reverse)
+ else tp;
+ tp1.baseClasses map implicitsOfClass;
}
+
+ def implicitsOfClass(clazz: Symbol): List[ImplicitInfo] =
+ clazz.initialize.linkedModule.moduleClass.info.decls.toList.filter(.hasFlag(IMPLICIT)) map
+ (sym => ImplicitInfo(sym.name, clazz.linkedModule.tpe.memberType(sym), sym));
+
+ var tree = searchImplicit(context.implicitss, true);
+ if (tree == EmptyTree) tree = searchImplicit(implicitsOfType(pt.widen), false);
tree
}