diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ElimStaticThis.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ExplicitOuter.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/LambdaLift.scala | 22 |
5 files changed, 24 insertions, 19 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 41e77c61f..d7ef44144 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -67,8 +67,8 @@ class Compiler { new Constructors, new FunctionalInterfaces), List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here - new Flatten, new ElimStaticThis, + new Flatten, new RestoreScopes), List(/*new PrivateToStatic,*/ new ExpandPrivate, diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index c1b2e20eb..b00896117 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -231,6 +231,9 @@ object Contexts { final def withPhase(phase: Phase): Context = withPhase(phase.id) + final def withPhaseNoLater(phase: Phase) = + if (ctx.phase.id > phase.id) withPhase(phase) else ctx + /** If -Ydebug is on, the top of the stack trace where this context * was created, otherwise `null`. */ diff --git a/src/dotty/tools/dotc/transform/ElimStaticThis.scala b/src/dotty/tools/dotc/transform/ElimStaticThis.scala index c60990477..7df29b0b0 100644 --- a/src/dotty/tools/dotc/transform/ElimStaticThis.scala +++ b/src/dotty/tools/dotc/transform/ElimStaticThis.scala @@ -9,7 +9,6 @@ import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.SymDenotations.SymDenotation import TreeTransforms.{MiniPhaseTransform, TransformerInfo} import dotty.tools.dotc.core.Types.{ThisType, TermRef} -import Phases.Phase /** Replace This references to module classes in static methods by global identifiers to the * corresponding modules. @@ -18,8 +17,6 @@ class ElimStaticThis extends MiniPhaseTransform { import ast.tpd._ def phaseName: String = "elimStaticThis" - override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Flatten]) - override def transformThis(tree: This)(implicit ctx: Context, info: TransformerInfo): Tree = if (!tree.symbol.is(Package) && ctx.owner.enclosingMethod.is(JavaStatic)) { assert(tree.symbol.is(ModuleClass)) @@ -28,12 +25,10 @@ class ElimStaticThis extends MiniPhaseTransform { else tree override def transformIdent(tree: tpd.Ident)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { - val meth = ctx.owner.enclosingMethod - // We cannot use meth.enclosingClass because it skips other static classes, - // so instead we require this phase to run after Flatten and use meth.owner - if (meth.is(JavaStatic) && meth.owner.is(ModuleClass)) { + if (ctx.owner.enclosingMethod.is(JavaStatic)) { tree.tpe match { - case TermRef(thiz: ThisType, _) if (thiz.underlying.typeSymbol == meth.owner) => + case TermRef(thiz: ThisType, _) => + assert(thiz.underlying.typeSymbol.is(ModuleClass)) ref(thiz.underlying.typeSymbol.sourceModule).select(tree.symbol) case _ => tree } diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 70a4f299a..0fa429d6e 100644 --- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -299,9 +299,10 @@ object ExplicitOuter { def path(toCls: Symbol): Tree = try { def loop(tree: Tree): Tree = { val treeCls = tree.tpe.widen.classSymbol - ctx.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)}") + 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) tree - else loop(tree select outerAccessor(treeCls.asClass)) + else loop(tree select outerAccessor(treeCls.asClass)(outerAccessorCtx)) } ctx.log(i"computing outerpath to $toCls from ${ctx.outersIterator.map(_.owner).toList}") loop(This(ctx.owner.enclosingClass.asClass)) diff --git a/src/dotty/tools/dotc/transform/LambdaLift.scala b/src/dotty/tools/dotc/transform/LambdaLift.scala index 42c6e85af..bffc7458e 100644 --- a/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -94,7 +94,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform * than the previous value of `liftedowner(sym)`. */ def narrowLiftedOwner(sym: Symbol, owner: Symbol)(implicit ctx: Context) = { - if (sym.owner.isTerm && + if (sym.maybeOwner.isTerm && owner.isProperlyContainedIn(liftedOwner(sym)) && owner != sym) { ctx.log(i"narrow lifted $sym to $owner") @@ -189,10 +189,9 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform val sym = tree.symbol def narrowTo(thisClass: ClassSymbol) = { val enclClass = enclosure.enclosingClass - if (!thisClass.isStaticOwner) - narrowLiftedOwner(enclosure, - if (enclClass.isContainedIn(thisClass)) thisClass - else enclClass) // unknown this reference, play it safe and assume the narrowest possible owner + narrowLiftedOwner(enclosure, + if (enclClass.isContainedIn(thisClass)) thisClass + else enclClass) // unknown this reference, play it safe and assume the narrowest possible owner } tree match { case tree: Ident => @@ -210,8 +209,15 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform case tree: This => narrowTo(tree.symbol.asClass) case tree: DefDef => - if (sym.owner.isTerm && !sym.is(Label)) liftedOwner(sym) = sym.topLevelClass.owner - else if (sym.isPrimaryConstructor && sym.owner.owner.isTerm) symSet(called, sym) += sym.owner + if (sym.owner.isTerm && !sym.is(Label)) + liftedOwner(sym) = sym.enclosingClass.topLevelClass + // this will make methods in supercall constructors of top-level classes owned + // by the enclosing package, which means they will be static. + // On the other hand, all other methods will be indirectly owned by their + // top-level class. This avoids possible deadlocks when a static method + // has to access its enclosing object from the outside. + else if (sym.isPrimaryConstructor && sym.owner.owner.isTerm) + symSet(called, sym) += sym.owner case tree: TypeDef => if (sym.owner.isTerm) liftedOwner(sym) = sym.topLevelClass.owner case tree: Template => @@ -360,7 +366,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform val clazz = sym.enclosingClass val qual = if (clazz.isStaticOwner) singleton(clazz.thisType) - else outer(ctx.withPhase(thisTransform)).path(clazz) + else outer.path(clazz) transformFollowingDeep(qual.select(sym)) } |