Skip to content

Commit 4df4e53

Browse files
committed
Fix #8931: Refinement of markFree in lambda lift
1 parent b4338a8 commit 4df4e53

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,21 @@ object LambdaLift {
151151
if (!enclosure.exists) throw new NoPath
152152
if (enclosure == sym.enclosure) NoSymbol
153153
else {
154+
def nestedInConstructor(sym: Symbol): Boolean =
155+
sym.isConstructor ||
156+
sym.isTerm && nestedInConstructor(sym.enclosure)
154157
ctx.debuglog(i"mark free: ${sym.showLocated} with owner ${sym.maybeOwner} marked free in $enclosure")
155158
val intermediate =
156159
if (enclosure.is(PackageClass)) enclosure
157160
else if (enclosure.isConstructor) markFree(sym, enclosure.owner.enclosure)
158161
else markFree(sym, enclosure.enclosure)
159162
if (intermediate.exists) narrowLiftedOwner(enclosure, intermediate)
160-
if (!intermediate.isRealClass || enclosure.isConstructor)
163+
if !intermediate.isRealClass || nestedInConstructor(enclosure) then
161164
// Constructors and methods nested inside traits get the free variables
162-
// of the enclosing trait or class.
165+
// of the enclosing trait or class.
163166
// Conversely, local traits do not get free variables.
167+
// Methods inside constructors also don't have intermediates,
168+
// need to get all their free variables passed directly.
164169
if (!enclosure.is(Trait))
165170
if (symSet(free, enclosure).add(sym)) {
166171
changedFreeVars = true
@@ -301,7 +306,7 @@ object LambdaLift {
301306
private def generateProxies()(implicit ctx: Context): Unit =
302307
for ((owner, freeValues) <- free.iterator) {
303308
val newFlags = Synthetic | (if (owner.isClass) ParamAccessor | Private else Param)
304-
ctx.debuglog(i"free var proxy: ${owner.showLocated}, ${freeValues.toList}%, %")
309+
ctx.debuglog(i"free var proxy of ${owner.showLocated}: ${freeValues.toList}%, %")
305310
proxyMap(owner) = {
306311
for (fv <- freeValues.toList) yield {
307312
val proxyName = newName(fv)

tests/pos/i8931.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
trait Trait
2+
3+
trait Managed[T]:
4+
5+
def flatMap[U](f: T => Managed[U]) =
6+
class C:
7+
def make() =
8+
class D:
9+
def bar(): T = ???
10+
val t: T = ???
11+
val u =
12+
def foo = (f(t), f(bar()))
13+
foo
14+
new D().u
15+
()

0 commit comments

Comments
 (0)