diff options
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform')
3 files changed, 21 insertions, 19 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 34ea2bc6f..3857b405f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -415,7 +415,7 @@ object Erasure extends TypeTestsCasts{ if (tree.symbol == ctx.owner.lexicallyEnclosingClass || tree.symbol.isStaticOwner) promote(tree) else { ctx.log(i"computing outer path from ${ctx.owner.ownersIterator.toList}%, % to ${tree.symbol}, encl class = ${ctx.owner.enclosingClass}") - outer.path(tree.symbol) + outer.path(toCls = tree.symbol) } private def runtimeCallWithProtoArgs(name: Name, pt: Type, args: Tree*)(implicit ctx: Context): Tree = { diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 3cfbdf454..d75c32fcc 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -60,7 +60,8 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf /** Convert a selection of the form `qual.C_<OUTER>` to an outer path from `qual` to `C` */ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = if (tree.name.isOuterSelect) - outer.path(tree.tpe.widen.classSymbol, tree.qualifier, outOfContext = true).ensureConforms(tree.tpe) + outer.path(start = tree.qualifier, count = tree.name.outerSelectHops) + .ensureConforms(tree.tpe) else tree /** First, add outer accessors if a class does not have them yet and it references an outer this. @@ -354,31 +355,32 @@ object ExplicitOuter { } else Nil } - /** The path of outer accessors that references `toCls.this` starting from - * node `start`, which defaults to the context owner's this node. - * @param outOfContext When true, we take the `path` in code that has been inlined - * from somewhere else. In that case, we need to stop not - * just when `toCls` is reached exactly, but also in any superclass - * of `treeCls`. This compensates the `asSeenFrom` logic - * used to compute this-proxies in Inliner. + /** A path of outer accessors starting from node `start`. `start` defaults to the + * context owner's this node. There are two alternative conditions that determine + * where the path ends: + * + * - if the initial `count` parameter is non-negative: where the number of + * outer accessors reaches count. + * - if the initial `count` parameter is negative: where the class symbol of + * the type of the reached tree matches `toCls`. */ - def path(toCls: Symbol, - start: Tree = This(ctx.owner.lexicallyEnclosingClass.asClass), - outOfContext: Boolean = false): Tree = try { - def loop(tree: Tree): Tree = { + def path(start: Tree = This(ctx.owner.lexicallyEnclosingClass.asClass), + toCls: Symbol = NoSymbol, + count: Int = -1): Tree = try { + def loop(tree: Tree, count: Int): Tree = { val treeCls = tree.tpe.widen.classSymbol val outerAccessorCtx = ctx.withPhaseNoLater(ctx.lambdaLiftPhase) // lambdalift mangles local class names, which means we cannot reliably find outer acessors anymore ctx.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)(outerAccessorCtx)} in $treeCls") - if (treeCls == toCls || outOfContext && toCls.derivesFrom(treeCls)) tree + if (count == 0 || count < 0 && treeCls == toCls) tree else { val acc = outerAccessor(treeCls.asClass)(outerAccessorCtx) assert(acc.exists, i"failure to construct path from ${ctx.owner.ownersIterator.toList}%/% to `this` of ${toCls.showLocated};\n${treeCls.showLocated} does not have an outer accessor") - loop(tree.select(acc).ensureApplied) + loop(tree.select(acc).ensureApplied, count - 1) } } ctx.log(i"computing outerpath to $toCls from ${ctx.outersIterator.map(_.owner).toList}") - loop(start) + loop(start, count) } catch { case ex: ClassCastException => throw new ClassCastException(i"no path exists from ${ctx.owner.enclosingClass} to $toCls") diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index 19fb3dd0c..b603a53dc 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -440,10 +440,10 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform singleton(clazz.thisType) else if (ctx.owner.isConstructor) outerParam.get(ctx.owner) match { - case Some(param) => outer.path(clazz, Ident(param.termRef)) - case _ => outer.path(clazz) + case Some(param) => outer.path(start = Ident(param.termRef), toCls = clazz) + case _ => outer.path(toCls = clazz) } - else outer.path(clazz) + else outer.path(toCls = clazz) transformFollowingDeep(qual.select(sym)) } |