summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala25
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala31
-rw-r--r--src/library/scala/concurrent/ops.scala19
-rw-r--r--test/files/neg/names-defaults-neg-ref.check16
-rw-r--r--test/files/neg/names-defaults-neg-ref.scala26
-rw-r--r--test/files/neg/names-defaults-neg.check11
-rw-r--r--test/files/neg/names-defaults-neg.scala6
-rw-r--r--test/files/run/names-defaults.scala7
9 files changed, 87 insertions, 58 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 25af71be19..c599404025 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -233,7 +233,9 @@ trait NamesDefaults { self: Analyzer =>
})
List.map2(symPs, args)((symP, arg) => {
val (sym, byName) = symP
- val body = if (byName) blockTyper.typed(Function(List(), arg))
+ // resetAttrs required for #2290. given a block { val x = 1; x }, when wrapping into a function
+ // () => { val x = 1; x }, the owner of symbol x must change (to the apply method of the function).
+ val body = if (byName) blockTyper.typed(Function(List(), resetAttrs(arg)))
else arg
atPos(body.pos)(ValDef(sym, body).setType(NoType))
})
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index be0c65c49b..5b1ec93ffb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -65,6 +65,30 @@ abstract class RefChecks extends InfoTransform {
var currentApplication: Tree = EmptyTree
var inPattern: Boolean = false
+ // only one overloaded alternative is allowed to define default arguments
+ private def checkDefaultsInOverloaded(clazz: Symbol) {
+ def check(members: List[Symbol]): Unit = members match {
+ case x :: xs =>
+ if (x.paramss.exists(_.exists(p => p.hasFlag(DEFAULTPARAM)))) {
+ val others = xs.filter(alt => {
+ alt.name == x.name &&
+ alt.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM))) &&
+ (!alt.isConstructor || alt.owner == x.owner) // constructors of different classes are allowed to have defaults
+ })
+ if (!others.isEmpty) {
+ val all = x :: others
+ val rest = if (all.exists(_.owner != clazz)) ".\nThe members with defaults are defined in "+
+ all.map(_.owner).mkString("", " and ", ".")
+ unit.error(clazz.pos, "in "+ clazz +", multiple overloaded alternatives of "+ x +
+ " define default arguments"+ rest)
+ }
+ }
+ check(xs)
+ case _ => ()
+ }
+ check(clazz.info.members)
+ }
+
// Override checking ------------------------------------------------------------
/** 1. Check all members of class `clazz' for overriding conditions.
@@ -891,6 +915,7 @@ abstract class RefChecks extends InfoTransform {
case Template(_, _, _) =>
localTyper = localTyper.atOwner(tree, currentOwner)
validateBaseTypes(currentOwner)
+ checkDefaultsInOverloaded(currentOwner)
checkAllOverrides(currentOwner)
case TypeTree() =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d3f568ef1b..2408e1b8c9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1550,30 +1550,9 @@ trait Typers { self: Analyzer =>
for (vparams <- ddef.vparamss; vparam <- vparams)
checkStructuralCondition(meth.owner, vparam)
- // only one overloaded method is allowed to have defaults
- if (phase.id <= currentRun.typerPhase.id &&
- meth.owner.isClass && meth.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM)))) {
- // 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(ps => ps.exists(_.hasFlag(DEFAULTPARAM)) && isRepeatedParamType(ps.last.tpe)))
- error(meth.pos, "a parameter section with a `*'-parameter is not allowed to have default arguments")
- }
+ if (phase.id <= currentRun.typerPhase.id && meth.owner.isClass &&
+ meth.paramss.exists(ps => ps.exists(_.hasFlag(DEFAULTPARAM)) && isRepeatedParamType(ps.last.tpe)))
+ error(meth.pos, "a parameter section with a `*'-parameter is not allowed to have default arguments")
treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -1835,7 +1814,9 @@ trait Typers { self: Analyzer =>
while ((e1 ne null) && e1.owner == scope) {
if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
(e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
- if (!e.sym.isErroneous && !e1.sym.isErroneous)
+ // default getters are defined twice when multiple overloads have defaults. an
+ // error for this is issued in RefChecks.checkDefaultsInOverloaded
+ if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasFlag(DEFAULTPARAM))
error(e.sym.pos, e1.sym+" is defined twice"+
{if(!settings.debug.value) "" else " in "+unit.toString})
e1 = scope.lookupNextEntry(e1);
diff --git a/src/library/scala/concurrent/ops.scala b/src/library/scala/concurrent/ops.scala
index 67ef093847..3606869350 100644
--- a/src/library/scala/concurrent/ops.scala
+++ b/src/library/scala/concurrent/ops.scala
@@ -20,12 +20,7 @@ import scala.util.control.Exception.allCatch
*/
object ops
{
- // !!! I don't think this should be implicit, but it does need to be
- // made available as a default argument (difficult at present, see spawn.)
- // If it is merely implicit without being specified as a default, then it
- // will not be in scope for callers unless ops._ is first imported.
- implicit val defaultRunner: FutureTaskRunner =
- TaskRunners.threadRunner
+ val defaultRunner: FutureTaskRunner = TaskRunners.threadRunner
/**
* If expression computed successfully return it in <code>Right</code>,
@@ -49,12 +44,7 @@ object ops
*
* @param p the expression to evaluate
*/
- // !!! this should have a signature like:
- // def spawn(p: => Unit)(implicit runner: TaskRunner = defaultRunner): Unit
- // but at present the mixture of by-name argument and default implicit causes a crash.
-
- def spawn(p: => Unit): Unit = spawn(p, defaultRunner)
- def spawn(p: => Unit, runner: TaskRunner): Unit = {
+ def spawn(p: => Unit)(implicit runner: TaskRunner = defaultRunner): Unit = {
runner execute runner.functionAsTask(() => p)
}
@@ -62,10 +52,7 @@ object ops
* @param p ...
* @return ...
*/
- // See spawn above, this should have a signature like
- // def future[A](p: => A)(implicit runner: FutureTaskRunner = defaultRunner): () => A
- def future[A](p: => A): () => A = future[A](p, defaultRunner)
- def future[A](p: => A, runner: FutureTaskRunner): () => A = {
+ def future[A](p: => A)(implicit runner: FutureTaskRunner = defaultRunner): () => A = {
runner.futureAsFunction(runner submit runner.functionAsTask(() => p))
}
diff --git a/test/files/neg/names-defaults-neg-ref.check b/test/files/neg/names-defaults-neg-ref.check
new file mode 100644
index 0000000000..ac37816762
--- /dev/null
+++ b/test/files/neg/names-defaults-neg-ref.check
@@ -0,0 +1,16 @@
+names-defaults-neg-ref.scala:3: error: in anonymous class $anon, multiple overloaded alternatives of method f define default arguments.
+The members with defaults are defined in trait B2235 and trait A2235.
+ new A2235 with B2235
+ ^
+names-defaults-neg-ref.scala:7: error: in class A, multiple overloaded alternatives of method foo define default arguments()
+class A {
+ ^
+names-defaults-neg-ref.scala:17: error: in class C, multiple overloaded alternatives of method bar define default arguments.
+The members with defaults are defined in class C and class B.
+class C extends B {
+ ^
+names-defaults-neg-ref.scala:21: error: overriding method bar$default$1 in class B of type => String;
+ method bar$default$1 has incompatible type
+ def bar(i: Int = 129083) = i
+ ^
+four errors found
diff --git a/test/files/neg/names-defaults-neg-ref.scala b/test/files/neg/names-defaults-neg-ref.scala
new file mode 100644
index 0000000000..4611aadd22
--- /dev/null
+++ b/test/files/neg/names-defaults-neg-ref.scala
@@ -0,0 +1,26 @@
+object Test extends Application {
+ // #2235
+ new A2235 with B2235
+}
+
+// only one overloaded alternative is allowed to have defaults
+class A {
+ def foo(a: Int = 0) = a
+ def foo(b: String = "another") = b
+}
+
+class B {
+ def foo(a: Int) = a
+ def bar(u: String = "ldksj") = u
+}
+
+class C extends B {
+ override def foo(a: Int = 1092) = a
+ def foo(b: String = "lskdfj")
+
+ def bar(i: Int = 129083) = i
+}
+
+// #2235
+trait A2235 { def f(x: Int = 1) = x }
+trait B2235 { def f(x: String = "1") = x }
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index d8eb03fbaf..057a0519d7 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -104,13 +104,4 @@ names-defaults-neg.scala:83: error: type mismatch;
Error occured in an application involving default arguments.
new A2[String]()
^
-names-defaults-neg.scala:95: error: multiple overloaded alternatives of method foo define default arguments
- def foo(a: Int = 0) = a
- ^
-names-defaults-neg.scala:105: error: multiple overloaded alternatives of method foo define default arguments
- override def foo(a: Int = 1092) = a
- ^
-names-defaults-neg.scala:108: error: multiple overloaded alternatives of method bar define default arguments
- def bar(i: Int = 129083) = i
- ^
-28 errors found
+25 errors found
diff --git a/test/files/neg/names-defaults-neg.scala b/test/files/neg/names-defaults-neg.scala
index cf149d4b31..5829da361c 100644
--- a/test/files/neg/names-defaults-neg.scala
+++ b/test/files/neg/names-defaults-neg.scala
@@ -90,12 +90,6 @@ object Test extends Application {
def test8[T](x: => T) = println("test8")
}
-// only one overloaded alternative is allowed to have defaults
-class A {
- def foo(a: Int = 0) = a
- def foo(b: String = "another") = b
-}
-
class B {
def foo(a: Int) = a
def bar(u: String = "ldksj") = u
diff --git a/test/files/run/names-defaults.scala b/test/files/run/names-defaults.scala
index 8e8c8a1e4a..05f0afa199 100644
--- a/test/files/run/names-defaults.scala
+++ b/test/files/run/names-defaults.scala
@@ -251,6 +251,13 @@ object Test extends Application {
// (cannot call f using the default, List(1,2) doesn't match the param type)
+ // #2290
+ def spawn(a: Int, b: => Unit) = { () }
+ def t {
+ spawn(b = { val ttt = 1; ttt }, a = 0)
+ }
+
+
// 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))