From d9d5dcd1e21c215826a915db47eaf993621e0441 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 24 Jun 2012 18:56:02 +0200 Subject: SI-4176 A repeat dose of repeated parameter type sanitization. - During eta expansion, treat parameters of type A* as Seq[A] - Do the same for method/class parameters as referred to by an Ident. Also fixes SI-5967, which shows up during pattern matching. --- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 17 +++++++---------- .../scala/tools/nsc/typechecker/EtaExpansion.scala | 17 +++++++++++++---- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 5 ++++- 3 files changed, 24 insertions(+), 15 deletions(-) (limited to 'src/compiler/scala') diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 3a527676b4..be5909a67f 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -213,17 +213,14 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { def wildcardStar(tree: Tree) = atPos(tree.pos) { Typed(tree, Ident(tpnme.WILDCARD_STAR)) } - def paramToArg(vparam: Symbol) = { - val arg = Ident(vparam) - if (isRepeatedParamType(vparam.tpe)) wildcardStar(arg) - else arg - } + def paramToArg(vparam: Symbol): Tree = + paramToArg(Ident(vparam), isRepeatedParamType(vparam.tpe)) - def paramToArg(vparam: ValDef) = { - val arg = Ident(vparam.name) - if (treeInfo.isRepeatedParamType(vparam.tpt)) wildcardStar(arg) - else arg - } + def paramToArg(vparam: ValDef): Tree = + paramToArg(Ident(vparam.name), treeInfo.isRepeatedParamType(vparam.tpt)) + + def paramToArg(arg: Ident, isRepeatedParam: Boolean): Tree = + if (isRepeatedParam) wildcardStar(arg) else arg /** Make forwarder to method `target`, passing all parameters in `params` */ def mkForwarder(target: Tree, vparamss: List[List[Symbol]]) = diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index e1fb683aa9..a4d9cdaffe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -107,11 +107,20 @@ trait EtaExpansion { self: Analyzer => */ def expand(tree: Tree, tpe: Type): Tree = tpe match { case mt @ MethodType(paramSyms, restpe) if !mt.isImplicit => - val params = paramSyms map (sym => - ValDef(Modifiers(SYNTHETIC | PARAM), - sym.name.toTermName, TypeTree(sym.tpe) , EmptyTree)) + val params: List[(ValDef, Boolean)] = paramSyms.map { + sym => + val origTpe = sym.tpe + val isRepeated = definitions.isRepeatedParamType(origTpe) + // SI-4176 Don't leak A* in eta-expanded function types. See t4176b.scala + val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropRepeatedParamType(origTpe) + val valDef = ValDef(Modifiers(SYNTHETIC | PARAM), sym.name.toTermName, TypeTree(droppedStarTpe), EmptyTree) + (valDef, isRepeated) + } atPos(tree.pos.makeTransparent) { - Function(params, expand(Apply(tree, params map gen.paramToArg), restpe)) + val args = params.map { + case (valDef, isRepeated) => gen.paramToArg(Ident(valDef.name), isRepeated) + } + Function(params.map(_._1), expand(Apply(tree, args), restpe)) } case _ => tree diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 69d3fd7f47..04d9d67d68 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4687,7 +4687,10 @@ trait Typers extends Modes with Adaptations with Tags { ) val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual) // assert(pre.typeArgs isEmpty) // no need to add #2416-style check here, right? - stabilize(tree2, pre2, mode, pt) + val tree3 = stabilize(tree2, pre2, mode, pt) + // SI-5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid + // inference errors in pattern matching. + tree3 setType dropRepeatedParamType(tree3.tpe) } } } -- cgit v1.2.3