@@ -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,40 +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
- // If we have all fields initialized, then we can promote This to hot.
168
- val classRef = state.thisClass.info.asInstanceOf [ClassInfo ].appliedRef
169
- val allFieldsInited = classRef.fields.forall { denot =>
170
- val sym = denot.symbol
171
- sym.isOneOf(Flags .Lazy | Flags .Deferred ) || state.fieldsInited.contains(sym)
172
- }
173
- if (allFieldsInited)
174
- Errors .empty
175
- else
176
- PromoteThis (pot, eff.source, state2.path).toErrors
177
- case _ : Cold =>
178
- PromoteCold (eff.source, state2.path).toErrors
179
-
180
- case pot @ Warm (cls, outer) =>
181
- val errors = state.test { check(Promote (outer)(eff.source)) }
182
- if (errors.isEmpty) Errors .empty
183
- else PromoteWarm (pot, eff.source, state2.path).toErrors
184
-
185
- case Fun (pots, effs) =>
186
- val errs1 = state.test { effs.flatMap { check(_) } }
187
- val errs2 = state.test { pots.flatMap { pot => check(Promote (pot)(eff.source))(state.copy(path = Vector .empty)) } }
188
- if (errs1.nonEmpty || errs2.nonEmpty)
189
- UnsafePromotion (pot, eff.source, state2.path, errs1 ++ errs2).toErrors
190
- else
191
- Errors .empty
192
-
193
- case pot =>
194
- val (pots, effs) = expand(pot)
195
- val effs2 = pots.map(Promote (_)(eff.source))
196
- (effs2 ++ effs).flatMap(check(_))
197
- }
165
+ case Promote (pot) => checkPromote(pot, eff.source)
198
166
199
167
case FieldAccess (pot, field) =>
200
168
@@ -279,6 +247,47 @@ object Checking {
279
247
}
280
248
}
281
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
+
282
291
private def expand (pot : Potential )(implicit state : State ): Summary = trace(" expand " + pot.show, init, sum => Summary .show(sum.asInstanceOf [Summary ])) {
283
292
pot match {
284
293
case MethodReturn (pot1, sym) =>
0 commit comments