diff options
author | Lukas Rytz <lukas.rytz@epfl.ch> | 2009-09-24 12:45:00 +0000 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@epfl.ch> | 2009-09-24 12:45:00 +0000 |
commit | 593d685e4fa50cf087bfc89a208ed2c89d2407c1 (patch) | |
tree | 04d0a413a11f9ccd96fc3a347602c8d3a7437f5a /src/compiler/scala/tools/nsc | |
parent | ad9103538dec453a5e8a40a750ed3cc664296f68 (diff) | |
download | scala-593d685e4fa50cf087bfc89a208ed2c89d2407c1.tar.gz scala-593d685e4fa50cf087bfc89a208ed2c89d2407c1.tar.bz2 scala-593d685e4fa50cf087bfc89a208ed2c89d2407c1.zip |
fixed #2290 and #2325
Diffstat (limited to 'src/compiler/scala/tools/nsc')
3 files changed, 34 insertions, 26 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); |