diff options
author | Lukas Rytz <lukas.rytz@epfl.ch> | 2010-08-05 20:17:38 +0000 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@epfl.ch> | 2010-08-05 20:17:38 +0000 |
commit | 20efb133c53be74160d711286a99d3cd6d751fdf (patch) | |
tree | 912d89829ac43b8f5af7d055ff8c1ddb1cb5d15c /src/compiler | |
parent | 0a787b6477311a718cbb6abec15df9dfdc12186e (diff) | |
download | scala-20efb133c53be74160d711286a99d3cd6d751fdf.tar.gz scala-20efb133c53be74160d711286a99d3cd6d751fdf.tar.bz2 scala-20efb133c53be74160d711286a99d3cd6d751fdf.zip |
fixes names/defaults when using :_* for specify...
fixes names/defaults when using :_* for specifying repeated parameters.
close #3697, no review.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 12 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala | 27 |
2 files changed, 25 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 } }) |