Skip to content

Commit

Permalink
ParamForwarding: do not require param accessors to be private[this]
Browse files Browse the repository at this point in the history
Also mark the forwarder as Stable otherwise we get a RefChecks error.

This fixes scala#608.
  • Loading branch information
smarter committed May 28, 2015
1 parent 9be3ee8 commit 9126119
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/dotty/tools/dotc/transform/ParamForwarding.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ class ParamForwarding(thisTransformer: DenotTransformer) {
stat match {
case stat: ValDef =>
val sym = stat.symbol.asTerm
if (sym is (PrivateLocalParamAccessor, butNot = Mutable)) {
if (sym is (ParamAccessor, butNot = Mutable)) {
val idx = superArgs.indexWhere(_.symbol == sym)
if (idx >= 0 && superParamNames(idx) == stat.name) { // supercall to like-named parameter
val alias = inheritedAccessor(sym)
if (alias.exists) {
def forwarder(implicit ctx: Context) = {
sym.copySymDenotation(initFlags = sym.flags | Method, info = sym.info.ensureMethodic)
sym.copySymDenotation(initFlags = sym.flags | Method | Stable, info = sym.info.ensureMethodic)
.installAfter(thisTransformer)
val superAcc =
Super(This(currentClass), tpnme.EMPTY, inConstrCall = false).select(alias)
Expand Down
16 changes: 16 additions & 0 deletions tests/run/paramForwarding.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
B:
private final int B.theValue$$local
private final int B.theValueInB$$local
Bz:
private final int Bz.theValue$$local
private final int Bz.theValueInBz$$local
C:

D:
private final int D.other$$local
NonVal:

X:
private final int X.theValue$$local
Y:
private final int Y.theValue$$local
89 changes: 89 additions & 0 deletions tests/run/paramForwarding.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// A contains a field A.theValue$$local accessible using the
// generated getter A.theValue()
class A(val theValue: Int) {
val theValueInA = theValue // use the constructor parameter theValue

def getTheValue = theValue // virtual call to the getter theValue()
}

// B contains a field B.theValue$$local accessible using the getter
// B.theValue() which overrides A.theValue()
class B(override val theValue: Int) extends A(42) {
val theValueInB = theValue
}

// Bz contains a field Bz.theValue$$local accessible using the getter
// Bz.theValue() which overrides A.theValue()
class Bz extends A(42) {
override val theValue: Int = 10
val theValueInBz = theValue
}

// C does not contains a field C.theValue$$local, it contains
// a getter C.theValue() which only calls super.theValue()
class C(override val theValue: Int) extends A(theValue)

// D contains a field D.other$$local and a corresponding getter.
class D(val other: Int) extends A(other)


// NonVal does not contain a field NonVal.theValue$$local.
class NonVal(theValue: Int) extends A(theValue) {
def getTheValueInNonVal = theValue // use the constructor parameter theValue
}

// X contains a field X.theValue$$local accessible using the getter
// X.theValue() which overrides A.theValue()
class X(override val theValue: Int) extends NonVal(0)

// Y contains a field Y.theValue$$local accessible using the getter
// Y.theValue() which overrides A.theValue()
class Y(override val theValue: Int) extends NonVal(theValue)


object Test {
def printFields(obj: Any) =
println(obj.getClass.getDeclaredFields.map(_.toString).sorted.deep.mkString("\n"))

def main(args: Array[String]): Unit = {
val b10 = new B(10)
val bz = new Bz
val c11 = new C(11)
val d12 = new D(12)
val nv13 = new NonVal(13)
val x14 = new X(14)
val y15 = new Y(15)

println("B:")
printFields(b10)
println("Bz:")
printFields(bz)
println("C:")
printFields(c11)
println("D:")
printFields(d12)
println("NonVal:")
printFields(nv13)
println("X:")
printFields(x14)
println("Y:")
printFields(y15)


assert(b10.getTheValue == 10)
assert(b10.theValue == 10)
assert(b10.theValueInB == 10)
assert(b10.theValueInA == 42)

assert(bz.getTheValue == 10)
assert(bz.theValue == 10)
assert(bz.theValueInBz == 10)
assert(bz.theValueInA == 42)


assert(x14.theValue == 14)
assert(x14.getTheValue == 14)
assert(x14.getTheValueInNonVal == 0)
assert(x14.theValueInA == 0)
}
}

0 comments on commit 9126119

Please sign in to comment.