@@ -90,6 +90,9 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
90
90
free.getOrElse(sym, Nil ).toList.map(pm)
91
91
}
92
92
93
+ /** Set `liftedOwner(sym)` to `owner` if `owner` is more deeply nested
94
+ * than the previous value of `liftedowner(sym)`.
95
+ */
93
96
def narrowLiftedOwner (sym : Symbol , owner : Symbol )(implicit ctx : Context ) = {
94
97
if (sym.owner.isTerm &&
95
98
owner.isProperlyContainedIn(liftedOwner(sym)) &&
@@ -100,11 +103,22 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
100
103
}
101
104
}
102
105
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
+ *
108
122
* pre: sym.owner.isTerm, (enclosure.isMethod || enclosure.isClass)
109
123
*
110
124
* The idea of `markFree` is illustrated with an example:
@@ -130,22 +144,30 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
130
144
* }
131
145
* }
132
146
*/
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 {
134
148
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 " )
138
152
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
+ }
141
162
else {
163
+ narrowLiftedOwner(enclosure, sym.enclosingClass)
142
164
val ss = symSet(free, enclosure)
143
165
if (! ss(sym)) {
144
166
ss += sym
145
167
changedFreeVars = true
146
168
ctx.debuglog(i " $sym is free in $enclosure" )
147
169
}
148
- ! enclosure.isClass
170
+ if ( enclosure.isClass) enclosure else NoSymbol
149
171
}
150
172
}
151
173
} catch {
@@ -272,7 +294,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
272
294
local.copySymDenotation(
273
295
owner = newOwner,
274
296
name = newName(local),
275
- initFlags = local.flags | Private | maybeStatic | maybeNotJavaPrivate,
297
+ initFlags = local.flags &~ InSuperCall | Private | maybeStatic | maybeNotJavaPrivate,
276
298
info = liftedInfo(local)).installAfter(thisTransform)
277
299
if (local.isClass)
278
300
for (member <- local.asClass.info.decls)
@@ -372,8 +394,13 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
372
394
val sym = tree.symbol
373
395
tree.tpe match {
374
396
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
377
404
else if (! prefixIsElidable(tpe)) ref(tpe)
378
405
else tree
379
406
case _ =>
0 commit comments