Skip to content

Commit 347a730

Browse files
authored
Merge pull request #14714 from dotty-staging/fix-14707
Fix hoisting local symbols
2 parents c9d33a8 + fabb0d4 commit 347a730

File tree

4 files changed

+43
-23
lines changed

4 files changed

+43
-23
lines changed

compiler/src/dotty/tools/dotc/transform/Dependencies.scala

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,18 @@ abstract class Dependencies(root: ast.tpd.Tree, @constructorOnly rootContext: Co
179179
if enclClass.isContainedIn(thisClass) then thisClass
180180
else enclClass) // unknown this reference, play it safe and assume the narrowest possible owner
181181

182+
def setLogicOwner(local: Symbol) =
183+
val encClass = local.owner.enclosingClass
184+
val preferEncClass =
185+
encClass.isStatic
186+
// non-static classes can capture owners, so should be avoided
187+
&& (encClass.isProperlyContainedIn(local.topLevelClass)
188+
// can be false for symbols which are defined in some weird combination of supercalls.
189+
|| encClass.is(ModuleClass, butNot = Package)
190+
// needed to not cause deadlocks in classloader. see t5375.scala
191+
)
192+
logicOwner(sym) = if preferEncClass then encClass else local.enclosingPackageClass
193+
182194
tree match
183195
case tree: Ident =>
184196
if isLocal(sym) then
@@ -194,7 +206,7 @@ abstract class Dependencies(root: ast.tpd.Tree, @constructorOnly rootContext: Co
194206
case tree: This =>
195207
narrowTo(tree.symbol.asClass)
196208
case tree: MemberDef if isExpr(sym) && sym.owner.isTerm =>
197-
logicOwner(sym) = sym.enclosingPackageClass
209+
setLogicOwner(sym)
198210
// this will make methods in supercall constructors of top-level classes owned
199211
// by the enclosing package, which means they will be static.
200212
// 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
205217
// the class itself. This is done so that the constructor inherits
206218
// the free variables of the class.
207219
symSet(called, sym) += sym.owner
208-
case tree: TypeDef =>
209-
if sym.owner.isTerm then logicOwner(sym) = sym.topLevelClass.owner
220+
case tree: TypeDef if sym.owner.isTerm =>
221+
setLogicOwner(sym)
210222
case _ =>
211223
end process
212224

compiler/src/dotty/tools/dotc/transform/LambdaLift.scala

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,7 @@ object LambdaLift:
9494
private def liftLocals()(using Context): Unit = {
9595
for ((local, lOwner) <- deps.logicalOwner) {
9696
val (newOwner, maybeStatic) =
97-
if (lOwner is Package) {
98-
val encClass = local.enclosingClass
99-
val topClass = local.topLevelClass
100-
val preferEncClass =
101-
encClass.isStatic &&
102-
// non-static classes can capture owners, so should be avoided
103-
(encClass.isProperlyContainedIn(topClass) ||
104-
// can be false for symbols which are defined in some weird combination of supercalls.
105-
encClass.is(ModuleClass, butNot = Package)
106-
// needed to not cause deadlocks in classloader. see t5375.scala
107-
)
108-
if (preferEncClass) (encClass, EmptyFlags)
109-
else (topClass, JavaStatic)
110-
}
97+
if lOwner is Package then (local.topLevelClass, JavaStatic)
11198
else (lOwner, EmptyFlags)
11299
// Drop Module because class is no longer a singleton in the lifted context.
113100
var initFlags = local.flags &~ Module | Private | Lifted | maybeStatic

compiler/src/dotty/tools/dotc/transform/MegaPhase.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,12 +418,16 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase {
418418
}
419419
}
420420

421-
if (tree.source != ctx.source && tree.source.exists)
422-
transformTree(tree, start)(using ctx.withSource(tree.source))
423-
else if (tree.isInstanceOf[NameTree])
424-
transformNamed(tree, start, ctx)
425-
else
426-
transformUnnamed(tree, start, ctx)
421+
// try
422+
if (tree.source != ctx.source && tree.source.exists)
423+
transformTree(tree, start)(using ctx.withSource(tree.source))
424+
else if (tree.isInstanceOf[NameTree])
425+
transformNamed(tree, start, ctx)
426+
else
427+
transformUnnamed(tree, start, ctx)
428+
// catch case ex: AssertionError =>
429+
// println(i"error while transforming $tree")
430+
// throw ex
427431
}
428432

429433
def transformSpecificTree[T <: Tree](tree: T, start: Int)(using Context): T =

tests/pos/i14707.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
object M {
2+
class A {{
3+
def f(v: => Int): Int = 0
4+
def g: Int = 0
5+
new { f(g) }
6+
}}
7+
}
8+
9+
object M2 {
10+
abstract class A {
11+
def local = {
12+
def f(v: () => Int): Int = 0
13+
def g(): Int = 0
14+
new AnyRef { def h = f(() => g()) }
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)