summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2010-08-05 08:20:47 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2010-08-05 08:20:47 +0000
commit23bd1501fc8aefecc3054c846973c05d260bb987 (patch)
treeb387765e88d41cd27797b5718cb5d97f1f6a31a0
parent8a8172da3cda740586f86a3b4b276e7d9235bca6 (diff)
downloadscala-23bd1501fc8aefecc3054c846973c05d260bb987.tar.gz
scala-23bd1501fc8aefecc3054c846973c05d260bb987.tar.bz2
scala-23bd1501fc8aefecc3054c846973c05d260bb987.zip
close #3685. review by moors.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala27
-rw-r--r--test/files/neg/names-defaults-neg.check28
-rw-r--r--test/files/neg/names-defaults-neg.scala47
3 files changed, 95 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index d783cf9c9f..fcafbc3b4c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -444,7 +444,20 @@ trait NamesDefaults { self: Analyzer =>
}
val reportAmbiguousErrors = typer.context.reportAmbiguousErrors
typer.context.reportAmbiguousErrors = false
- val res = typer.silent(_.typed(arg, subst(paramtpe))) match {
+
+ 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 (sym.isVariable || sym.isGetter && sym.accessed.isVariable) {
+ // named arg not allowed
+ typer.context.error(sym.pos, "variable definition needs type because the name is used as named argument the definition.")
+ typer.infer.setError(arg)
+ } else cr // named arg OK
+ }
+ val res = typedAssign match {
case _: TypeError =>
// if the named argument is on the original parameter
// position, positional after named is allowed.
@@ -453,13 +466,15 @@ trait NamesDefaults { self: Analyzer =>
argPos(index) = pos
rhs
case t: Tree =>
- // this throws an exception that's caught in `tryTypedApply` (as it uses `silent`)
- // unfortunately, tryTypedApply recovers from the exception if you use errorTree(arg, ...) and conforms is allowed as a view (see tryImplicit in Implicits)
- // because it tries to produce a new qualifier (if the old one was P, the new one will be conforms.apply(P)), and if that works, it pretends nothing happened
- // so, to make sure tryTypedApply fails, would like to pass EmptyTree instead of arg, but can't do that because eventually setType(ErrorType) is called, and EmptyTree only accepts NoType as its tpe
- // thus, we need to disable conforms as a view...
+ if (!t.isErroneous) {
+ // this throws an exception that's caught in `tryTypedApply` (as it uses `silent`)
+ // unfortunately, tryTypedApply recovers from the exception if you use errorTree(arg, ...) and conforms is allowed as a view (see tryImplicit in Implicits)
+ // because it tries to produce a new qualifier (if the old one was P, the new one will be conforms.apply(P)), and if that works, it pretends nothing happened
+ // so, to make sure tryTypedApply fails, would like to pass EmptyTree instead of arg, but can't do that because eventually setType(ErrorType) is called, and EmptyTree only accepts NoType as its tpe
+ // 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
}
typer.context.reportAmbiguousErrors = reportAmbiguousErrors
//@M note that we don't get here when an ambiguity was detected (during the computation of res),
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index ec786c5e03..1f77b828b7 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -132,5 +132,31 @@ names-defaults-neg.scala:131: error: parameter specified twice: a
names-defaults-neg.scala:132: error: wrong number of parameters; expected = 2
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
^
+names-defaults-neg.scala:140: error: variable definition needs type because the name is used as named argument the definition.
+ def t3 { var x = t.f(x = 1) }
+ ^
+names-defaults-neg.scala:143: error: variable definition needs type because the name is used as named argument the definition.
+ object t6 { var x = t.f(x = 1) }
+ ^
+names-defaults-neg.scala:146: error: variable definition needs type because the name is used as named argument the definition.
+ class t9 { var x = t.f(x = 1) }
+ ^
+names-defaults-neg.scala:160: error: variable definition needs type because the name is used as named argument the definition.
+ def u3 { var x = u.f(x = 1) }
+ ^
+names-defaults-neg.scala:163: error: variable definition needs type because the name is used as named argument the definition.
+ def u6 { var x = u.f(x = "32") }
+ ^
+names-defaults-neg.scala:166: error: reference to x is ambiguous; it is both, a parameter
+name of the method and the name of a variable currently in scope.
+ def u9 { var x: Int = u.f(x = 1) }
+ ^
+names-defaults-neg.scala:173: error: variable definition needs type because the name is used as named argument the definition.
+ class u15 { var x = u.f(x = 1) }
+ ^
+names-defaults-neg.scala:176: error: reference to x is ambiguous; it is both, a parameter
+name of the method and the name of a variable currently in scope.
+ class u18 { var x: Int = u.f(x = 1) }
+ ^
one warning found
-32 errors found
+40 errors found
diff --git a/test/files/neg/names-defaults-neg.scala b/test/files/neg/names-defaults-neg.scala
index 8d1ec4ce96..4350f9860d 100644
--- a/test/files/neg/names-defaults-neg.scala
+++ b/test/files/neg/names-defaults-neg.scala
@@ -131,3 +131,50 @@ object anfun {
val taf3 = testAnnFun(b = _: String, a = get(8))
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
}
+
+object t3685 {
+ object t { def f(x: Int) = x }
+
+ def t1 { def x = t.f(x = 1) }
+ def t2 { val x = t.f(x = 1) }
+ def t3 { var x = t.f(x = 1) }
+ object t4 { def x = t.f(x = 1) }
+ object t5 { val x = t.f(x = 1) }
+ object t6 { var x = t.f(x = 1) }
+ class t7 { def x = t.f(x = 1) }
+ class t8 { val x = t.f(x = 1) }
+ class t9 { var x = t.f(x = 1) }
+
+ def t10 { def x: Int = t.f(x = 1) }
+ def t11 { val x: Int = t.f(x = 1) }
+ def t12 { var x: Int = t.f(x = 1) }
+ class t13 { def x: Int = t.f(x = 1) }
+ class t14 { val x: Int = t.f(x = 1) }
+ class t15 { var x: Int = t.f(x = 1) }
+
+
+ object u { def f[T](x: T) = 100 }
+
+ def u1 { def x = u.f(x = 1) }
+ def u2 { val x = u.f(x = 1) }
+ def u3 { var x = u.f(x = 1) }
+ def u4 { def x = u.f(x = "23") }
+ def u5 { val x = u.f(x = "32") }
+ def u6 { var x = u.f(x = "32") }
+ def u7 { def x: Int = u.f(x = 1) }
+ def u8 { val x: Int = u.f(x = 1) }
+ def u9 { var x: Int = u.f(x = 1) }
+ def u10 { def x: Int = u.f(x = "32") }
+ def u11 { val x: Int = u.f(x = "32") }
+ def u12 { var x: Int = u.f(x = "32") }
+
+ class u13 { def x = u.f(x = 1) }
+ class u14 { val x = u.f(x = 1) }
+ class u15 { var x = u.f(x = 1) }
+ class u16 { def x: Int = u.f(x = 1) }
+ class u17 { val x: Int = u.f(x = 1) }
+ class u18 { var x: Int = u.f(x = 1) }
+ class u19 { def x: Int = u.f(x = "32") }
+ class u20 { val x: Int = u.f(x = "32") }
+ class u21 { var x: Int = u.f(x = "32") }
+}