git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@18772 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
f6f5b1d9d7
commit
0ef0cf9371
|
@ -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))
|
||||
})
|
||||
|
|
|
@ -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() =>
|
||||
|
|
|
@ -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)))
|
||||
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);
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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 }
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue