Skip to content

Commit 3c45b0e

Browse files
committed
extract function to find a kill location
this will help match the structure from PR 112236, where `first_non_contained_inclusive` serves the same purpose as `loan_kill_location` introduced in this commit: finding the location within a range of statements in the block, where the loan goes out of scope, if any.
1 parent 93477da commit 3c45b0e

File tree

1 file changed

+41
-34
lines changed

1 file changed

+41
-34
lines changed

compiler/rustc_borrowck/src/dataflow.rs

+41-34
Original file line numberDiff line numberDiff line change
@@ -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

465472
impl<'a, 'tcx> Borrows<'a, 'tcx> {

0 commit comments

Comments
 (0)