Skip to content

Commit 285c90d

Browse files
committed
Verify symbol is a param by querying the reftree
In the HoistSuperArgs phase we have established which tree should be hoisted, and replace all references in the Tree with params that are accessible in the hoisted tree. When the Tree contains an anonymous class without parameters, the paramSyms of that class refer to the created 'fresh' super symbol (e.g. `B$superArg$1`), while the RefTree symbol belongs to the superclass `B`. This meant that the conditional was never satisfied, and the type was never replaced by the primary constructor argument of the generated superArg class. In the current design `treeMap` is called before `typeMap` on a given tree, thus the code in `treeMap` was never executed. This is mitigated by rewriting the check, to only take params or accessors into account in the scope of the hoisted tree.
1 parent 1b00033 commit 285c90d

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
116116
case _ => false
117117
}
118118

119+
/** Only rewire types that are owned by the current Hoister and is an param or accessor */
120+
def needsRewire(tp: Type) = tp match {
121+
case ntp: NamedType =>
122+
(ntp.symbol.owner == cls || ntp.symbol.owner == constr) && ntp.symbol.isParamOrAccessor
123+
case _ => false
124+
}
125+
119126
// begin hoistSuperArg
120127
arg match {
121128
case Apply(fn, arg1 :: Nil) if fn.symbol == defn.cbnArg =>
@@ -128,9 +135,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
128135
typeMap = new TypeMap {
129136
lazy val origToParam = origParams.zip(paramSyms).toMap
130137
def apply(tp: Type) = tp match {
131-
case tp: NamedType
132-
if (tp.symbol.owner == cls || tp.symbol.owner == constr) &&
133-
tp.symbol.isParamOrAccessor =>
138+
case tp: NamedType if needsRewire(tp) =>
134139
origToParam.get(tp.symbol) match {
135140
case Some(mappedSym) => if (tp.symbol.isType) mappedSym.typeRef else mappedSym.termRef
136141
case None => mapOver(tp)
@@ -140,7 +145,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
140145
}
141146
},
142147
treeMap = {
143-
case tree: RefTree if paramSyms.contains(tree.symbol) =>
148+
case tree: RefTree if needsRewire(tree.tpe) =>
144149
cpy.Ident(tree)(tree.name).withType(tree.tpe)
145150
case tree =>
146151
tree

tests/pos/i8748.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class A(a: String) extends B(new C {
2+
override def get(): String = a
3+
})
4+
5+
class B(c: C)
6+
7+
trait C {
8+
def get(): String
9+
}

tests/pos/i8786.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class B(y: Int) extends A(new C(y){})
2+
3+
class A(c: C)
4+
5+
abstract class C(y: Int) {
6+
def x: Int = y
7+
}

0 commit comments

Comments
 (0)