summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala27
-rw-r--r--test/files/run/names-defaults.check10
-rw-r--r--test/files/run/names-defaults.scala17
4 files changed, 52 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 71c4353834..081f0053ec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -40,19 +40,15 @@ trait Infer {
* (nargs - params.length + 1) copies of its type is returned.
* By-name types are replaced with their underlying type.
*
- * @param formals ...
- * @param nargs ...
+ * @param removeByName allows keeping ByName parameters. Used in NamesDefaults.
+ * @param removeRepeated allows keeping repeated parameter (if there's one argument). Used in NamesDefaults.
*/
- def formalTypes(formals: List[Type], nargs: Int): List[Type] =
- formalTypes(formals, nargs, true)
-
- /** This variant allows keeping ByName parameters. Useed in NamesDefaults. */
- def formalTypes(formals: List[Type], nargs: Int, removeByName: Boolean): List[Type] = {
+ def formalTypes(formals: List[Type], nargs: Int, removeByName: Boolean = true, removeRepeated: Boolean = true): List[Type] = {
val formals1 = if (removeByName) formals mapConserve {
case TypeRef(_, sym, List(arg)) if (sym == ByNameParamClass) => arg
case formal => formal
} else formals
- if (isVarArgTpes(formals1)) {
+ if (isVarArgTpes(formals1) && (removeRepeated || formals.length != nargs)) {
val ft = formals1.last.normalize.typeArgs.head
formals1.init ::: (for (i <- List.range(formals1.length - 1, nargs)) yield ft)
} else formals1
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index fcafbc3b4c..d846412185 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -251,18 +251,32 @@ trait NamesDefaults { self: Analyzer =>
val context = blockTyper.context
val symPs = (args, paramTypes).zipped map ((arg, tpe) => {
val byName = tpe.typeSymbol == ByNameParamClass
+ val (argTpe, repeated) =
+ if (tpe.typeSymbol == RepeatedParamClass) arg match {
+ case Typed(expr, tpt @ Ident(name)) if name == nme.WILDCARD_STAR.toTypeName =>
+ (expr.tpe, true)
+ case _ =>
+ (seqType(arg.tpe), true)
+ } else (arg.tpe, false)
val s = context.owner.newValue(arg.pos, unit.fresh.newName(arg.pos, "x$"))
- val valType = if (byName) functionType(List(), arg.tpe)
- else arg.tpe
+ val valType = if (byName) functionType(List(), argTpe)
+ else if (repeated) argTpe
+ else argTpe
s.setInfo(valType)
- (context.scope.enter(s), byName)
+ (context.scope.enter(s), byName, repeated)
})
(symPs, args).zipped map ((symP, arg) => {
- val (sym, byName) = symP
+ val (sym, byName, repeated) = symP
// resetAttrs required for #2290. given a block { val x = 1; x }, when wrapping into a function
// () => { val x = 1; x }, the owner of symbol x must change (to the apply method of the function).
val body = if (byName) blockTyper.typed(Function(List(), resetLocalAttrs(arg)))
- else arg
+ else if (repeated) arg match {
+ case Typed(expr, tpt @ Ident(name)) if name == nme.WILDCARD_STAR.toTypeName =>
+ expr
+ case _ =>
+ val factory = Select(gen.mkAttributedRef(SeqModule), nme.apply)
+ blockTyper.typed(Apply(factory, List(resetLocalAttrs(arg))))
+ } else arg
atPos(body.pos)(ValDef(sym, body).setType(NoType))
})
}
@@ -290,7 +304,7 @@ trait NamesDefaults { self: Analyzer =>
// ValDef's in the block), change the arguments to these local values.
case Apply(expr, typedArgs) =>
// typedArgs: definition-site order
- val formals = formalTypes(expr.tpe.paramTypes, typedArgs.length, false)
+ val formals = formalTypes(expr.tpe.paramTypes, typedArgs.length, false, false)
// valDefs: call-site order
val valDefs = argValDefs(reorderArgsInv(typedArgs, argPos),
reorderArgsInv(formals, argPos),
@@ -301,6 +315,7 @@ trait NamesDefaults { self: Analyzer =>
atPos(vDef.pos.focus) {
// for by-name parameters, the local value is a nullary function returning the argument
if (tpe.typeSymbol == ByNameParamClass) Apply(ref, List())
+ else if (tpe.typeSymbol == RepeatedParamClass) Typed(ref, Ident(nme.WILDCARD_STAR.toTypeName))
else ref
}
})
diff --git a/test/files/run/names-defaults.check b/test/files/run/names-defaults.check
index 5b271a5d28..2c940b6211 100644
--- a/test/files/run/names-defaults.check
+++ b/test/files/run/names-defaults.check
@@ -109,3 +109,13 @@ List(1, 2)
1
2
3
+3
+3
+3
+3
+3
+3
+3
+3
+3
+3
diff --git a/test/files/run/names-defaults.scala b/test/files/run/names-defaults.scala
index 2a50d26cdd..5e84b9c132 100644
--- a/test/files/run/names-defaults.scala
+++ b/test/files/run/names-defaults.scala
@@ -367,6 +367,23 @@ object Test extends Application {
println(deprNam2.g(x = "sljkfd"))
+ // #3697
+ object t3697 {
+ def a(x: Int*)(s: Int = 3) = s
+ def b(a: Int, b: Int, c: Int*) = a + b
+ }
+ println(t3697.a(Seq(3): _*)())
+ println(t3697.a(3)())
+ println(t3697.a()())
+ println(t3697.a(2,3,1)())
+ println(t3697.b(a = 1, b = 2))
+ println(t3697.b(a = 1, b = 2, 3))
+ println(t3697.b(b = 1, a = 2, c = 3))
+ println(t3697.b(a = 1, b = 2, 3, 4))
+ println(t3697.b(a = 1, b = 2, Seq(3, 4): _*))
+ println(t3697.b(b = 1, a = 2, c = Seq(3, 4): _*))
+
+
// DEFINITIONS
def test1(a: Int, b: String) = println(a +": "+ b)
def test2(u: Int, v: Int)(k: String, l: Int) = println(l +": "+ k +", "+ (u + v))