diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala | 35 | ||||
-rw-r--r-- | test/files/run/names-defaults.check | 1 | ||||
-rw-r--r-- | test/files/run/names-defaults.scala | 8 |
3 files changed, 31 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 120a2efc4b..e8c78dbab2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -469,17 +469,16 @@ trait NamesDefaults { self: Analyzer => val reportAmbiguousErrors = typer.context.reportAmbiguousErrors typer.context.reportAmbiguousErrors = false + var variableNameClash = false val typedAssign = try { typer.silent(_.typed(arg, subst(paramtpe))) } catch { // `silent` only catches and returns TypeErrors which are not // CyclicReferences. Fix for #3685 case cr @ CyclicReference(sym, info) if sym.name == param.name => - // If this condition included sym.isMethod, #4041 issues a sensible - // error instead of crashing; but some programs which now compile would - // require a return type annotation. if (sym.isVariable || sym.isGetter && sym.accessed.isVariable) { // named arg not allowed + variableNameClash = true typer.context.error(sym.pos, "%s definition needs %s because '%s' is used as a named argument in its body.".format( "variable", // "method" @@ -491,16 +490,25 @@ trait NamesDefaults { self: Analyzer => } else cr } + + def applyNamedArg = { + // if the named argument is on the original parameter + // position, positional after named is allowed. + if (index != pos) + positionalAllowed = false + argPos(index) = pos + rhs + } + val res = typedAssign match { - case _: TypeError => - // if the named argument is on the original parameter - // position, positional after named is allowed. - if (index != pos) - positionalAllowed = false - argPos(index) = pos - rhs + case _: TypeError => applyNamedArg + case t: Tree => - if (!t.isErroneous) { + if (t.isErroneous && !variableNameClash) { + applyNamedArg + } else if (t.isErroneous) { + t // name clash with variable. error was already reported above. + } else { // This throws an exception which is caught in `tryTypedApply` (as it // uses `silent`) - unfortunately, tryTypedApply recovers from the // exception if you use errorTree(arg, ...) and conforms is allowed as @@ -513,9 +521,10 @@ trait NamesDefaults { self: Analyzer => // is called, and EmptyTree can only be typed NoType. Thus we need to // disable conforms as a view... errorTree(arg, "reference to "+ name +" is ambiguous; it is both, a parameter\n"+ - "name of the method and the name of a variable currently in scope.") - } else t // error was reported above + "name of the method and the name of a variable currently in scope.") + } } + typer.context.reportAmbiguousErrors = reportAmbiguousErrors //@M note that we don't get here when an ambiguity was detected (during the computation of res), // as errorTree throws an exception diff --git a/test/files/run/names-defaults.check b/test/files/run/names-defaults.check index 2c940b6211..5656d1a276 100644 --- a/test/files/run/names-defaults.check +++ b/test/files/run/names-defaults.check @@ -119,3 +119,4 @@ List(1, 2) 3 3 3 +(1,0), (1,2) diff --git a/test/files/run/names-defaults.scala b/test/files/run/names-defaults.scala index 2d1d7417e4..4a69842650 100644 --- a/test/files/run/names-defaults.scala +++ b/test/files/run/names-defaults.scala @@ -385,6 +385,14 @@ object Test extends App { println(t3697.b(b = 1, a = 2, c = Seq(3, 4): _*)) + // #4041 + object t4041 { + def _1 = (0, 0) copy (_1 = 1) + def _2 = (1, 1) copy (_2 = 2) + } + println(""+ t4041._1 +", "+ t4041._2) + + // 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)) |