aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/Compiler.scala2
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala3
-rw-r--r--src/dotty/tools/dotc/transform/ElimStaticThis.scala11
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitOuter.scala5
-rw-r--r--src/dotty/tools/dotc/transform/LambdaLift.scala22
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))
}