summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/dataflow.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/dataflow.rs')
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs132
1 files changed, 67 insertions, 65 deletions
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 94939c7e4..2daa82aef 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -156,10 +156,10 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
&mut self,
borrow_index: BorrowIndex,
borrow_region: RegionVid,
- location: Location,
+ first_location: Location,
) {
// We visit one BB at a time. The complication is that we may start in the
- // middle of the first BB visited (the one containing `location`), in which
+ // middle of the first BB visited (the one containing `first_location`), in which
// case we may have to later on process the first part of that BB if there
// is a path back to its start.
@@ -168,61 +168,58 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
// `visited` once they are added to `stack`, before they are actually
// processed, because this avoids the need to look them up again on
// completion.
- self.visited.insert(location.block);
+ self.visited.insert(first_location.block);
- let mut first_lo = location.statement_index;
- let first_hi = self.body[location.block].statements.len();
+ let first_block = first_location.block;
+ let mut first_lo = first_location.statement_index;
+ let first_hi = self.body[first_block].statements.len();
- self.visit_stack.push(StackEntry { bb: location.block, lo: first_lo, hi: first_hi });
+ self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi });
- while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
- // If we process the first part of the first basic block (i.e. we encounter that block
- // for the second time), we no longer have to visit its successors again.
- let mut finished_early = bb == location.block && hi != first_hi;
- for i in lo..=hi {
- let location = Location { block: bb, statement_index: i };
+ 'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
+ if let Some(kill_stmt) =
+ self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi)
+ {
+ let kill_location = Location { block: bb, statement_index: kill_stmt };
// If region does not contain a point at the location, then add to list and skip
// successor locations.
- if !self.regioncx.region_contains(borrow_region, location) {
- debug!("borrow {:?} gets killed at {:?}", borrow_index, location);
- self.borrows_out_of_scope_at_location
- .entry(location)
- .or_default()
- .push(borrow_index);
- finished_early = true;
- break;
- }
+ debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
+ self.borrows_out_of_scope_at_location
+ .entry(kill_location)
+ .or_default()
+ .push(borrow_index);
+ continue 'preorder;
}
- if !finished_early {
- // Add successor BBs to the work list, if necessary.
- let bb_data = &self.body[bb];
- debug_assert!(hi == bb_data.statements.len());
- for succ_bb in bb_data.terminator().successors() {
- if !self.visited.insert(succ_bb) {
- if succ_bb == location.block && first_lo > 0 {
- // `succ_bb` has been seen before. If it wasn't
- // fully processed, add its first part to `stack`
- // for processing.
- self.visit_stack.push(StackEntry {
- bb: succ_bb,
- lo: 0,
- hi: first_lo - 1,
- });
-
- // And update this entry with 0, to represent the
- // whole BB being processed.
- first_lo = 0;
- }
- } else {
- // succ_bb hasn't been seen before. Add it to
- // `stack` for processing.
- self.visit_stack.push(StackEntry {
- bb: succ_bb,
- lo: 0,
- hi: self.body[succ_bb].statements.len(),
- });
+ // If we process the first part of the first basic block (i.e. we encounter that block
+ // for the second time), we no longer have to visit its successors again.
+ if bb == first_block && hi != first_hi {
+ continue;
+ }
+
+ // Add successor BBs to the work list, if necessary.
+ let bb_data = &self.body[bb];
+ debug_assert!(hi == bb_data.statements.len());
+ for succ_bb in bb_data.terminator().successors() {
+ if !self.visited.insert(succ_bb) {
+ if succ_bb == first_block && first_lo > 0 {
+ // `succ_bb` has been seen before. If it wasn't
+ // fully processed, add its first part to `stack`
+ // for processing.
+ self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
+
+ // And update this entry with 0, to represent the
+ // whole BB being processed.
+ first_lo = 0;
}
+ } else {
+ // succ_bb hasn't been seen before. Add it to
+ // `stack` for processing.
+ self.visit_stack.push(StackEntry {
+ bb: succ_bb,
+ lo: 0,
+ hi: self.body[succ_bb].statements.len(),
+ });
}
}
}
@@ -231,27 +228,32 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
}
}
+pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
+ body: &Body<'tcx>,
+ regioncx: &RegionInferenceContext<'tcx>,
+ borrow_set: &BorrowSet<'tcx>,
+) -> FxIndexMap<Location, Vec<BorrowIndex>> {
+ let mut prec = OutOfScopePrecomputer::new(body, regioncx);
+ for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
+ let borrow_region = borrow_data.region;
+ let location = borrow_data.reserve_location;
+
+ prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
+ }
+
+ prec.borrows_out_of_scope_at_location
+}
+
impl<'a, 'tcx> Borrows<'a, 'tcx> {
- pub(crate) fn new(
+ pub fn new(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
nonlexical_regioncx: &'a RegionInferenceContext<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
) -> Self {
- let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx);
- for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
- let borrow_region = borrow_data.region;
- let location = borrow_data.reserve_location;
-
- prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
- }
-
- Borrows {
- tcx,
- body,
- borrow_set,
- borrows_out_of_scope_at_location: prec.borrows_out_of_scope_at_location,
- }
+ let borrows_out_of_scope_at_location =
+ calculate_borrows_out_of_scope_at_location(body, nonlexical_regioncx, borrow_set);
+ Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
}
pub fn location(&self, idx: BorrowIndex) -> &Location {
@@ -328,7 +330,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
// bottom = nothing is reserved or activated yet;
- BitSet::new_empty(self.borrow_set.len() * 2)
+ BitSet::new_empty(self.borrow_set.len())
}
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {