@@ -90,6 +90,9 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
9090 free.getOrElse(sym, Nil ).toList.map(pm)
9191 }
9292
93+ /** Set `liftedOwner(sym)` to `owner` if `owner` is more deeply nested
94+ * than the previous value of `liftedowner(sym)`.
95+ */
9396 def narrowLiftedOwner (sym : Symbol , owner : Symbol )(implicit ctx : Context ) = {
9497 if (sym.owner.isTerm &&
9598 owner.isProperlyContainedIn(liftedOwner(sym)) &&
@@ -100,11 +103,22 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
100103 }
101104 }
102105
103- /** Mark symbol `sym` as being free in `enclosure`, unless `sym`
104- * is defined in `enclosure` or there is a class between `enclosure`s owner
105- * and the owner of `sym`.
106- * Return `true` if there is no class between `enclosure` and
107- * the owner of sym.
106+ /** Mark symbol `sym` as being free in `enclosure`, unless `sym` is defined
107+ * in `enclosure` or there is an intermediate class properly containing `enclosure`
108+ * in which `sym` is also free. Also, update `liftedOwner` of `enclosure` so
109+ * that `enclosure` can access `sym`, or its proxy in an intermediate class.
110+ * This means:
111+ *
112+ * 1. If there is an intermediate class in which `sym` is free, `enclosure`
113+ * must be contained in that class (in order to access the `sym proxy stored
114+ * in the class).
115+ *
116+ * 2. If there is no intermediate class, `enclosure` must be contained
117+ * in the class enclosing `sym`.
118+ *
119+ * Return the closest enclosing intermediate class between `enclosure` and
120+ * the owner of sym, or NoSymbol if none exists.
121+ *
108122 * pre: sym.owner.isTerm, (enclosure.isMethod || enclosure.isClass)
109123 *
110124 * The idea of `markFree` is illustrated with an example:
@@ -130,22 +144,30 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
130144 * }
131145 * }
132146 */
133- private def markFree (sym : Symbol , enclosure : Symbol )(implicit ctx : Context ): Boolean = try {
147+ private def markFree (sym : Symbol , enclosure : Symbol )(implicit ctx : Context ): Symbol = try {
134148 if (! enclosure.exists) throw new NoPath
135- ctx.log( i " mark free: ${ sym.showLocated} with owner ${sym.maybeOwner} marked free in $ enclosure" )
136- narrowLiftedOwner(enclosure, sym.enclosingClass)
137- (enclosure == sym.enclosure) || {
149+ if (enclosure == sym.enclosure) NoSymbol
150+ else {
151+ ctx.log( i " mark free: ${ sym.showLocated} with owner ${sym.maybeOwner} marked free in $enclosure " )
138152 ctx.debuglog(i " $enclosure != ${sym.enclosure}" )
139- if (enclosure.is(PackageClass ) ||
140- ! markFree(sym, enclosure.skipConstructor.enclosure)) false
153+ val intermediate =
154+ if (enclosure.is(PackageClass )) enclosure
155+ else markFree(sym, enclosure.skipConstructor.enclosure)
156+ // `enclosure` might be a constructor, in which case we want the enclosure
157+ // of the enclosing class, so skipConstructor is needed here.
158+ if (intermediate.exists) {
159+ narrowLiftedOwner(enclosure, intermediate)
160+ intermediate
161+ }
141162 else {
163+ narrowLiftedOwner(enclosure, sym.enclosingClass)
142164 val ss = symSet(free, enclosure)
143165 if (! ss(sym)) {
144166 ss += sym
145167 changedFreeVars = true
146168 ctx.debuglog(i " $sym is free in $enclosure" )
147169 }
148- ! enclosure.isClass
170+ if ( enclosure.isClass) enclosure else NoSymbol
149171 }
150172 }
151173 } catch {
@@ -272,7 +294,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
272294 local.copySymDenotation(
273295 owner = newOwner,
274296 name = newName(local),
275- initFlags = local.flags | Private | maybeStatic | maybeNotJavaPrivate,
297+ initFlags = local.flags &~ InSuperCall | Private | maybeStatic | maybeNotJavaPrivate,
276298 info = liftedInfo(local)).installAfter(thisTransform)
277299 if (local.isClass)
278300 for (member <- local.asClass.info.decls)
@@ -372,8 +394,13 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
372394 val sym = tree.symbol
373395 tree.tpe match {
374396 case tpe @ TermRef (prefix, _) =>
375- if ((prefix eq NoPrefix ) && sym.enclosure != currentEnclosure && ! sym.isStatic)
376- (if (sym is Method ) memberRef(sym) else proxyRef(sym)).withPos(tree.pos)
397+ if (prefix eq NoPrefix )
398+ if (sym.enclosure != currentEnclosure && ! sym.isStatic)
399+ (if (sym is Method ) memberRef(sym) else proxyRef(sym)).withPos(tree.pos)
400+ else if (sym.owner.isClass) // sym was lifted out
401+ ref(sym).withPos(tree.pos)
402+ else
403+ tree
377404 else if (! prefixIsElidable(tpe)) ref(tpe)
378405 else tree
379406 case _ =>
0 commit comments