@@ -389,40 +389,17 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
389389
390390 self . visit_stack . push ( StackEntry { bb : issued_location. block , lo : first_lo, hi : first_hi } ) ;
391391
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 ;
426403 }
427404
428405 // 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> {
460437 assert ! ( self . visit_stack. is_empty( ) , "visit stack should be empty" ) ;
461438 assert ! ( self . reachability_stack. is_empty( ) , "reachability stack should be empty" ) ;
462439 }
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+ }
463470}
464471
465472impl < ' a , ' tcx > Borrows < ' a , ' tcx > {
0 commit comments