diff --git a/compiler/src/dotty/tools/dotc/transform/Dependencies.scala b/compiler/src/dotty/tools/dotc/transform/Dependencies.scala index 6f781c85a027..5e0b77dc9f45 100644 --- a/compiler/src/dotty/tools/dotc/transform/Dependencies.scala +++ b/compiler/src/dotty/tools/dotc/transform/Dependencies.scala @@ -179,6 +179,18 @@ abstract class Dependencies(root: ast.tpd.Tree, @constructorOnly rootContext: Co if enclClass.isContainedIn(thisClass) then thisClass else enclClass) // unknown this reference, play it safe and assume the narrowest possible owner + def setLogicOwner(local: Symbol) = + val encClass = local.owner.enclosingClass + val preferEncClass = + encClass.isStatic + // non-static classes can capture owners, so should be avoided + && (encClass.isProperlyContainedIn(local.topLevelClass) + // can be false for symbols which are defined in some weird combination of supercalls. + || encClass.is(ModuleClass, butNot = Package) + // needed to not cause deadlocks in classloader. see t5375.scala + ) + logicOwner(sym) = if preferEncClass then encClass else local.enclosingPackageClass + tree match case tree: Ident => if isLocal(sym) then @@ -194,7 +206,7 @@ abstract class Dependencies(root: ast.tpd.Tree, @constructorOnly rootContext: Co case tree: This => narrowTo(tree.symbol.asClass) case tree: MemberDef if isExpr(sym) && sym.owner.isTerm => - logicOwner(sym) = sym.enclosingPackageClass + setLogicOwner(sym) // 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 @@ -205,8 +217,8 @@ abstract class Dependencies(root: ast.tpd.Tree, @constructorOnly rootContext: Co // the class itself. This is done so that the constructor inherits // the free variables of the class. symSet(called, sym) += sym.owner - case tree: TypeDef => - if sym.owner.isTerm then logicOwner(sym) = sym.topLevelClass.owner + case tree: TypeDef if sym.owner.isTerm => + setLogicOwner(sym) case _ => end process diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index 464e0d59afed..bb073666363b 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -94,20 +94,7 @@ object LambdaLift: private def liftLocals()(using Context): Unit = { for ((local, lOwner) <- deps.logicalOwner) { val (newOwner, maybeStatic) = - if (lOwner is Package) { - val encClass = local.enclosingClass - val topClass = local.topLevelClass - val preferEncClass = - encClass.isStatic && - // non-static classes can capture owners, so should be avoided - (encClass.isProperlyContainedIn(topClass) || - // can be false for symbols which are defined in some weird combination of supercalls. - encClass.is(ModuleClass, butNot = Package) - // needed to not cause deadlocks in classloader. see t5375.scala - ) - if (preferEncClass) (encClass, EmptyFlags) - else (topClass, JavaStatic) - } + if lOwner is Package then (local.topLevelClass, JavaStatic) else (lOwner, EmptyFlags) // Drop Module because class is no longer a singleton in the lifted context. var initFlags = local.flags &~ Module | Private | Lifted | maybeStatic diff --git a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala index e4a78616e4eb..9d241216bdaa 100644 --- a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala +++ b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala @@ -418,12 +418,16 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { } } - if (tree.source != ctx.source && tree.source.exists) - transformTree(tree, start)(using ctx.withSource(tree.source)) - else if (tree.isInstanceOf[NameTree]) - transformNamed(tree, start, ctx) - else - transformUnnamed(tree, start, ctx) + // try + if (tree.source != ctx.source && tree.source.exists) + transformTree(tree, start)(using ctx.withSource(tree.source)) + else if (tree.isInstanceOf[NameTree]) + transformNamed(tree, start, ctx) + else + transformUnnamed(tree, start, ctx) + // catch case ex: AssertionError => + // println(i"error while transforming $tree") + // throw ex } def transformSpecificTree[T <: Tree](tree: T, start: Int)(using Context): T = diff --git a/tests/pos/i14707.scala b/tests/pos/i14707.scala new file mode 100644 index 000000000000..b1da8e1a040e --- /dev/null +++ b/tests/pos/i14707.scala @@ -0,0 +1,17 @@ +object M { + class A {{ + def f(v: => Int): Int = 0 + def g: Int = 0 + new { f(g) } + }} +} + +object M2 { + abstract class A { + def local = { + def f(v: () => Int): Int = 0 + def g(): Int = 0 + new AnyRef { def h = f(() => g()) } + } + } +} \ No newline at end of file