Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_borrowck memory management tweaks #131225

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions compiler/rustc_borrowck/src/consumers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! This file provides API for compiler consumers.

use std::rc::Rc;

use rustc_hir::def_id::LocalDefId;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::{Body, Promoted};
Expand Down Expand Up @@ -65,10 +63,10 @@ pub struct BodyWithBorrowckFacts<'tcx> {
/// The mir bodies of promoteds.
pub promoted: IndexVec<Promoted, Body<'tcx>>,
/// The set of borrows occurring in `body` with data about them.
pub borrow_set: Rc<BorrowSet<'tcx>>,
pub borrow_set: BorrowSet<'tcx>,
/// Context generated during borrowck, intended to be passed to
/// [`calculate_borrows_out_of_scope_at_location`].
pub region_inference_context: Rc<RegionInferenceContext<'tcx>>,
pub region_inference_context: RegionInferenceContext<'tcx>,
/// The table that maps Polonius points to locations in the table.
/// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
/// or [`ConsumerOptions::PoloniusOutputFacts`].
Expand All @@ -79,7 +77,7 @@ pub struct BodyWithBorrowckFacts<'tcx> {
pub input_facts: Option<Box<PoloniusInput>>,
/// Polonius output facts. Populated when using
/// [`ConsumerOptions::PoloniusOutputFacts`].
pub output_facts: Option<Rc<PoloniusOutput>>,
pub output_facts: Option<Box<PoloniusOutput>>,
}

/// This function computes borrowck facts for the given body. The [`ConsumerOptions`]
Expand Down
20 changes: 10 additions & 10 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,9 +708,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// for the branching codepaths that aren't covered, to point at them.
let map = self.infcx.tcx.hir();
let body = map.body_owned_by(self.mir_def_id());
let mut visitor =
ConditionVisitor { tcx: self.infcx.tcx, spans: &spans, name: &name, errors: vec![] };
let mut visitor = ConditionVisitor { tcx: self.infcx.tcx, spans, name, errors: vec![] };
visitor.visit_body(&body);
let spans = visitor.spans;

