diff options
author | Lukas Rytz <lukas.rytz@typesafe.com> | 2014-07-14 17:15:50 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2014-07-14 17:15:50 +0200 |
commit | 854de2dc0b209888d487f958e54cd05526cfd3f1 (patch) | |
tree | 063a6f65510611fae7aa3669775317b50b27cb6e /src | |
parent | efe4f63fa13bf734eb44e5fa5fab62587260e808 (diff) | |
parent | c39c693f81cdf4d86a6c13bee48fcbc4006fb3bc (diff) | |
download | scala-854de2dc0b209888d487f958e54cd05526cfd3f1.tar.gz scala-854de2dc0b209888d487f958e54cd05526cfd3f1.tar.bz2 scala-854de2dc0b209888d487f958e54cd05526cfd3f1.zip |
Merge pull request #3871 from lrytz/t8117
SI-8117 Fix bug when mixing well-positioned named and positional args
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 43902d1c65..b6387fd56b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -379,18 +379,37 @@ trait NamesDefaults { self: Analyzer => def makeNamedTypes(syms: List[Symbol]) = syms map (sym => NamedType(sym.name, sym.tpe)) - def missingParams[T](args: List[T], params: List[Symbol], argName: T => Option[Name] = nameOfNamedArg _): (List[Symbol], Boolean) = { - val namedArgs = args.dropWhile(arg => { - val n = argName(arg) - n.isEmpty || params.forall(p => p.name != n.get) - }) - val namedParams = params.drop(args.length - namedArgs.length) - // missing: keep those with a name which doesn't exist in namedArgs - val missingParams = namedParams.filter(p => namedArgs.forall(arg => { + /** + * Returns the parameter symbols of an invocation expression that are not defined by the list + * of arguments. + * + * @param args The list of arguments + * @param params The list of parameter sybols of the invoked method + * @param argName A function that extracts the name of an argument expression, if it is a named argument. + */ + def missingParams[T](args: List[T], params: List[Symbol], argName: T => Option[Name]): (List[Symbol], Boolean) = { + // The argument list contains first a mix of positional args and named args that are on the + // right parameter position, and then a number or named args on different positions. + + // collect all named arguments whose position does not match the parameter they define + val namedArgsOnChangedPosition = args.zip(params) dropWhile { + case (arg, param) => + val n = argName(arg) + // drop the argument if + // - it's not named, or + // - it's named, but defines the parameter on its current position, or + // - it's named, but none of the parameter names matches (treated as a positional argument, an assignment expression) + n.isEmpty || n.get == param.name || params.forall(_.name != n.get) + } map (_._1) + + val paramsWithoutPositionalArg = params.drop(args.length - namedArgsOnChangedPosition.length) + + // missing parameters: those with a name which is not specified in one of the namedArgsOnChangedPosition + val missingParams = paramsWithoutPositionalArg.filter(p => namedArgsOnChangedPosition.forall { arg => val n = argName(arg) n.isEmpty || n.get != p.name - })) - val allPositional = missingParams.length == namedParams.length + }) + val allPositional = missingParams.length == paramsWithoutPositionalArg.length (missingParams, allPositional) } @@ -407,7 +426,7 @@ trait NamesDefaults { self: Analyzer => previousArgss: List[List[Tree]], params: List[Symbol], pos: scala.reflect.internal.util.Position, context: Context): (List[Tree], List[Symbol]) = { if (givenArgs.length < params.length) { - val (missing, positional) = missingParams(givenArgs, params) + val (missing, positional) = missingParams(givenArgs, params, nameOfNamedArg) if (missing forall (_.hasDefault)) { val defaultArgs = missing flatMap (p => { val defGetter = defaultGetter(p, context) |