Skip to content

Commit e9fecd3

Browse files
committed
Fix #1990: Handle case where inlining changes class of outer
The new situation in the test was that outer of the inlined method was `A` but it's as seen from type is a subtype `B`. We need two fixes: - Ignore outerSelects in TreeChecker. These are treated as having fixed symbols. - Adapt the outer-path logic to deal with code that's moved to another context.
1 parent 6df672c commit e9fecd3

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf
6060
/** Convert a selection of the form `qual.C_<OUTER>` to an outer path from `qual` to `C` */
6161
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
6262
if (tree.name.isOuterSelect)
63-
outer.path(tree.tpe.widen.classSymbol, tree.qualifier).ensureConforms(tree.tpe)
63+
outer.path(tree.tpe.widen.classSymbol, tree.qualifier, outOfContext = true).ensureConforms(tree.tpe)
6464
else tree
6565

6666
/** First, add outer accessors if a class does not have them yet and it references an outer this.
@@ -355,14 +355,21 @@ object ExplicitOuter {
355355
}
356356

357357
/** The path of outer accessors that references `toCls.this` starting from
358-
* the context owner's this node.
358+
* node `start`, which defaults to the context owner's this node.
359+
* @param outOfContext When true, we take the `path` in code that has been inlined
360+
* from somewhere else. In that case, we need to stop not
361+
* just when `toCls` is reached exactly, but also in any superclass
362+
* of `treeCls`. This compensates the `asSeenFrom` logic
363+
* used to compute this-proxies in Inliner.
359364
*/
360-
def path(toCls: Symbol, start: Tree = This(ctx.owner.lexicallyEnclosingClass.asClass)): Tree = try {
365+
def path(toCls: Symbol,
366+
start: Tree = This(ctx.owner.lexicallyEnclosingClass.asClass),
367+
outOfContext: Boolean = true): Tree = try {
361368
def loop(tree: Tree): Tree = {
362369
val treeCls = tree.tpe.widen.classSymbol
363370
val outerAccessorCtx = ctx.withPhaseNoLater(ctx.lambdaLiftPhase) // lambdalift mangles local class names, which means we cannot reliably find outer acessors anymore
364371
ctx.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)(outerAccessorCtx)} in $treeCls")
365-
if (treeCls == toCls) tree
372+
if (treeCls == toCls || outOfContext && toCls.derivesFrom(treeCls)) tree
366373
else {
367374
val acc = outerAccessor(treeCls.asClass)(outerAccessorCtx)
368375
assert(acc.exists,

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import core.Types._
1212
import core.Flags._
1313
import core.Constants._
1414
import core.StdNames._
15+
import core.NameOps._
1516
import core.Decorators._
1617
import core.TypeErasure.isErasedType
1718
import core.Phases.Phase
@@ -336,7 +337,10 @@ class TreeChecker extends Phase with SymTransformer {
336337
assert(tree.isTerm || !ctx.isAfterTyper, tree.show + " at " + ctx.phase)
337338
val tpe = tree.typeOpt
338339
val sym = tree.symbol
339-
if (!tpe.isInstanceOf[WithFixedSym] && sym.exists && !sym.is(Private)) {
340+
if (!tpe.isInstanceOf[WithFixedSym] &&
341+
sym.exists && !sym.is(Private) &&
342+
!tree.name.isOuterSelect // outer selects have effectively fixed symbols
343+
) {
340344
val qualTpe = tree.qualifier.typeOpt
341345
val member =
342346
if (sym.is(Private)) qualTpe.member(tree.name)

tests/pos/i1990.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class A {
2+
class Foo {
3+
inline def inlineMeth: Unit = {
4+
new Bar
5+
}
6+
}
7+
class Bar
8+
}
9+
10+
class B extends A {
11+
(new Foo).inlineMeth
12+
}

0 commit comments

Comments
 (0)