@@ -35,6 +35,7 @@ object Checking {
35
35
thisClass : ClassSymbol , // the concrete class of `this`
36
36
fieldsInited : mutable.Set [Symbol ],
37
37
parentsInited : mutable.Set [ClassSymbol ],
38
+ safePromoted : mutable.Set [Potential ], // Potentials that can be safely promoted
38
39
env : Env
39
40
) {
40
41
@@ -161,32 +162,7 @@ object Checking {
161
162
implicit val state2 : State = state.withVisited(eff)
162
163
163
164
eff match {
164
- case Promote (pot) =>
165
- pot match {
166
- case pot : ThisRef =>
167
- PromoteThis (pot, eff.source, state2.path).toErrors
168
-
169
- case _ : Cold =>
170
- PromoteCold (eff.source, state2.path).toErrors
171
-
172
- case pot @ Warm (cls, outer) =>
173
- val errors = state.test { check(Promote (outer)(eff.source)) }
174
- if (errors.isEmpty) Errors .empty
175
- else PromoteWarm (pot, eff.source, state2.path).toErrors
176
-
177
- case Fun (pots, effs) =>
178
- val errs1 = state.test { effs.flatMap { check(_) } }
179
- val errs2 = state.test { pots.flatMap { pot => check(Promote (pot)(eff.source))(state.copy(path = Vector .empty)) } }
180
- if (errs1.nonEmpty || errs2.nonEmpty)
181
- UnsafePromotion (pot, eff.source, state2.path, errs1 ++ errs2).toErrors
182
- else
183
- Errors .empty
184
-
185
- case pot =>
186
- val (pots, effs) = expand(pot)
187
- val effs2 = pots.map(Promote (_)(eff.source))
188
- (effs2 ++ effs).flatMap(check(_))
189
- }
165
+ case Promote (pot) => checkPromote(pot, eff.source)
190
166
191
167
case FieldAccess (pot, field) =>
192
168
@@ -271,6 +247,47 @@ object Checking {
271
247
}
272
248
}
273
249
250
+ private def checkPromote (pot : Potential , source : Tree )(implicit state : State ): Errors =
251
+ if (state.safePromoted.contains(pot)) Errors .empty
252
+ else
253
+ val errs = pot match {
254
+ case pot : ThisRef =>
255
+ // If we have all fields initialized, then we can promote This to hot.
256
+ val classRef = state.thisClass.info.asInstanceOf [ClassInfo ].appliedRef
257
+ val allFieldsInited = classRef.fields.forall { denot =>
258
+ val sym = denot.symbol
259
+ sym.isOneOf(Flags .Lazy | Flags .Deferred ) || state.fieldsInited.contains(sym)
260
+ }
261
+ if (allFieldsInited)
262
+ Errors .empty
263
+ else
264
+ PromoteThis (pot, source, state.path).toErrors
265
+ case _ : Cold =>
266
+ PromoteCold (source, state.path).toErrors
267
+
268
+ case pot @ Warm (cls, outer) =>
269
+ val errors = state.test { checkPromote(outer, source) }
270
+ if (errors.isEmpty) Errors .empty
271
+ else PromoteWarm (pot, source, state.path).toErrors
272
+
273
+ case Fun (pots, effs) =>
274
+ val errs1 = state.test { effs.flatMap { check(_) } }
275
+ val errs2 = state.test { pots.flatMap { pot => checkPromote(pot, source)(state.copy(path = Vector .empty)) } }
276
+ if (errs1.nonEmpty || errs2.nonEmpty)
277
+ UnsafePromotion (pot, source, state.path, errs1 ++ errs2).toErrors
278
+ else
279
+ Errors .empty
280
+
281
+ case pot =>
282
+ val (pots, effs) = expand(pot)
283
+ val effs2 = pots.map(Promote (_)(source))
284
+ (effs2 ++ effs).flatMap(check(_))
285
+ }
286
+ // If we can safely promote, then we don't need to check again
287
+ if (errs.isEmpty)
288
+ state.safePromoted += pot
289
+ errs
290
+
274
291
private def expand (pot : Potential )(implicit state : State ): Summary = trace(" expand " + pot.show, init, sum => Summary .show(sum.asInstanceOf [Summary ])) {
275
292
pot match {
276
293
case MethodReturn (pot1, sym) =>
0 commit comments