Skip to content

Commit 3189fd9

Browse files
committed
ParamForwarding: do not require param accessors to be private[this]
Also mark the forwarder as Stable otherwise we get a RefChecks error. This fixes #608.
1 parent c0b6930 commit 3189fd9

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

src/dotty/tools/dotc/transform/ParamForwarding.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ class ParamForwarding(thisTransformer: DenotTransformer) {
4343
stat match {
4444
case stat: ValDef =>
4545
val sym = stat.symbol.asTerm
46-
if (sym is (PrivateLocalParamAccessor, butNot = Mutable)) {
46+
if (sym is (ParamAccessor, butNot = Mutable)) {
4747
val idx = superArgs.indexWhere(_.symbol == sym)
4848
if (idx >= 0 && superParamNames(idx) == stat.name) { // supercall to like-named parameter
4949
val alias = inheritedAccessor(sym)
5050
if (alias.exists) {
5151
def forwarder(implicit ctx: Context) = {
52-
sym.copySymDenotation(initFlags = sym.flags | Method, info = sym.info.ensureMethodic)
52+
sym.copySymDenotation(initFlags = sym.flags | Method | Stable, info = sym.info.ensureMethodic)
5353
.installAfter(thisTransformer)
5454
val superAcc =
5555
Super(This(currentClass), tpnme.EMPTY, inConstrCall = false).select(alias)

tests/run/paramForwarding.check

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
B:
2+
private final int B.theValue$$local
3+
private final int B.theValueInB$$local
4+
Bz:
5+
private final int Bz.theValue$$local
6+
private final int Bz.theValueInBz$$local
7+
C:
8+
9+
D:
10+
private final int D.other$$local
11+
NonVal:
12+
13+
X:
14+
private final int X.theValue$$local
15+
Y:
16+
private final int Y.theValue$$local

tests/run/paramForwarding.scala

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// A contains a field A.theValue$$local accessible using the
2+
// generated getter A.theValue()
3+
class A(val theValue: Int) {
4+
val theValueInA = theValue // use the constructor parameter theValue
5+
6+
def getTheValue = theValue // virtual call to the getter theValue()
7+
}
8+
9+
// B contains a field B.theValue$$local accessible using the getter
10+
// B.theValue() which overrides A.theValue()
11+
class B(override val theValue: Int) extends A(42) {
12+
val theValueInB = theValue
13+
}
14+
15+
// Bz contains a field Bz.theValue$$local accessible using the getter
16+
// Bz.theValue() which overrides A.theValue()
17+
class Bz extends A(42) {
18+
override val theValue: Int = 10
19+
val theValueInBz = theValue
20+
}
21+
22+
// C does not contains a field C.theValue$$local, it contains
23+
// a getter C.theValue() which only calls super.theValue()
24+
class C(override val theValue: Int) extends A(theValue)
25+
26+
// D contains a field D.other$$local and a corresponding getter.
27+
class D(val other: Int) extends A(other)
28+
29+
30+
// NonVal does not contain a field NonVal.theValue$$local.
31+
class NonVal(theValue: Int) extends A(theValue) {
32+
def getTheValueInNonVal = theValue // use the constructor parameter theValue
33+
}
34+
35+
// X contains a field X.theValue$$local accessible using the getter
36+
// X.theValue() which overrides A.theValue()
37+
class X(override val theValue: Int) extends NonVal(0)
38+
39+
// Y contains a field Y.theValue$$local accessible using the getter
40+
// Y.theValue() which overrides A.theValue()
41+
class Y(override val theValue: Int) extends NonVal(theValue)
42+
43+
44+
object Test {
45+
def printFields(obj: Any) =
46+
println(obj.getClass.getDeclaredFields.map(_.toString).sorted.deep.mkString("\n"))
47+
48+
def main(args: Array[String]): Unit = {
49+
val b10 = new B(10)
50+
val bz = new Bz
51+
val c11 = new C(11)
52+
val d12 = new D(12)
53+
val nv13 = new NonVal(13)
54+
val x14 = new X(14)
55+
val y15 = new Y(15)
56+
57+
println("B:")
58+
printFields(b10)
59+
println("Bz:")
60+
printFields(bz)
61+
println("C:")
62+
printFields(c11)
63+
println("D:")
64+
printFields(d12)
65+
println("NonVal:")
66+
printFields(nv13)
67+
println("X:")
68+
printFields(x14)
69+
println("Y:")
70+
printFields(y15)
71+
72+
73+
assert(b10.getTheValue == 10)
74+
assert(b10.theValue == 10)
75+
assert(b10.theValueInB == 10)
76+
assert(b10.theValueInA == 42)
77+
78+
assert(bz.getTheValue == 10)
79+
assert(bz.theValue == 10)
80+
assert(bz.theValueInBz == 10)
81+
assert(bz.theValueInA == 42)
82+
83+
84+
assert(x14.theValue == 14)
85+
assert(x14.getTheValue == 14)
86+
assert(x14.getTheValueInNonVal == 0)
87+
assert(x14.theValueInA == 0)
88+
}
89+
}

0 commit comments

Comments
 (0)