Skip to content

Commit 447cc9d

Browse files
committed
Region inference: split results from RegionInferenceContext
This ensures all of region inference is immutable, and makes every operation that requires region inference to have been executed to run explicitly require the results.
1 parent eeb94be commit 447cc9d

27 files changed

+2063
-1947
lines changed

compiler/rustc_borrowck/src/consumers.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub use super::polonius::legacy::{
1616
PoloniusFacts as PoloniusInput, PoloniusLocationTable, PoloniusOutput, PoloniusRegionVid,
1717
RichLocation, RustcFacts,
1818
};
19-
pub use super::region_infer::RegionInferenceContext;
2019
use crate::BorrowCheckRootCtxt;
20+
use crate::region_infer::InferredRegions;
2121

2222
/// Struct used during mir borrowck to collect bodies with facts for a typeck root and all
2323
/// its nested bodies.
@@ -59,15 +59,15 @@ impl<'tcx> BorrowckConsumer<'tcx> {
5959
#[derive(Debug, Copy, Clone)]
6060
pub enum ConsumerOptions {
6161
/// Retrieve the [`Body`] along with the [`BorrowSet`]
62-
/// and [`RegionInferenceContext`]. If you would like the body only, use
62+
/// and [`InferredRegions`]. If you would like the body only, use
6363
/// [`TyCtxt::mir_promoted`].
6464
///
6565
/// These can be used in conjunction with [`calculate_borrows_out_of_scope_at_location`].
66-
RegionInferenceContext,
66+
InferredRegions,
6767
/// The recommended option. Retrieves the maximal amount of information
6868
/// without significant slowdowns.
6969
///
70-
/// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext),
70+
/// Implies [`InferredRegions`](ConsumerOptions::InferredRegions),
7171
/// and additionally retrieve the [`PoloniusLocationTable`] and [`PoloniusInput`] that
7272
/// would be given to Polonius. Critically, this does not run Polonius, which
7373
/// one may want to avoid due to performance issues on large bodies.
@@ -89,9 +89,10 @@ pub struct BodyWithBorrowckFacts<'tcx> {
8989
pub promoted: IndexVec<Promoted, Body<'tcx>>,
9090
/// The set of borrows occurring in `body` with data about them.
9191
pub borrow_set: BorrowSet<'tcx>,
92-
/// Context generated during borrowck, intended to be passed to
92+
/// The inferred region values. These are included because they
93+
/// are necessary as input to
9394
/// [`calculate_borrows_out_of_scope_at_location`].
94-
pub region_inference_context: RegionInferenceContext<'tcx>,
95+
pub inferred_regions: InferredRegions<'tcx>,
9596
/// The table that maps Polonius points to locations in the table.
9697
/// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
9798
/// or [`ConsumerOptions::PoloniusOutputFacts`].

compiler/rustc_borrowck/src/dataflow.rs

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::fmt;
22

3+
use either::Either;
34
use rustc_data_structures::fx::FxIndexMap;
45
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
56
use rustc_middle::mir::{
@@ -11,10 +12,13 @@ use rustc_mir_dataflow::impls::{
1112
EverInitializedPlaces, EverInitializedPlacesDomain, MaybeUninitializedPlaces,
1213
MaybeUninitializedPlacesDomain,
1314
};
15+
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
1416
use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice};
1517
use tracing::debug;
1618

17-
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
19+
use crate::polonius::{self, LiveLoans};
20+
use crate::region_infer::InferredRegions;
21+
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, places_conflict};
1822

1923
// This analysis is different to most others. Its results aren't computed with
2024
// `iterate_to_fixpoint`, but are instead composed from the results of three sub-analyses that are
@@ -182,34 +186,33 @@ struct OutOfScopePrecomputer<'a, 'tcx> {
182186
visited: DenseBitSet<mir::BasicBlock>,
183187
visit_stack: Vec<mir::BasicBlock>,
184188
body: &'a Body<'tcx>,
185-
regioncx: &'a RegionInferenceContext<'tcx>,
186189
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
187190
}
188191

189192
impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
190193
fn compute(
191194
body: &Body<'tcx>,
192-
regioncx: &RegionInferenceContext<'tcx>,
195+
scc_values: &InferredRegions<'_>,
193196
borrow_set: &BorrowSet<'tcx>,
194197
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
195198
let mut prec = OutOfScopePrecomputer {
196199
visited: DenseBitSet::new_empty(body.basic_blocks.len()),
197200
visit_stack: vec![],
198201
body,
199-
regioncx,
200202
borrows_out_of_scope_at_location: FxIndexMap::default(),
201203
};
202204
for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
203205
let borrow_region = borrow_data.region;
204206
let location = borrow_data.reserve_location;
205-
prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
207+
prec.precompute_borrows_out_of_scope(scc_values, borrow_index, borrow_region, location);
206208
}
207209

208210
prec.borrows_out_of_scope_at_location
209211
}
210212

