Use Rc less in MirBorrowckCtxt.

The `regioncx` and `borrow_set` fields can be references instead of
`Rc`. They use the existing `'a` lifetime. This avoids some heap
allocations and is a bit simpler.
This commit is contained in:
Nicholas Nethercote 2024-10-04 13:47:32 +10:00
parent 9ff5fc4ffb
commit 89e84c053d
2 changed files with 17 additions and 25 deletions

View File

@ -1,5 +1,4 @@
use std::collections::VecDeque;
use std::rc::Rc;
use rustc_data_structures::fx::FxIndexSet;
use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
@ -11,7 +10,7 @@
pub(crate) fn find<'tcx>(
body: &Body<'tcx>,
regioncx: &Rc<RegionInferenceContext<'tcx>>,
regioncx: &RegionInferenceContext<'tcx>,
tcx: TyCtxt<'tcx>,
region_vid: RegionVid,
start_point: Location,
@ -23,7 +22,7 @@ pub(crate) fn find<'tcx>(
struct UseFinder<'a, 'tcx> {
body: &'a Body<'tcx>,
regioncx: &'a Rc<RegionInferenceContext<'tcx>>,
regioncx: &'a RegionInferenceContext<'tcx>,
tcx: TyCtxt<'tcx>,
region_vid: RegionVid,
start_point: Location,

View File

@ -201,8 +201,7 @@ fn do_mir_borrowck<'tcx>(
.into_results_cursor(body);
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
let borrow_set =
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data));
let borrow_set = BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data);
// Compute non-lexical lifetimes.
let nll::NllOutput {
@ -246,8 +245,6 @@ fn do_mir_borrowck<'tcx>(
// usage significantly on some benchmarks.
drop(flow_inits);
let regioncx = Rc::new(regioncx);
let flow_borrows = Borrows::new(tcx, body, &regioncx, &borrow_set)
.into_engine(tcx, body)
.pass_name("borrowck")
@ -289,10 +286,10 @@ fn do_mir_borrowck<'tcx>(
access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(),
uninitialized_error_reported: Default::default(),
regioncx: regioncx.clone(),
regioncx: &regioncx,
used_mut: Default::default(),
used_mut_upvars: SmallVec::new(),
borrow_set: Rc::clone(&borrow_set),
borrow_set: &borrow_set,
upvars: &[],
local_names: IndexVec::from_elem(None, &promoted_body.local_decls),
region_names: RefCell::default(),
@ -330,10 +327,10 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(),
uninitialized_error_reported: Default::default(),
regioncx: Rc::clone(&regioncx),
regioncx: &regioncx,
used_mut: Default::default(),
used_mut_upvars: SmallVec::new(),
borrow_set: Rc::clone(&borrow_set),
borrow_set: &borrow_set,
upvars: tcx.closure_captures(def),
local_names,
region_names: RefCell::default(),
@ -423,8 +420,8 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
Some(Box::new(BodyWithBorrowckFacts {
body: body_owned,
promoted,
borrow_set,
region_inference_context: regioncx,
borrow_set: Rc::new(borrow_set),
region_inference_context: Rc::new(regioncx),
location_table: polonius_input.as_ref().map(|_| location_table),
input_facts: polonius_input,
output_facts,
@ -570,10 +567,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
used_mut_upvars: SmallVec<[FieldIdx; 8]>,
/// Region inference context. This contains the results from region inference and lets us e.g.
/// find out which CFG points are contained in each borrow region.
regioncx: Rc<RegionInferenceContext<'tcx>>,
regioncx: &'a RegionInferenceContext<'tcx>,
/// The set of borrows extracted from the MIR
borrow_set: Rc<BorrowSet<'tcx>>,
borrow_set: &'a BorrowSet<'tcx>,
/// Information about upvars not necessarily preserved in types or MIR
upvars: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
@ -800,9 +797,8 @@ fn visit_terminator_after_primary_effect(
TerminatorKind::Yield { value: _, resume: _, resume_arg: _, drop: _ } => {
if self.movable_coroutine {
// Look for any active borrows to locals
let borrow_set = self.borrow_set.clone();
for i in state.borrows.iter() {
let borrow = &borrow_set[i];
let borrow = &self.borrow_set[i];
self.check_for_local_borrow(borrow, span);
}
}
@ -816,9 +812,8 @@ fn visit_terminator_after_primary_effect(
// Often, the storage will already have been killed by an explicit
// StorageDead, but we don't always emit those (notably on unwind paths),
// so this "extra check" serves as a kind of backup.
let borrow_set = self.borrow_set.clone();
for i in state.borrows.iter() {
let borrow = &borrow_set[i];
let borrow = &self.borrow_set[i];
self.check_for_invalidation_at_exit(loc, borrow, span);
}
}
@ -1037,13 +1032,12 @@ fn check_access_for_conflict(
state: &BorrowckDomain<'a, 'tcx>,
) -> bool {
let mut error_reported = false;
let borrow_set = Rc::clone(&self.borrow_set);
// Use polonius output if it has been enabled.
let mut polonius_output;
let borrows_in_scope = if let Some(polonius) = &self.polonius_output {
let location = self.location_table.start_index(location);
polonius_output = BitSet::new_empty(borrow_set.len());
polonius_output = BitSet::new_empty(self.borrow_set.len());
for &idx in polonius.errors_at(location) {
polonius_output.insert(idx);
}
@ -1057,7 +1051,7 @@ fn check_access_for_conflict(
self.infcx.tcx,
self.body,
(sd, place_span.0),
&borrow_set,
self.borrow_set,
|borrow_index| borrows_in_scope.contains(borrow_index),
|this, borrow_index, borrow| match (rw, borrow.kind) {
// Obviously an activation is compatible with its own
@ -1580,9 +1574,8 @@ fn check_activations(
// Two-phase borrow support: For each activation that is newly
// generated at this statement, check if it interferes with
// another borrow.
let borrow_set = self.borrow_set.clone();
for &borrow_index in borrow_set.activations_at_location(location) {
let borrow = &borrow_set[borrow_index];
for &borrow_index in self.borrow_set.activations_at_location(location) {
let borrow = &self.borrow_set[borrow_index];
// only mutable borrows should be 2-phase
assert!(match borrow.kind {