Skip to content

Commit 0035403

Browse files
committed
refactor to match precomputer from PR 112236
1 parent 3c45b0e commit 0035403

File tree

1 file changed

+34
-54
lines changed

1 file changed

+34
-54
lines changed

compiler/rustc_borrowck/src/dataflow.rs

+34-54
Original file line numberDiff line numberDiff line change
@@ -240,19 +240,9 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
240240
prec.borrows_out_of_scope_at_location
241241
}
242242

243-
/// An entry in the CFG walk stack of the scope computation, recording visited statements within a
244-
/// block, in case of cycles requiring revisiting the same block but at earlier points.
245-
// FIXME: `precompute_borrows_out_of_scope` has stopped using this structure, and a similar
246-
// reorganizing of `precompute_loans_out_of_scope` could also avoid it.
247-
struct StackEntry {
248-
bb: mir::BasicBlock,
249-
lo: usize,
250-
hi: usize,
251-
}
252-
253243
struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
254244
visited: BitSet<mir::BasicBlock>,
255-
visit_stack: Vec<StackEntry>,
245+
visit_stack: Vec<mir::BasicBlock>,
256246
body: &'a Body<'tcx>,
257247
regioncx: &'a RegionInferenceContext<'tcx>,
258248

@@ -327,7 +317,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
327317
&mut self,
328318
loan_idx: BorrowIndex,
329319
issuing_region: RegionVid,
330-
issued_location: Location,
320+
first_location: Location,
331321
) {
332322
// Let's precompute the reachability set of the issuing region, via reachability on the
333323
// condensation graph. We can also early return when reaching regions that outlive free
@@ -373,61 +363,51 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
373363
}
374364
}
375365

376-
// We visit one BB at a time. The complication is that we may start in the middle of the
377-
// first BB visited (the one containing `issued_location`), in which case we may have to
378-
// later on process the first part of that BB if there is a path back to its start.
366+
let first_block = first_location.block;
367+
let first_bb_data = &self.body.basic_blocks[first_block];
379368

380-
// For visited BBs, we record the index of the first statement processed. (In fully
381-
// processed BBs this index is 0.) Note also that we add BBs to `visited` once they are
382-
// added to `stack`, before they are actually processed, because this avoids the need to
383-
// look them up again on completion.
384-
self.visited.insert(issued_location.block);
369+
// The first block we visit is the one where the loan is issued, starting from the statement
370+
// where the loan is issued: at `first_location`.
371+
let first_lo = first_location.statement_index;
372+
let first_hi = first_bb_data.statements.len();
373+
374+
if let Some(kill_location) = self.loan_kill_location(first_block, first_lo, first_hi) {
375+
debug!("loan {:?} gets killed at {:?}", loan_idx, kill_location);
376+
self.loans_out_of_scope_at_location.entry(kill_location).or_default().push(loan_idx);
385377

386-
let first_block = issued_location.block;
387-
let mut first_lo = issued_location.statement_index;
388-
let first_hi = self.body[issued_location.block].statements.len();
378+
// The loan dies within the first block, we're done and can early return.
379+
self.reachability.clear();
380+
return;
381+
}
389382

390-
self.visit_stack.push(StackEntry { bb: issued_location.block, lo: first_lo, hi: first_hi });
383+
// The loan is not dead. Add successor BBs to the work list, if necessary.
384+
for succ_bb in first_bb_data.terminator().successors() {
385+
if self.visited.insert(succ_bb) {
386+
self.visit_stack.push(succ_bb);
387+
}
388+
}
391389

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) {
390+
// We may end up visiting `first_block` again. This is not an issue: we know at this point
391+
// that the loan is not killed in the `first_lo..=first_hi` range, so checking the
392+
// `0..first_lo` range and the `0..first_hi` range gives the same result.
393+
while let Some(block) = self.visit_stack.pop() {
394+
let bb_data = &self.body[block];
395+
let num_stmts = bb_data.statements.len();
396+
if let Some(kill_location) = self.loan_kill_location(block, 0, num_stmts) {
397397
debug!("loan {:?} gets killed at {:?}", loan_idx, kill_location);
398398
self.loans_out_of_scope_at_location
399399
.entry(kill_location)
400400
.or_default()
401401
.push(loan_idx);
402-
continue;
403-
}
404402

405-
// If we process the first part of the first basic block (i.e. we encounter that block
406-
// for the second time), we no longer have to visit its successors again.
407-
if bb == first_block && hi != first_hi {
403+
// The loan dies within this block, so we don't need to visit its successors.
408404
continue;
409405
}
410406

411407
// Add successor BBs to the work list, if necessary.
412-
let bb_data = &self.body[bb];
413-
debug_assert!(hi == bb_data.statements.len());
414408
for succ_bb in bb_data.terminator().successors() {
415-
if !self.visited.insert(succ_bb) {
416-
if succ_bb == first_block && first_lo > 0 {
417-
// `succ_bb` has been seen before. If it wasn't fully processed, add its
418-
// first part to the stack for processing.
419-
self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
420-
421-
// And update this entry with 0, to represent the whole BB being processed.
422-
first_lo = 0;
423-
}
424-
} else {
425-
// `succ_bb` hasn't been seen before. Add it to the stack for processing.
426-
self.visit_stack.push(StackEntry {
427-
bb: succ_bb,
428-
lo: 0,
429-
hi: self.body[succ_bb].statements.len(),
430-
});
409+
if self.visited.insert(succ_bb) {
410+
self.visit_stack.push(succ_bb);
431411
}
432412
}
433413
}
@@ -439,8 +419,8 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
439419
}
440420

441421
/// 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.
422+
/// This is the statement where the issuing region can't reach any of the regions that are live
423+
/// at this point.
444424
fn loan_kill_location(&self, block: BasicBlock, start: usize, end: usize) -> Option<Location> {
445425
for statement_index in start..=end {
446426
let location = Location { block, statement_index };

0 commit comments

Comments
 (0)