From 541dd58f4d8fec8fc2b385b2c288721e5e258915 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 13 Jan 2010 17:27:01 +0000 Subject: better fix for see #2421 after feedback from Ma... better fix for see #2421 after feedback from Martin --- .../scala/tools/nsc/typechecker/Implicits.scala | 9 +- .../scala/tools/nsc/typechecker/Typers.scala | 101 +++++++++++---------- 2 files changed, 59 insertions(+), 51 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index c4464010c1..0539b4ee17 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -477,7 +477,14 @@ self: Analyzer => // #2421b: since type inference (which may have been performed during implicit search) // does not check whether inferred arguments meet the bounds of the corresponding parameter (see note in solvedTypes), // must check again here: - typed1(itree2, EXPRmode, wildPt) + itree2 match { // roughly equivalent to typed1(itree2, EXPRmode, wildPt), + // since typed1 only forces checking of the outer tree and calls typed on the subtrees + // (they have already been type checked, by the typed1(itree...) above, so the subtrees are skipped by typed) + // inlining the essential bit here for clarity + //TODO: verify that these subtrees don't need re-checking + case TypeApply(fun, args) => typedTypeApply(itree2, EXPRmode, fun, args) + case _ => + } val result = new SearchResult(itree2, subst) incCounter(foundImplicits) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f29f6fa7a3..515c7ad354 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2900,6 +2900,56 @@ trait Typers { self: Analyzer => TypeTree(ExistentialType(typeParams, tpe)) setOriginal tree } + // lifted out of typed1 because it's needed in typedImplicit0 + protected def typedTypeApply(tree: Tree, mode: Int, fun: Tree, args: List[Tree]): Tree = fun.tpe match { + case OverloadedType(pre, alts) => + inferPolyAlternatives(fun, args map (_.tpe)) + val tparams = fun.symbol.typeParams //@M TODO: fun.symbol.info.typeParams ? (as in typedAppliedTypeTree) + val args1 = if(args.length == tparams.length) { + //@M: in case TypeApply we can't check the kind-arities of the type arguments, + // as we don't know which alternative to choose... here we do + map2Conserve(args, tparams) { + //@M! the polytype denotes the expected kind + (arg, tparam) => typedHigherKindedType(arg, mode, polyType(tparam.typeParams, AnyClass.tpe)) + } + } else // @M: there's probably something wrong when args.length != tparams.length... (triggered by bug #320) + // Martin, I'm using fake trees, because, if you use args or arg.map(typedType), + // inferPolyAlternatives loops... -- I have no idea why :-( + // ...actually this was looping anyway, see bug #278. + return errorTree(fun, "wrong number of type parameters for "+treeSymTypeMsg(fun)) + + typedTypeApply(tree, mode, fun, args1) + case SingleType(_, _) => + typedTypeApply(tree, mode, fun setType fun.tpe.widen, args) + case PolyType(tparams, restpe) if (tparams.length != 0) => + if (tparams.length == args.length) { + val targs = args map (_.tpe) + checkBounds(tree.pos, NoPrefix, NoSymbol, tparams, targs, "") + if (fun.symbol == Predef_classOf) { + checkClassType(args.head, true, false) + atPos(tree.pos) { gen.mkClassOf(targs.head) } + } else { + if (phase.id <= currentRun.typerPhase.id && + fun.symbol == Any_isInstanceOf && !targs.isEmpty) + checkCheckable(tree.pos, targs.head, "") + val resultpe = restpe.instantiateTypeParams(tparams, targs) + //@M substitution in instantiateParams needs to be careful! + //@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int] + //@M --> first, m[a] gets changed to m[Int], then m gets substituted for List, + // this must preserve m's type argument, so that we end up with List[Int], and not List[a] + //@M related bug: #1438 + //println("instantiating type params "+restpe+" "+tparams+" "+targs+" = "+resultpe) + treeCopy.TypeApply(tree, fun, args) setType resultpe + } + } else { + errorTree(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun)) + } + case ErrorType => + setError(tree) + case _ => + errorTree(tree, treeSymTypeMsg(fun)+" does not take type parameters.") + } + /** * @param tree ... * @param mode ... @@ -3184,55 +3234,6 @@ trait Typers { self: Analyzer => errorTree(expr1, "_ must follow method; cannot follow " + expr1.tpe) } - def typedTypeApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match { - case OverloadedType(pre, alts) => - inferPolyAlternatives(fun, args map (_.tpe)) - val tparams = fun.symbol.typeParams //@M TODO: fun.symbol.info.typeParams ? (as in typedAppliedTypeTree) - val args1 = if(args.length == tparams.length) { - //@M: in case TypeApply we can't check the kind-arities of the type arguments, - // as we don't know which alternative to choose... here we do - map2Conserve(args, tparams) { - //@M! the polytype denotes the expected kind - (arg, tparam) => typedHigherKindedType(arg, mode, polyType(tparam.typeParams, AnyClass.tpe)) - } - } else // @M: there's probably something wrong when args.length != tparams.length... (triggered by bug #320) - // Martin, I'm using fake trees, because, if you use args or arg.map(typedType), - // inferPolyAlternatives loops... -- I have no idea why :-( - // ...actually this was looping anyway, see bug #278. - return errorTree(fun, "wrong number of type parameters for "+treeSymTypeMsg(fun)) - - typedTypeApply(fun, args1) - case SingleType(_, _) => - typedTypeApply(fun setType fun.tpe.widen, args) - case PolyType(tparams, restpe) if (tparams.length != 0) => - if (tparams.length == args.length) { - val targs = args map (_.tpe) - checkBounds(tree.pos, NoPrefix, NoSymbol, tparams, targs, "") - if (fun.symbol == Predef_classOf) { - checkClassType(args.head, true, false) - atPos(tree.pos) { gen.mkClassOf(targs.head) } - } else { - if (phase.id <= currentRun.typerPhase.id && - fun.symbol == Any_isInstanceOf && !targs.isEmpty) - checkCheckable(tree.pos, targs.head, "") - val resultpe = restpe.instantiateTypeParams(tparams, targs) - //@M substitution in instantiateParams needs to be careful! - //@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int] - //@M --> first, m[a] gets changed to m[Int], then m gets substituted for List, - // this must preserve m's type argument, so that we end up with List[Int], and not List[a] - //@M related bug: #1438 - //println("instantiating type params "+restpe+" "+tparams+" "+targs+" = "+resultpe) - treeCopy.TypeApply(tree, fun, args) setType resultpe - } - } else { - errorTree(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun)) - } - case ErrorType => - setError(tree) - case _ => - errorTree(tree, treeSymTypeMsg(fun)+" does not take type parameters.") - } - /** * @param args ... * @return ... @@ -3922,7 +3923,7 @@ trait Typers { self: Analyzer => } //@M TODO: context.undetparams = undets_fun ? - typedTypeApply(fun1, args1) + typedTypeApply(tree, mode, fun1, args1) case Apply(Block(stats, expr), args) => typed1(atPos(tree.pos)(Block(stats, Apply(expr, args))), mode, pt) -- cgit v1.2.3