summaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala29
2 files changed, 47 insertions, 12 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 =