diff options
author | Martin Odersky <odersky@gmail.com> | 2005-05-25 16:29:18 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-05-25 16:29:18 +0000 |
commit | b5c59169585faf8c352ed105db969e8deb590cf7 (patch) | |
tree | 0672dc159471047b9d55e38af31a976845a674fa /sources/scala/tools/nsc/typechecker/Typers.scala | |
parent | 6e45b64b7c55dd92da686418f65e1a415c346bf7 (diff) | |
download | scala-b5c59169585faf8c352ed105db969e8deb590cf7.tar.gz scala-b5c59169585faf8c352ed105db969e8deb590cf7.tar.bz2 scala-b5c59169585faf8c352ed105db969e8deb590cf7.zip |
a
Diffstat (limited to 'sources/scala/tools/nsc/typechecker/Typers.scala')
-rwxr-xr-x | sources/scala/tools/nsc/typechecker/Typers.scala | 446 |
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 } |