Skip to content

Commit 0cf0f8a

Browse files
committed
Ensure type correctness in the presence of This -> proxy mappings
1 parent d46a5b9 commit 0cf0f8a

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
450450

451451
// The tree map to apply to the inlined tree. This maps references to this-types
452452
// and parameters to references of their arguments or their proxies.
453-
def treeMap(tree: Tree) = {
454-
tree match {
453+
def treeMap(tree: Tree) = tree match {
455454
case _: This =>
456455
tree.tpe match {
457456
case thistpe: ThisType =>
@@ -468,7 +467,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
468467
case None => tree
469468
}
470469
case _ => tree
471-
}}
470+
}
472471

473472
val inlineCtx = inlineContext(call)
474473
// The complete translation maps references to `this` and parameters to
@@ -519,9 +518,10 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
519518
* 5. Make sure that the tree's typing is idempotent (so that future -Ycheck passes succeed)
520519
*/
521520
private object InlineTyper extends ReTyper {
522-
523521
var retainedClosures = Set[Symbol]()
524522

523+
private val bindings = bindingsBuf.map(_.symbol)
524+
525525
override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context) = {
526526
val tree1 = super.typedIdent(tree, pt)
527527
tree1 match {
@@ -559,5 +559,18 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
559559
case _ =>
560560
super.typedApply(tree, pt)
561561
}
562+
563+
/** If expected type contans a reference rooted in a this-proxy,
564+
* the tree's type might still be a subtype of the same reference, but
565+
* rooted in the original `this`. In this case we insert a cast to ensure
566+
* the inlined code is type correct.
567+
*/
568+
override def adaptInterpolated(tree: Tree, pt: Type)(implicit ctx: Context) = {
569+
def refersToProxy(tr: NamedType) = tr.isTerm && bindings.contains(tr.symbol)
570+
val casted =
571+
if (tree.isType || pt.namedPartsWith(refersToProxy).isEmpty) tree
572+
else tree.ensureConforms(pt)
573+
super.adaptInterpolated(casted, pt)
574+
}
562575
}
563576
}

tests/pos/i3130b.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
trait F { def f(): Int }
21
class Outer {
2+
trait F { def f(): Int }
33
inline def inner: F = {
44
class InnerClass(x: Int) extends F {
55
def this() = this(3)

0 commit comments

Comments
 (0)