1
1
#![ deny( rustc:: untranslatable_diagnostic) ]
2
2
#![ deny( rustc:: diagnostic_outside_of_impl) ]
3
- use rustc_data_structures:: fx:: FxIndexMap ;
3
+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
4
4
use rustc_index:: bit_set:: BitSet ;
5
5
use rustc_middle:: mir:: { self , BasicBlock , Body , Location , Place } ;
6
6
use rustc_middle:: ty:: RegionVid ;
@@ -235,9 +235,9 @@ struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
235
235
body : & ' a Body < ' tcx > ,
236
236
regioncx : & ' a RegionInferenceContext < ' tcx > ,
237
237
borrows_out_of_scope_at_location : FxIndexMap < Location , Vec < BorrowIndex > > ,
238
- placeholders : Vec < RegionVid > ,
239
- reachability : BitSet < ConstraintSccIndex > ,
240
- reachability_stack : Vec < ConstraintSccIndex > ,
238
+ placeholders : FxHashSet < ConstraintSccIndex > ,
239
+ reachability : BitSet < RegionVid > ,
240
+ reachability_stack : Vec < RegionVid > ,
241
241
}
242
242
243
243
impl < ' a , ' tcx > PoloniusOutOfScopePrecomputer < ' a , ' tcx > {
@@ -256,6 +256,7 @@ impl<'a, 'tcx> PoloniusOutOfScopePrecomputer<'a, 'tcx> {
256
256
) ;
257
257
is_placeholder
258
258
} )
259
+ . map ( |r| regioncx. constraint_sccs . scc ( r) )
259
260
. collect ( ) ;
260
261
261
262
Self {
@@ -265,7 +266,7 @@ impl<'a, 'tcx> PoloniusOutOfScopePrecomputer<'a, 'tcx> {
265
266
regioncx,
266
267
borrows_out_of_scope_at_location : FxIndexMap :: default ( ) ,
267
268
placeholders,
268
- reachability : BitSet :: new_empty ( regioncx. constraint_sccs . num_sccs ( ) ) ,
269
+ reachability : BitSet :: new_empty ( regioncx. regions ( ) . count ( ) ) ,
269
270
reachability_stack : vec ! [ ] ,
270
271
}
271
272
}
@@ -286,42 +287,51 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
286
287
// regions via member constraints. (The `OutOfScopePrecomputer` wouldn't be called on a
287
288
// region that outlives free regions via outlives constraints.)
288
289
289
- let liveness = & self . regioncx . liveness_constraints ;
290
290
let sccs = & self . regioncx . constraint_sccs ;
291
+ let member_constraints = & self . regioncx . member_constraints ;
291
292
292
- let issuing_region_scc = sccs. scc ( issuing_region) ;
293
- self . reachability_stack . push ( issuing_region_scc) ;
294
- self . reachability . insert ( issuing_region_scc) ;
293
+ self . reachability_stack . push ( issuing_region) ;
294
+ self . reachability . insert ( issuing_region) ;
295
295
296
- let member_constraints = & self . regioncx . member_constraints ;
296
+ let static_region = self . regioncx . universal_regions ( ) . fr_static ;
297
+ while let Some ( region) = self . reachability_stack . pop ( ) {
298
+ let scc = sccs. scc ( region) ;
297
299
298
- while let Some ( scc) = self . reachability_stack . pop ( ) {
299
300
// Handle successors of this SCC:
300
301
//
301
- // 1. Push outlives successors to the worklist stack
302
-
303
- // should be something like:
304
- // self.reachability_stack
305
- // .extend(sccs.successors(scc).filter(|succ_scc| reachability.insert(succ_scc)));
306
- for & succ_scc in sccs. successors ( scc) {
307
- if self . reachability . insert ( succ_scc) {
308
- self . reachability_stack . push ( succ_scc) ;
309
- }
310
- }
311
-
312
- // 2. Deal with member constraints
302
+ // 1. Via member constraints
313
303
//
314
304
// The issuing region can flow into the choice regions here, and they are either:
315
305
// - placeholders or free regions themselves,
316
306
// - or also transitively outlive a free region.
317
307
//
318
308
// That is to say, if there are member constraints here, the loan escapes the
319
309
// function and cannot go out of scope. We can early return.
320
- if member_constraints. indices ( scc) . next ( ) . is_some ( ) {
310
+ //
311
+ // 2. Via placeholders
312
+ //
313
+ // If the issuing region outlives placeholders, its loan escapes the function and
314
+ // cannot go out of scope. We can early return.
315
+ if member_constraints. indices ( scc) . next ( ) . is_some ( ) || self . placeholders . contains ( & scc)
316
+ {
321
317
self . reachability_stack . clear ( ) ;
322
318
self . reachability . clear ( ) ;
323
319
return ;
324
320
}
321
+
322
+ // 3. Via outlives successors, which we want to record and traverse, so we add them
323
+ // to the worklist stack
324
+ let successors = self . regioncx . constraint_graph . outgoing_edges (
325
+ region,
326
+ & self . regioncx . constraints ,
327
+ static_region,
328
+ ) ;
329
+ for outlives_constraint in successors {
330
+ let succ = outlives_constraint. sub ;
331
+ if self . reachability . insert ( succ) {
332
+ self . reachability_stack . push ( succ) ;
333
+ }
334
+ }
325
335
}
326
336
327
337
// We visit one BB at a time. The complication is that we may start in the
@@ -352,23 +362,10 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
352
362
// live regions.
353
363
let mut issuing_region_can_reach_live_regions = false ;
354
364
355
- // Check reachability of all live regions:
356
- // - the local regions that are live at this point,
357
- // - the placeholders, which are live at all points and don't need liveness to be
358
- // computed, and are thus absent from the liveness values.
359
- //
360
- // As mentioned above, we don't need to check for free regions, if the issuing
361
- // region outlived a free region via outlives constraints, we wouldn't need to
362
- // compute its loan's scope.
363
- for live_region in
364
- liveness. live_regions_at ( location) . chain ( self . placeholders . iter ( ) . copied ( ) )
365
- {
366
- let live_region_scc = sccs. scc ( live_region) ;
367
-
368
- // If a single live region is reachable from the issuing region, then the loan
369
- // is still live at this point. We can stop checking other live regions at this
370
- // location, and go to the next location.
371
- if self . reachability . contains ( live_region_scc) {
365
+ // Check whether the issuing region can reach local regions that are live at this
366
+ // point.
367
+ for reachable_region in self . reachability . iter ( ) {
368
+ if self . regioncx . liveness_constraints . contains ( reachable_region, location) {
372
369
issuing_region_can_reach_live_regions = true ;
373
370
break ;
374
371
}
@@ -422,7 +419,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
422
419
self . visited . clear ( ) ;
423
420
self . reachability . clear ( ) ;
424
421
assert ! ( self . visit_stack. is_empty( ) , "visit stack should be empty" ) ;
425
- assert ! ( self . reachability_stack. is_empty( ) , "reachablity stack should be empty" ) ;
422
+ assert ! ( self . reachability_stack. is_empty( ) , "reachability stack should be empty" ) ;
426
423
}
427
424
}
428
425
0 commit comments