summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2012-06-24 18:56:02 +0200
committerJason Zaugg <jzaugg@gmail.com>2012-06-30 09:20:46 +0200
commitd9d5dcd1e21c215826a915db47eaf993621e0441 (patch)
treea6c4bf8aab8ff6d548c1a8763b3640d03282bb0d
parentf43de697595eaebcf2feec03beb95daf606ac678 (diff)
downloadscala-d9d5dcd1e21c215826a915db47eaf993621e0441.tar.gz
scala-d9d5dcd1e21c215826a915db47eaf993621e0441.tar.bz2
scala-d9d5dcd1e21c215826a915db47eaf993621e0441.zip
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.
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala5
-rw-r--r--test/files/pos/t4176b.scala5
-rw-r--r--test/files/pos/t5967.scala6
5 files changed, 35 insertions, 15 deletions
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)
}
}
}
diff --git a/test/files/pos/t4176b.scala b/test/files/pos/t4176b.scala
new file mode 100644
index 0000000000..11914c50c8
--- /dev/null
+++ b/test/files/pos/t4176b.scala
@@ -0,0 +1,5 @@
+object Test {
+ def foo(a: String*) = a
+ val fooEta = foo _
+ (foo: Seq[String] => Seq[String])
+}
diff --git a/test/files/pos/t5967.scala b/test/files/pos/t5967.scala
new file mode 100644
index 0000000000..eb9bd6dfa7
--- /dev/null
+++ b/test/files/pos/t5967.scala
@@ -0,0 +1,6 @@
+object Test {
+ def f(a: Int*) = a match {
+ case 0 :: Nil => "List(0)! My favorite Seq!"
+ case _ => a.toString
+ }
+}