summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2009-06-02 14:33:05 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2009-06-02 14:33:05 +0000
commit115dcf1b3d42274fde2f78dfd87b60b8a059592c (patch)
treed3221aaf8b605ee3b76b3f64495fbce4dcf99900
parentda8b3a4b9d5010d20daeac76aeb13560035b63cb (diff)
downloadscala-115dcf1b3d42274fde2f78dfd87b60b8a059592c.tar.gz
scala-115dcf1b3d42274fde2f78dfd87b60b8a059592c.tar.bz2
scala-115dcf1b3d42274fde2f78dfd87b60b8a059592c.zip
named argument disallowed when assignment expre...
named argument disallowed when assignment expression would typecheck. minor fixe to names / defaults.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala29
-rw-r--r--test/files/neg/names-defaults-neg.check24
-rw-r--r--test/files/run/names-defaults.check4
-rw-r--r--test/files/run/names-defaults.scala9
5 files changed, 68 insertions, 28 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 55a409775b..5ccc22f4dd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -349,7 +349,7 @@ trait NamesDefaults { self: Analyzer =>
// @LUC TODO: make faster (don't use zipWithIndex)
val namelessArgs = for ((arg, index) <- (args.zipWithIndex)) yield arg match {
case Assign(Ident(name), rhs) =>
- val pos = params.findIndexOf(p => p.name == name && !p.hasFlag(SYNTHETIC))
+ val pos = params.indexWhere(p => p.name == name && !p.hasFlag(SYNTHETIC))
if (pos == -1) {
if (positionalAllowed) {
argPos(index) = index
@@ -362,9 +362,31 @@ trait NamesDefaults { self: Analyzer =>
} else if (argPos contains pos) {
errorTree(arg, "parameter specified twice: "+ name)
} else {
- positionalAllowed = false
- argPos(index) = pos
- rhs
+ // for named arguments, check wether the assignment expression would
+ // typecheck. if it does, report an ambiguous error.
+ val param = params(pos)
+ val paramtpe = params(pos).tpe.cloneInfo(param)
+ // replace type parameters by wildcard. in the below example we need to
+ // typecheck (x = 1) with wildcard (not T) so that it succeeds.
+ // def f[T](x: T) = x
+ // var x = 0
+ // f(x = 1) << "x = 1" typechecks with expected type WildcardType
+ val udp = typer.context.extractUndetparams()
+ val subst = new SubstTypeMap(udp, udp map (_ => WildcardType))
+ val res = typer.silent(_.typed(arg, subst(paramtpe))) match {
+ case _: TypeError =>
+ positionalAllowed = false
+ argPos(index) = pos
+ // if `rhs' has the form `x = ...`, wrap it into a block, prevent
+ // treating it as named argument again.
+ if (isNamed(rhs)) Block(List(), rhs)
+ else rhs
+ case t: Tree =>
+ 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.")
+ }
+ typer.context.undetparams = udp
+ res
}
case _ =>
argPos(index) = index
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 02f6d20522..89cfcb21e2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1510,12 +1510,23 @@ trait Typers { self: Analyzer =>
// only one overloaded method is allowed to have defaults
if (meth.owner.isClass && meth.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM)))) {
- val overloads = meth.owner.info.member(meth.name)
- val otherHasDefault = overloads.filter(alt => {
- alt != meth && alt.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM)))
- }) != NoSymbol
- if (otherHasDefault)
- error(meth.pos, "multiple overloaded alternatives of "+ meth +" define default arguments")
+ // don't do the check if it has already failed for another alternatvie
+ if (meth.paramss.exists(_.exists(p => p.hasFlag(DEFAULTPARAM) &&
+ !p.defaultGetter.tpe.isError))) {
+ val overloads = meth.owner.info.member(meth.name)
+ val others = overloads.filter(alt => {
+ alt != meth && alt.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM)))
+ })
+ if (others != NoSymbol) {
+ // setting `ErrorType' to defaultGetters prevents the error
+ // messages saying "foo$default$1 is defined twice"
+ for (ps <- meth.paramss; p <- ps)
+ if (p hasFlag DEFAULTPARAM) p.defaultGetter.setInfo(ErrorType)
+ for (alt <- others.alternatives; ps <- alt.paramss; p <- ps)
+ if (p hasFlag DEFAULTPARAM) p.defaultGetter.setInfo(ErrorType)
+ error(meth.pos, "multiple overloaded alternatives of "+ meth +" define default arguments")
+ }
+ }
if (meth.paramss.exists(_.exists(_.tpe.typeSymbol == RepeatedParamClass)))
error(meth.pos, "methods with `*'-parameters are not allowed to have default arguments")
@@ -2018,8 +2029,10 @@ trait Typers { self: Analyzer =>
if (allArgs.length == formals.length) {
// a default for each missing argument was found
val (namelessArgs, argPos) = removeNames(Typer.this)(allArgs, params)
- transformNamedApplication(Typer.this, mode, pt)(
- treeCopy.Apply(tree, fun1, namelessArgs), argPos)
+ if (namelessArgs exists (_.isErroneous)) setError(tree)
+ else
+ transformNamedApplication(Typer.this, mode, pt)(
+ treeCopy.Apply(tree, fun1, namelessArgs), argPos)
} else {
tryTupleApply.getOrElse {
val suffix =
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index 5e621c9690..c7f7b80ade 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -12,6 +12,10 @@ names-defaults-neg.scala:8: error: positional after named argument.
names-defaults-neg.scala:9: error: positional after named argument.
test1(b = "(*", 23)
^
+names-defaults-neg.scala:14: error: reference to x is ambiguous; it is both, a parameter
+name of the method and the name of a variable currently in scope.
+ test2(x = 1)
+ ^
names-defaults-neg.scala:16: error: not found: value c
test1(c = 0, b = "joke")
^
@@ -70,29 +74,17 @@ match argument types (a: Int,b: java.lang.String) and expected result type Any
names-defaults-neg.scala:75: error: multiple overloaded alternatives of method foo define default arguments
def foo(a: Int = 0) = a
^
-names-defaults-neg.scala:76: error: multiple overloaded alternatives of method foo define default arguments
- def foo(b: String = "another") = b
- ^
-names-defaults-neg.scala:76: error: method foo$default$1 is defined twice
- def foo(b: String = "another") = b
- ^
names-defaults-neg.scala:85: error: multiple overloaded alternatives of method foo define default arguments
override def foo(a: Int = 1092) = a
^
-names-defaults-neg.scala:86: error: multiple overloaded alternatives of method foo define default arguments
- def foo(b: String = "lskdfj")
- ^
-names-defaults-neg.scala:88: error: multiple overloaded alternatives of method bar define default arguments
- def bar(i: Int = 129083) = i
- ^
names-defaults-neg.scala:88: error: type mismatch;
found : Int(129083)
required: java.lang.String
def bar(i: Int = 129083) = i
^
-names-defaults-neg.scala:86: error: method foo$default$1 is defined twice
- def foo(b: String = "lskdfj")
- ^
+names-defaults-neg.scala:88: error: multiple overloaded alternatives of method bar define default arguments
+ def bar(i: Int = 129083) = i
+ ^
names-defaults-neg.scala:93: error: using named or default arguments in a super constructor call is not allowed
class B1 extends A1(10)
^
@@ -105,4 +97,4 @@ names-defaults-neg.scala:99: error: using named or default arguments in a self c
names-defaults-neg.scala:105: error: using named or default arguments in a self constructor call is not allowed
this(sep + b + sep)
^
-28 errors found
+25 errors found
diff --git a/test/files/run/names-defaults.check b/test/files/run/names-defaults.check
index eea0bdc51a..643615368d 100644
--- a/test/files/run/names-defaults.check
+++ b/test/files/run/names-defaults.check
@@ -88,3 +88,7 @@ Factory(-1,blabla)
Fact2(ju,1)
Fact2(1,1)
Fact2(10,blabla)
+test5
+2
+test5
+3 \ No newline at end of file
diff --git a/test/files/run/names-defaults.scala b/test/files/run/names-defaults.scala
index 01eebd42f8..38ba317029 100644
--- a/test/files/run/names-defaults.scala
+++ b/test/files/run/names-defaults.scala
@@ -167,6 +167,14 @@ object Test extends Application {
println(Fact2(10)().copy(y = "blabla")())
+ // assignment to var <-> named argument
+ var argName = 1
+ test5(argName = (argName = 2))
+ println(argName) // should be 2
+ test5({argName = 3; ()})
+ println(argName) // should be 3
+
+
// 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))
@@ -177,6 +185,7 @@ object Test extends Application {
def inner(b: Int = a, c: String) = println(b +": "+ c)
inner(c = "/")
}
+ def test5(argName: Unit) = println("test5")
}