diff options
-rw-r--r-- | src/dotty/tools/dotc/transform/ElimStaticThis.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/LambdaLift.scala | 16 | ||||
-rw-r--r-- | tests/run/t5375.scala | 11 |
3 files changed, 27 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/transform/ElimStaticThis.scala b/src/dotty/tools/dotc/transform/ElimStaticThis.scala index 70a610188..3afcfa685 100644 --- a/src/dotty/tools/dotc/transform/ElimStaticThis.scala +++ b/src/dotty/tools/dotc/transform/ElimStaticThis.scala @@ -27,9 +27,11 @@ class ElimStaticThis extends MiniPhaseTransform { override def transformIdent(tree: tpd.Ident)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { if (ctx.owner.enclosingMethod.is(JavaStatic)) { tree.tpe match { - case TermRef(thiz: ThisType, _) => - assert(thiz.underlying.typeSymbol.is(ModuleClass)) + case TermRef(thiz: ThisType, _) if thiz.underlying.typeSymbol.is(ModuleClass) => ref(thiz.underlying.typeSymbol.sourceModule).select(tree.symbol) + case TermRef(thiz: ThisType, _) => + assert(tree.symbol.is(Flags.JavaStatic)) + tree case _ => tree } } diff --git a/src/dotty/tools/dotc/transform/LambdaLift.scala b/src/dotty/tools/dotc/transform/LambdaLift.scala index 3ef684e55..5fbe0343f 100644 --- a/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -249,14 +249,21 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform else if (sym is Method) markCalled(sym, enclosure) else if (sym.isTerm) markFree(sym, enclosure) } - if (sym.maybeOwner.isClass) narrowTo(sym.owner.asClass) + def captureImplicitThis(x: Type): Unit = { + x match { + case tr@TermRef(x, _) if (!tr.termSymbol.isStatic) => captureImplicitThis(x) + case x: ThisType if (!x.tref.typeSymbol.isStaticOwner) => narrowTo(x.tref.typeSymbol.asClass) + case _ => + } + } + captureImplicitThis(tree.tpe) case tree: Select => if (sym.is(Method) && isLocal(sym)) markCalled(sym, enclosure) case tree: This => narrowTo(tree.symbol.asClass) case tree: DefDef => if (sym.owner.isTerm && !sym.is(Label)) - liftedOwner(sym) = sym.enclosingClass.topLevelClass + liftedOwner(sym) = sym.enclosingPackageClass // 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 @@ -362,8 +369,9 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform // though the second condition seems weird, it's not true for symbols which are defined in some // weird combinations of super calls. (encClass, EmptyFlags) - } else - (topClass, JavaStatic) + } else if (encClass.is(ModuleClass, butNot = Package) && encClass.isStatic) // needed to not cause deadlocks in classloader. see t5375.scala + (encClass, EmptyFlags) + else (topClass, JavaStatic) } else (lOwner, EmptyFlags) local.copySymDenotation( diff --git a/tests/run/t5375.scala b/tests/run/t5375.scala index 8c2c06fde..d8413c1a3 100644 --- a/tests/run/t5375.scala +++ b/tests/run/t5375.scala @@ -1,3 +1,14 @@ +/** Hello fellow compiler developer. + if you are wondering why does test suite hang on this test + then it's likely that the lambda inside map has been compiled into static method + unfotrunatelly, as it is executed inside static object initializer, + it is executed inside class-loader, in a synchronized block that is not source defined. + + If the lambda will be static Test$#foo, calling it through a different thread would require grabbing the + lock inside classloader. Unlike if it not static and is called through This(Test).foo, no lock is grabbed. + + @DarkDimius +*/ object Test extends dotty.runtime.LegacyApp { val foos = (1 to 1000).toSeq try |