@@ -389,40 +389,17 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
389
389
390
390
self . visit_stack . push ( StackEntry { bb : issued_location. block , lo : first_lo, hi : first_hi } ) ;
391
391
392
- ' preorder: while let Some ( StackEntry { bb, lo, hi } ) = self . visit_stack . pop ( ) {
393
- for i in lo..=hi {
394
- let location = Location { block : bb, statement_index : i } ;
395
-
396
- // The loan is out of scope at point `location` if it's not contained within any
397
- // live regions.
398
- let mut issuing_region_can_reach_live_regions = false ;
399
-
400
- // Check whether the issuing region can reach local regions that are live at this
401
- // point.
402
- //
403
- // FIXME: if the issuing region `i` can reach a live region `r` at point `p`, and
404
- // `r` is live at point `q`, then it's guaranteed that `i` would reach `r` at point
405
- // `q`. The reachability is location-insensitive, and we could take advantage of
406
- // that, by jumping to a further point than the next statement. We can jump to the
407
- // furthest point within the block where `r` is live.
408
- let point = self . regioncx . liveness_values ( ) . point_from_location ( location) ;
409
- if let Some ( live_sccs) = self . live_sccs_per_point . row ( point) {
410
- for live_scc in live_sccs. iter ( ) {
411
- if self . reachability . contains ( live_scc) {
412
- issuing_region_can_reach_live_regions = true ;
413
- break ;
414
- }
415
- }
416
- }
417
-
418
- // If no live region is reachable from the issuing region, then the loan is killed
419
- // at this point, and goes out of scope. We also can skip visiting successor
420
- // locations.
421
- if !issuing_region_can_reach_live_regions {
422
- debug ! ( "loan {:?} gets killed at {:?}" , loan_idx, location) ;
423
- self . loans_out_of_scope_at_location . entry ( location) . or_default ( ) . push ( loan_idx) ;
424
- continue ' preorder;
425
- }
392
+ while let Some ( StackEntry { bb, lo, hi } ) = self . visit_stack . pop ( ) {
393
+ // Check whether the issuing region can reach local regions that are live at this point.
394
+ // If not, then the loan is killed at this point and goes out of scope. We also can skip
395
+ // visiting successor locations.
396
+ if let Some ( kill_location) = self . loan_kill_location ( bb, lo, hi) {
397
+ debug ! ( "loan {:?} gets killed at {:?}" , loan_idx, kill_location) ;
398
+ self . loans_out_of_scope_at_location
399
+ . entry ( kill_location)
400
+ . or_default ( )
401
+ . push ( loan_idx) ;
402
+ continue ;
426
403
}
427
404
428
405
// If we process the first part of the first basic block (i.e. we encounter that block
@@ -460,6 +437,36 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
460
437
assert ! ( self . visit_stack. is_empty( ) , "visit stack should be empty" ) ;
461
438
assert ! ( self . reachability_stack. is_empty( ) , "reachability stack should be empty" ) ;
462
439
}
440
+
441
+ /// Returns the lowest statement in `start..=end`, where the loan goes out of scope, if any.
442
+ /// This will be the statement where the issuing region can't reach any of the regions live at
443
+ /// this point.
444
+ fn loan_kill_location ( & self , block : BasicBlock , start : usize , end : usize ) -> Option < Location > {
445
+ for statement_index in start..=end {
446
+ let location = Location { block, statement_index } ;
447
+
448
+ // Check whether the issuing region can reach local regions that are live at this
449
+ // point.
450
+ //
451
+ // FIXME: if the issuing region `i` can reach a live region `r` at point `p`, and
452
+ // `r` is live at point `q`, then it's guaranteed that `i` would reach `r` at point
453
+ // `q`. Reachability is location-insensitive, and we could take advantage of
454
+ // that, by jumping to a further point than the next statement. We can jump to the
455
+ // furthest point within the block where `r` is live.
456
+ let point = self . regioncx . liveness_values ( ) . point_from_location ( location) ;
457
+ if let Some ( live_sccs) = self . live_sccs_per_point . row ( point) {
458
+ if live_sccs. iter ( ) . any ( |live_scc| self . reachability . contains ( live_scc) ) {
459
+ continue ;
460
+ }
461
+ }
462
+
463
+ // No live region is reachable from the issuing region: the loan is killed at this point
464
+ // and goes out of scope.
465
+ return Some ( location) ;
466
+ }
467
+
468
+ None
469
+ }
463
470
}
464
471
465
472
impl < ' a , ' tcx > Borrows < ' a , ' tcx > {
0 commit comments