211213
fn precompute_borrows_out_of_scope(
212214
&mut self,
215+
scc_values: &InferredRegions<'_>,
213216
borrow_index: BorrowIndex,
214217
borrow_region: RegionVid,
215218
first_location: Location,
@@ -222,12 +225,9 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
222225
let first_lo = first_location.statement_index;
223226
let first_hi = first_bb_data.statements.len();
224227

225-
if let Some(kill_stmt) = self.regioncx.first_non_contained_inclusive(
226-
borrow_region,
227-
first_block,
228-
first_lo,
229-
first_hi,
230-
) {
228+
if let Some(kill_stmt) =
229+
scc_values.first_non_contained_inclusive(borrow_region, first_block, first_lo, first_hi)
230+
{
231231
let kill_location = Location { block: first_block, statement_index: kill_stmt };
232232
// If region does not contain a point at the location, then add to list and skip
233233
// successor locations.
@@ -255,7 +255,7 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
255255
let bb_data = &self.body[block];
256256
let num_stmts = bb_data.statements.len();
257257
if let Some(kill_stmt) =
258-
self.regioncx.first_non_contained_inclusive(borrow_region, block, 0, num_stmts)
258+
scc_values.first_non_contained_inclusive(borrow_region, block, 0, num_stmts)
259259
{
260260
let kill_location = Location { block, statement_index: kill_stmt };
261261
// If region does not contain a point at the location, then add to list and skip
@@ -285,25 +285,26 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
285285
// This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`.
286286
pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
287287
body: &Body<'tcx>,
288-
regioncx: &RegionInferenceContext<'tcx>,
288+
scc_values: &InferredRegions<'_>,
289289
borrow_set: &BorrowSet<'tcx>,
290290
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
291-
OutOfScopePrecomputer::compute(body, regioncx, borrow_set)
291+
OutOfScopePrecomputer::compute(body, scc_values, borrow_set)
292292
}
293293

294294
struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
295295
visited: DenseBitSet<mir::BasicBlock>,
296296
visit_stack: Vec<mir::BasicBlock>,
297297
body: &'a Body<'tcx>,
298-
regioncx: &'a RegionInferenceContext<'tcx>,
299-
298+
live_loans: &'a LiveLoans,
299+
location_map: &'a DenseLocationMap,
300300
loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
301301
}
302302

303303
impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
304304
fn compute(
305305
body: &Body<'tcx>,
306-
regioncx: &RegionInferenceContext<'tcx>,
306+
location_map: &DenseLocationMap,
307+
live_loans: &LiveLoans,
307308
borrow_set: &BorrowSet<'tcx>,
308309
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
309310
// The in-tree polonius analysis computes loans going out of scope using the
@@ -312,7 +313,8 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
312313
visited: DenseBitSet::new_empty(body.basic_blocks.len()),
313314
visit_stack: vec![],
314315
body,
315-
regioncx,
316+
live_loans,
317+
location_map,
316318
loans_out_of_scope_at_location: FxIndexMap::default(),
317319
};
318320
for (loan_idx, loan_data) in borrow_set.iter_enumerated() {
@@ -412,7 +414,8 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
412414
// Reachability is location-insensitive, and we could take advantage of that, by jumping
413415
// to a further point than just the next statement: we can jump to the furthest point
414416
// within the block where `r` is live.
415-
if self.regioncx.is_loan_live_at(loan_idx, location) {
417+
let point = self.location_map.point_from_location(location);
418+
if self.is_loan_live_at(loan_idx, point) {
416419
continue;
417420
}
418421

@@ -423,21 +426,28 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
423426

424427
None
425428
}
429+
430+
fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
431+
self.live_loans.contains(point, loan_idx)
432+
}
426433
}
427434

428435
impl<'a, 'tcx> Borrows<'a, 'tcx> {
429436
pub fn new(
430437
tcx: TyCtxt<'tcx>,
431438
body: &'a Body<'tcx>,
432-
regioncx: &RegionInferenceContext<'tcx>,
439+
inference_results: Either<&'a InferredRegions<'_>, &'a polonius::LiveLoans>,
440+
location_map: &DenseLocationMap,
433441
borrow_set: &'a BorrowSet<'tcx>,
434442
) -> Self {
435-
let borrows_out_of_scope_at_location =
436-
if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
437-
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set)
438-
} else {
439-
PoloniusOutOfScopePrecomputer::compute(body, regioncx, borrow_set)
440-
};
443+
let borrows_out_of_scope_at_location = match inference_results {
444+
Either::Left(inferred_regions) => {
445+
calculate_borrows_out_of_scope_at_location(body, inferred_regions, borrow_set)
446+
}
447+
Either::Right(live_loans) => {
448+
PoloniusOutOfScopePrecomputer::compute(body, location_map, live_loans, borrow_set)
449+
}
450+
};
441451
Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
442452
}
443453

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
401401
// started MIR borrowchecking with, so the region
402402
// constraints have already been taken. Use the data from
403403
// our `mbcx` instead.
404-
|vid| RegionVariableOrigin::Nll(mbcx.regioncx.definitions[vid].origin),
405-
|vid| mbcx.regioncx.definitions[vid].universe,
404+
|vid| RegionVariableOrigin::Nll(mbcx.definitions[vid].origin),
405+
|vid| mbcx.definitions[vid].universe,
406406
)
407407
}
408408
}

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3454,7 +3454,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
34543454

