Permalink
Browse files

SI-5543: Ctor default arg wrongly scoped (revised)

This patch fixes the motivating bug by detecting when a method is
the default arg getter for a constructor parameter.  That requires
fixing a secondary bug where an arbitrary string was used to encode
<init> in lieu of <init>.encode.  There is no speculative mangling.
  • Loading branch information...
som-snytt committed Apr 27, 2012
1 parent 2a9cce8 commit 77b577a5aeab782b64b39b3a812c35fdd8ab265a
@@ -260,7 +260,7 @@ class Flags extends ModifierFlags {
/** When a symbol for a default getter is created, it inherits these
* flags from the method with the default. Other flags applied at creation
* time are SYNTHETIC, DEFAULTPARAM, and possibly OVERRIDE.
* time are SYNTHETIC, DEFAULTPARAM, and possibly OVERRIDE, and maybe PRESUPER.
*/
final val DefaultGetterFlags = PRIVATE | PROTECTED | FINAL
@@ -272,6 +272,7 @@ trait StdNames {
val BITMAP_PREFIX = "bitmap$"
val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
val DEFAULT_GETTER_STRING = "$default$"
val DEFAULT_GETTER_INIT_STRING = "$lessinit$greater" // CONSTRUCTOR.encoded, less is more
val DO_WHILE_PREFIX = "doWhile$"
val EVIDENCE_PARAM_PREFIX = "evidence$"
val EXCEPTION_RESULT_PREFIX = "exceptionResult"
@@ -413,14 +414,19 @@ trait StdNames {
name.subName(0, name.length - SETTER_SUFFIX.length)
}
// Nominally, name$default$N, encoded for <init>
def defaultGetterName(name: Name, pos: Int): TermName = {
val prefix = if (isConstructorName(name)) "init" else name
val prefix = if (isConstructorName(name)) DEFAULT_GETTER_INIT_STRING else name
newTermName(prefix + DEFAULT_GETTER_STRING + pos)
}
// Nominally, name from name$default$N, CONSTRUCTOR for <init>
def defaultGetterToMethod(name: Name): TermName = {
val p = name.pos(DEFAULT_GETTER_STRING)
if (p < name.length) name.toTermName.subName(0, p)
else name.toTermName
if (p < name.length) {
val q = name.toTermName.subName(0, p)
// i.e., if (q.decoded == CONSTRUCTOR.toString) CONSTRUCTOR else q
if (q.toString == DEFAULT_GETTER_INIT_STRING) CONSTRUCTOR else q
} else name.toTermName
}
// If the name ends with $nn where nn are
@@ -4649,7 +4649,9 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser
case ddef @ DefDef(_, _, _, _, _, _) =>
// flag default getters for constructors. An actual flag would be nice. See SI-5543.
val flag = ddef.mods.hasDefaultFlag && nme.defaultGetterToMethod(sym.name) == nme.CONSTRUCTOR
//val flag = ddef.mods.hasDefaultFlag && ddef.mods.hasFlag(PRESUPER)
val flag = ddef.mods.hasDefaultFlag && sym.owner.isModuleClass &&
nme.defaultGetterToMethod(sym.name) == nme.CONSTRUCTOR
newTyper(context.makeNewScope(tree, sym)).constrTyperIf(flag).typedDefDef(ddef)
case tdef @ TypeDef(_, _, _, _) =>
@@ -10,7 +10,7 @@ object Test extends Function0[Int] {
}
object A {
val v = 5
// should happily coexist with default getters
// should happily coexist with default getters, in a happier world
def init(x: Function0[Int] = Test.this)(a: Int = v, b: Int = v * x()) = x.toString +", "+ a +", "+ b
override def toString = "A"
}

0 comments on commit 77b577a

Please sign in to comment.