let mut show_assign_sugg = false;
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
Expand Down Expand Up @@ -4465,20 +4465,20 @@ impl<'hir> Visitor<'hir> for BreakFinder {

/// Given a set of spans representing statements initializing the relevant binding, visit all the
/// function expressions looking for branching code paths that *do not* initialize the binding.
struct ConditionVisitor<'b, 'tcx> {
struct ConditionVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
spans: &'b [Span],
name: &'b str,
spans: Vec<Span>,
name: String,
errors: Vec<(Span, String)>,
}

impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
impl<'v, 'tcx> Visitor<'v> for ConditionVisitor<'tcx> {
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
match ex.kind {
hir::ExprKind::If(cond, body, None) => {
// `if` expressions with no `else` that initialize the binding might be missing an
// `else` arm.
if ReferencedStatementsVisitor(self.spans).visit_expr(body).is_break() {
if ReferencedStatementsVisitor(&self.spans).visit_expr(body).is_break() {
self.errors.push((
cond.span,
format!(
Expand All @@ -4495,8 +4495,8 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
hir::ExprKind::If(cond, body, Some(other)) => {
// `if` expressions where the binding is only initialized in one of the two arms
// might be missing a binding initialization.
let a = ReferencedStatementsVisitor(self.spans).visit_expr(body).is_break();
let b = ReferencedStatementsVisitor(self.spans).visit_expr(other).is_break();
let a = ReferencedStatementsVisitor(&self.spans).visit_expr(body).is_break();
let b = ReferencedStatementsVisitor(&self.spans).visit_expr(other).is_break();
match (a, b) {
(true, true) | (false, false) => {}
(true, false) => {
Expand Down Expand Up @@ -4536,7 +4536,7 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
// arms might be missing an initialization.
let results: Vec<bool> = arms
.iter()
.map(|arm| ReferencedStatementsVisitor(self.spans).visit_arm(arm).is_break())
.map(|arm| ReferencedStatementsVisitor(&self.spans).visit_arm(arm).is_break())
.collect();
if results.iter().any(|x| *x) && !results.iter().all(|x| *x) {
for (arm, seen) in arms.iter().zip(results) {
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/find_use.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -11,7 +10,7 @@ use crate::region_infer::{Cause, RegionInferenceContext};

pub(crate) fn find<'tcx>(
body: &Body<'tcx>,
regioncx: &Rc<RegionInferenceContext<'tcx>>,
regioncx: &RegionInferenceContext<'tcx>,
tcx: TyCtxt<'tcx>,
region_vid: RegionVid,
start_point: Location,
Expand All @@ -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,
Expand Down
36 changes: 14 additions & 22 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use std::cell::RefCell;
use std::collections::BTreeMap;
use std::marker::PhantomData;
use std::ops::Deref;
use std::rc::Rc;

use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
Expand Down Expand Up @@ -201,8 +200,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 {
Expand Down Expand Up @@ -246,8 +244,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")
Expand Down Expand Up @@ -289,10 +285,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(),
Expand Down Expand Up @@ -330,10 +326,10 @@ fn do_mir_borrowck<'tcx>(
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(),
Expand Down Expand Up @@ -570,10 +566,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>],
Expand All @@ -589,7 +585,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
next_region_name: RefCell<usize>,

/// Results of Polonius analysis.
polonius_output: Option<Rc<PoloniusOutput>>,
polonius_output: Option<Box<PoloniusOutput>>,

diags: diags::BorrowckDiags<'infcx, 'tcx>,
move_errors: Vec<MoveError<'tcx>>,
Expand Down Expand Up @@ -800,9 +796,8 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
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);
}
}
Expand All @@ -816,9 +811,8 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
// 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);
}
}
Expand Down Expand Up @@ -1037,13 +1031,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
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);
}
Expand All @@ -1057,7 +1050,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
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
Expand Down Expand Up @@ -1580,9 +1573,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
// 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 {
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub(crate) struct NllOutput<'tcx> {
pub regioncx: RegionInferenceContext<'tcx>,
pub opaque_type_values: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
pub polonius_input: Option<Box<AllFacts>>,
pub polonius_output: Option<Rc<PoloniusOutput>>,
pub polonius_output: Option<Box<PoloniusOutput>>,
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
pub nll_errors: RegionErrors<'tcx>,
}
Expand Down Expand Up @@ -98,7 +98,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(

let universal_regions = Rc::new(universal_regions);

let elements = &Rc::new(DenseLocationMap::new(body));
let elements = Rc::new(DenseLocationMap::new(body));

// Run the MIR type-checker.
let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
Expand All @@ -107,13 +107,13 @@ pub(crate) fn compute_regions<'a, 'tcx>(
param_env,
body,
promoted,
&universal_regions,
universal_regions.clone(),
location_table,
borrow_set,
&mut all_facts,
flow_inits,
move_data,
elements,
elements.clone(),
upvars,
);

Expand Down Expand Up @@ -165,7 +165,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
universe_causes,
type_tests,
liveness_constraints,
elements,
elements.clone(),
);

// If requested: dump NLL facts, and run legacy polonius analysis.
Expand All @@ -184,7 +184,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
let algorithm = Algorithm::from_str(&algorithm).unwrap();
debug!("compute_regions: using polonius algorithm {:?}", algorithm);
let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis");
Some(Rc::new(Output::compute(all_facts, algorithm, false)))
Some(Box::new(Output::compute(all_facts, algorithm, false)))
} else {
None
}
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues,
elements: &Rc<DenseLocationMap>,
elements: Rc<DenseLocationMap>,
) -> Self {
debug!("universal_regions: {:#?}", universal_regions);
debug!("outlives constraints: {:#?}", outlives_constraints);
Expand All @@ -430,7 +430,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}

let mut scc_values =
RegionValues::new(elements, universal_regions.len(), &placeholder_indices);
RegionValues::new(elements, universal_regions.len(), placeholder_indices);

for region in liveness_constraints.regions() {
let scc = constraint_sccs.scc(region);
Expand Down Expand Up @@ -637,7 +637,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
&mut self,
infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>,
polonius_output: Option<Rc<PoloniusOutput>>,
polonius_output: Option<Box<PoloniusOutput>>,
) -> (Option<ClosureRegionRequirements<'tcx>>, RegionErrors<'tcx>) {
let mir_def_id = body.source.def_id();
self.propagate_constraints();
Expand All @@ -663,7 +663,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.check_polonius_subset_errors(
outlives_requirements.as_mut(),
&mut errors_buffer,
polonius_output.expect("Polonius output is unavailable despite `-Z polonius`"),
polonius_output
.as_ref()
.expect("Polonius output is unavailable despite `-Z polonius`"),
);
} else {
self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer);
Expand Down Expand Up @@ -1411,7 +1413,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
&self,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
errors_buffer: &mut RegionErrors<'tcx>,
polonius_output: Rc<PoloniusOutput>,
polonius_output: &PoloniusOutput,
) {
debug!(
"check_polonius_subset_errors: {} subset_errors",
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_borrowck/src/region_infer/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,15 +275,16 @@ impl<N: Idx> RegionValues<N> {
/// Each of the regions in num_region_variables will be initialized with an
/// empty set of points and no causal information.
pub(crate) fn new(
elements: &Rc<DenseLocationMap>,
elements: Rc<DenseLocationMap>,
num_universal_regions: usize,
placeholder_indices: &Rc<PlaceholderIndices>,
placeholder_indices: Rc<PlaceholderIndices>,
) -> Self {
let num_points = elements.num_points();
let num_placeholders = placeholder_indices.len();
Self {
elements: elements.clone(),
points: SparseIntervalMatrix::new(elements.num_points()),
placeholder_indices: placeholder_indices.clone(),
elements,
points: SparseIntervalMatrix::new(num_points),
placeholder_indices,
free_regions: SparseBitMatrix::new(num_universal_regions),
placeholders: SparseBitMatrix::new(num_placeholders),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ pub(crate) fn create<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
universal_regions: &Rc<UniversalRegions<'tcx>>,
universal_regions: Rc<UniversalRegions<'tcx>>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
) -> CreateResult<'tcx> {
UniversalRegionRelationsBuilder {
infcx,
param_env,
implicit_region_bound,
constraints,
universal_regions: universal_regions.clone(),
universal_regions,
region_bound_pairs: Default::default(),
outlives: Default::default(),
inverse_outlives: Default::default(),
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_borrowck/src/type_check/liveness/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::rc::Rc;

use itertools::{Either, Itertools};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::visit::{TyContext, Visitor};
Expand Down Expand Up @@ -33,7 +31,7 @@ mod trace;
pub(super) fn generate<'a, 'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>,
elements: &Rc<DenseLocationMap>,
elements: &DenseLocationMap,
flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
move_data: &MoveData<'tcx>,
) {
Expand Down
Loading
Loading