34553455
let tcx = self.infcx.tcx;
34563456

3457-
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
3457+
let return_ty = self.universal_regions().unnormalized_output_ty;
34583458

34593459
// to avoid panics
34603460
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use super::{RegionName, UseSpans, find_use};
2121
use crate::borrow_set::BorrowData;
2222
use crate::constraints::OutlivesConstraint;
2323
use crate::nll::ConstraintDescription;
24-
use crate::region_infer::{BlameConstraint, Cause};
24+
use crate::region_infer::{BlameConstraint, Cause, ConstraintSearch};
2525
use crate::{MirBorrowckCtxt, WriteKind};
2626

2727
#[derive(Debug)]
@@ -572,14 +572,23 @@ fn suggest_rewrite_if_let<G: EmissionGuarantee>(
572572
}
573573
}
574574

575-
impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
575+
impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
576+
pub(crate) fn constraint_search<'mbc>(&'mbc self) -> ConstraintSearch<'mbc, 'tcx> {
577+
ConstraintSearch {
578+
definitions: self.definitions,
579+
fr_static: self.universal_regions().fr_static,
580+
constraint_graph: &self.constraint_graph,
581+
constraints: &self.outlives_constraints,
582+
}
583+
}
584+
576585
fn free_region_constraint_info(
577586
&self,
578587
borrow_region: RegionVid,
579588
outlived_region: RegionVid,
580589
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<OutlivesConstraint<'tcx>>)
581590
{
582-
let (blame_constraint, path) = self.regioncx.best_blame_constraint(
591+
let (blame_constraint, path) = self.constraint_search().best_blame_constraint(
583592
borrow_region,
584593
NllRegionVariableOrigin::FreeRegion,
585594
outlived_region,
@@ -611,14 +620,17 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
611620
borrow: &BorrowData<'tcx>,
612621
kind_place: Option<(WriteKind, Place<'tcx>)>,
613622
) -> BorrowExplanation<'tcx> {
614-
let regioncx = &self.regioncx;
615623
let body: &Body<'_> = self.body;
616624
let tcx = self.infcx.tcx;
617625

618626
let borrow_region_vid = borrow.region;
619627
debug!(?borrow_region_vid);
620628

621-
let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
629+
let mut region_sub = self.constraint_search().find_sub_region_live_at(
630+
&self.liveness_constraints,
631+
borrow_region_vid,
632+
location,
633+
);
622634
debug!(?region_sub);
623635

624636
let mut use_location = location;
@@ -630,11 +642,13 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
630642
// loop iteration. In this case, try using the loop terminator location in
631643
// `find_sub_region_live_at`.
632644
if let Some(loop_terminator_location) =
633-
regioncx.find_loop_terminator_location(borrow.region, body)
645+
self.scc_values.find_loop_terminator_location(borrow.region, body)
634646
{
635-
region_sub = self
636-
.regioncx
637-
.find_sub_region_live_at(borrow_region_vid, loop_terminator_location);
647+
region_sub = self.constraint_search().find_sub_region_live_at(
648+
&self.liveness_constraints,
649+
borrow_region_vid,
650+
loop_terminator_location,
651+
);
638652
debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub);
639653
use_location = loop_terminator_location;
640654
use_in_later_iteration_of_loop = true;
@@ -658,7 +672,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
658672
false
659673
}
660674
};
661-
match find_use::find(body, regioncx, tcx, region_sub, use_location) {
675+
match find_use::find(body, self.scc_values, tcx, region_sub, use_location) {
662676
Some(Cause::LiveVar(local, location)) if !is_local_boring(local) => {
663677
let span = body.source_info(location).span;
664678
let spans = self

compiler/rustc_borrowck/src/diagnostics/find_use.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,36 @@ use rustc_middle::mir::{self, Body, Local, Location};
66
use rustc_middle::ty::{RegionVid, TyCtxt};
77

88
use crate::def_use::{self, DefUse};
9-
use crate::region_infer::{Cause, RegionInferenceContext};
9+
use crate::region_infer::{Cause, InferredRegions};
1010

1111
pub(crate) fn find<'tcx>(
1212
body: &Body<'tcx>,
13-
regioncx: &RegionInferenceContext<'tcx>,
13+
scc_values: &InferredRegions<'_>,
1414
tcx: TyCtxt<'tcx>,
1515
region_vid: RegionVid,
1616
start_point: Location,
1717
) -> Option<Cause> {
18-
let mut uf = UseFinder { body, regioncx, tcx, region_vid, start_point };
18+
let mut uf = UseFinder { body, tcx, region_vid, start_point, scc_values };
1919

2020
uf.find()
2121
}
2222

23-
struct UseFinder<'a, 'tcx> {
23+
struct UseFinder<'a, 'b, 'tcx> {
2424
body: &'a Body<'tcx>,
25-
regioncx: &'a RegionInferenceContext<'tcx>,
25+
scc_values: &'a InferredRegions<'b>,
2626
tcx: TyCtxt<'tcx>,
2727
region_vid: RegionVid,
2828
start_point: Location,
2929
}
3030

31-
impl<'a, 'tcx> UseFinder<'a, 'tcx> {
31+
impl<'a, 'b, 'tcx> UseFinder<'a, 'b, 'tcx> {
3232
fn find(&mut self) -> Option<Cause> {
3333
let mut queue = VecDeque::new();
3434
let mut visited = FxIndexSet::default();
3535

3636
queue.push_back(self.start_point);
3737
while let Some(p) = queue.pop_front() {
38-
if !self.regioncx.region_contains(self.region_vid, p) {
38+
if !self.scc_values.region_contains(self.region_vid, p) {
3939
continue;
4040
}
4141

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
666666
let tcx = self.infcx.tcx;
667667
let Some((gat_hir_id, generics)) = path.iter().find_map(|constraint| {
668668
let outlived = constraint.sub;
669-
if let Some(origin) = self.regioncx.definitions.get(outlived)
669+
if let Some(origin) = self.definitions.get(outlived)
670670
&& let NllRegionVariableOrigin::Placeholder(placeholder) = origin.origin
671671
&& let Some(id) = placeholder.bound.kind.get_id()
672672
&& let Some(placeholder_id) = id.as_local()

0 commit comments

Comments
 (0)