Skip to content

Commit 3b974c5

Browse files
authored
Avoid too eager transform of $outer for lhs & accessor rhs (#18949)
Fix #18927 The transformer in `mapOuter` in `Constructors` was transforming trees it should not: ```scala override def transform(tree: Tree)(using Context) = tree match { [....] case tree: RefTree if tree.symbol.is(ParamAccessor) && tree.symbol.name == nme.OUTER => ref(outerParam) [...] ``` There were two problems: - This case transformed LHS of `$outer` assignments in constructors. So, instead of setting the `$outer` field in the current class with the constructor, it was replaced with the $outer of the outer class. That resulted in not assigning any value to the `$outer` in inner class, and double assignment to the val in outer class. - LHS of the accessor def was also transformed, so it was evaluated to the `$outer` of the outer class. This only happened when the nested class is created in the secondary constructor, as the primary constructor is not transformed (only the template body)
2 parents 7d2cad5 + 2ff4ba7 commit 3b974c5

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

compiler/src/dotty/tools/dotc/transform/Constructors.scala

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Symbols.*
1515
import Decorators.*
1616
import DenotTransformers.*
1717
import collection.mutable
18+
import Types.*
1819

1920
object Constructors {
2021
val name: String = "constructors"
@@ -197,6 +198,10 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
197198
) &&
198199
fn.symbol.info.resultType.classSymbol == outerParam.info.classSymbol =>
199200
ref(outerParam)
201+
case Assign(lhs, rhs) if lhs.symbol.name == nme.OUTER => // not transform LHS of assignment to $outer field
202+
cpy.Assign(tree)(lhs, super.transform(rhs))
203+
case dd: DefDef if dd.name.endsWith(nme.OUTER.asSimpleName) => // not transform RHS of outer accessor
204+
dd
200205
case tree: RefTree if tree.symbol.is(ParamAccessor) && tree.symbol.name == nme.OUTER =>
201206
ref(outerParam)
202207
case _ =>

tests/pos/i18927.scala

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class A
2+
3+
class B {
4+
val a = new A
5+
6+
class C(i: Int) {
7+
def this() = {
8+
this(1)
9+
class Inner() {
10+
println(a)
11+
}
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)