Skip to content

Commit 08b2c37

Browse files
committed
Auto merge of rust-lang#117593 - lqd:polonius-crater, r=<try>
crater: assert_eq!(NLL, location-insensitive polonius); Crater run to check `-Zpolonius=next`. Any differences in how NLLs and location-insensitive polonius compute scopes will cause an assert to trip and an ICE. Depends on rust-lang#117560 to fix the last known fuzzing example where there was such a difference. r? `@ghost`
2 parents 5a9e0e8 + 952ab19 commit 08b2c37

File tree

6 files changed

+100
-98
lines changed

6 files changed

+100
-98
lines changed

compiler/rustc_borrowck/src/nll.rs

+16-21
Original file line numberDiff line numberDiff line change
@@ -182,26 +182,22 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
182182
let elements = &Rc::new(RegionValueElements::new(body));
183183

184184
// Run the MIR type-checker.
185-
let MirTypeckResults {
186-
constraints,
187-
universal_region_relations,
188-
opaque_type_values,
189-
live_loans,
190-
} = type_check::type_check(
191-
infcx,
192-
param_env,
193-
body,
194-
promoted,
195-
&universal_regions,
196-
location_table,
197-
borrow_set,
198-
&mut all_facts,
199-
flow_inits,
200-
move_data,
201-
elements,
202-
upvars,
203-
polonius_input,
204-
);
185+
let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
186+
type_check::type_check(
187+
infcx,
188+
param_env,
189+
body,
190+
promoted,
191+
&universal_regions,
192+
location_table,
193+
borrow_set,
194+
&mut all_facts,
195+
flow_inits,
196+
move_data,
197+
elements,
198+
upvars,
199+
polonius_input,
200+
);
205201

206202
if let Some(all_facts) = &mut all_facts {
207203
let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation");
@@ -279,7 +275,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
279275
type_tests,
280276
liveness_constraints,
281277
elements,
282-
live_loans,
283278
);
284279

285280
// Generate various additional constraints.

compiler/rustc_borrowck/src/region_infer/mod.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
77
use rustc_data_structures::graph::scc::Sccs;
88
use rustc_errors::Diagnostic;
99
use rustc_hir::def_id::CRATE_DEF_ID;
10-
use rustc_index::bit_set::SparseBitMatrix;
1110
use rustc_index::{IndexSlice, IndexVec};
1211
use rustc_infer::infer::outlives::test_type_match;
1312
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
@@ -31,8 +30,8 @@ use crate::{
3130
nll::PoloniusOutput,
3231
region_infer::reverse_sccs::ReverseSccGraph,
3332
region_infer::values::{
34-
LivenessValues, PlaceholderIndices, PointIndex, RegionElement, RegionValueElements,
35-
RegionValues, ToElementIndex,
33+
LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
34+
ToElementIndex,
3635
},
3736
type_check::{free_region_relations::UniversalRegionRelations, Locations},
3837
universal_regions::UniversalRegions,
@@ -120,9 +119,6 @@ pub struct RegionInferenceContext<'tcx> {
120119
/// Information about how the universally quantified regions in
121120
/// scope on this function relate to one another.
122121
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
123-
124-
/// The set of loans that are live at a given point in the CFG, when using `-Zpolonius=next`.
125-
live_loans: SparseBitMatrix<PointIndex, BorrowIndex>,
126122
}
127123

128124
/// Each time that `apply_member_constraint` is successful, it appends
@@ -335,7 +331,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
335331
type_tests: Vec<TypeTest<'tcx>>,
336332
liveness_constraints: LivenessValues<RegionVid>,
337333
elements: &Rc<RegionValueElements>,
338-
live_loans: SparseBitMatrix<PointIndex, BorrowIndex>,
339334
) -> Self {
340335
debug!("universal_regions: {:#?}", universal_regions);
341336
debug!("outlives constraints: {:#?}", outlives_constraints);
@@ -389,7 +384,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
389384
type_tests,
390385
universal_regions,
391386
universal_region_relations,
392-
live_loans,
393387
};
394388

395389
result.init_free_and_bound_regions();
@@ -2325,7 +2319,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
23252319
/// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`.
23262320
pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool {
23272321
let point = self.liveness_constraints.point_from_location(location);
2328-
self.live_loans.contains(point, loan_idx)
2322+
self.liveness_constraints.is_loan_live_at(loan_idx, point)
23292323
}
23302324
}
23312325

compiler/rustc_borrowck/src/region_infer/values.rs

+63-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use rustc_middle::ty::{self, RegionVid};
1111
use std::fmt::Debug;
1212
use std::rc::Rc;
1313

14+
use crate::dataflow::BorrowIndex;
15+
1416
/// Maps between a `Location` and a `PointIndex` (and vice versa).
1517
pub(crate) struct RegionValueElements {
1618
/// For each basic block, how many points are contained within?
@@ -120,16 +122,47 @@ pub(crate) enum RegionElement {
120122
/// When we initially compute liveness, we use an interval matrix storing
121123
/// liveness ranges for each region-vid.
122124
pub(crate) struct LivenessValues<N: Idx> {
125+
/// The map from locations to points.
123126
elements: Rc<RegionValueElements>,
127+
128+
/// For each region: the points where it is live.
124129
points: SparseIntervalMatrix<N, PointIndex>,
130+
131+
/// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at
132+
/// that point.
133+
pub(crate) loans: Option<LiveLoans<N>>,
134+
}
135+
136+
/// Data used to compute the loans that are live at a given point in the CFG, when using
137+
/// `-Zpolonius=next`.
138+
pub(crate) struct LiveLoans<N: Idx> {
139+
/// The set of loans that flow into a given region. When individual regions are marked as live
140+
/// in the CFG, these inflowing loans are recorded as live.
141+
pub(crate) inflowing_loans: SparseBitMatrix<N, BorrowIndex>,
142+
143+
/// The set of loans that are live at a given point in the CFG.
144+
pub(crate) live_loans: SparseBitMatrix<PointIndex, BorrowIndex>,
145+
}
146+
147+
impl<N: Idx> LiveLoans<N> {
148+
pub(crate) fn new(num_loans: usize) -> Self {
149+
LiveLoans {
150+
live_loans: SparseBitMatrix::new(num_loans),
151+
inflowing_loans: SparseBitMatrix::new(num_loans),
152+
}
153+
}
125154
}
126155

127156
impl<N: Idx> LivenessValues<N> {
128157
/// Creates a new set of "region values" that tracks causal information.
129158
/// Each of the regions in num_region_variables will be initialized with an
130159
/// empty set of points and no causal information.
131160
pub(crate) fn new(elements: Rc<RegionValueElements>) -> Self {
132-
Self { points: SparseIntervalMatrix::new(elements.num_points), elements }
161+
LivenessValues {
162+
points: SparseIntervalMatrix::new(elements.num_points),
163+
elements,
164+
loans: None,
165+
}
133166
}
134167

135168
/// Iterate through each region that has a value in this set.
@@ -142,13 +175,33 @@ impl<N: Idx> LivenessValues<N> {
142175
pub(crate) fn add_element(&mut self, row: N, location: Location) -> bool {
143176
debug!("LivenessValues::add(r={:?}, location={:?})", row, location);
144177
let index = self.elements.point_from_location(location);
178+
179+
// When available, record the loans flowing into this region as live at the given point.
180+
if let Some(loans) = self.loans.as_mut() {
181+
if let Some(inflowing) = loans.inflowing_loans.row(row) {
182+
loans.live_loans.union_row(index, inflowing);
183+
}
184+
}
185+
145186
self.points.insert(row, index)
146187
}
147188

148189
/// Adds all the elements in the given bit array into the given
149190
/// region. Returns whether any of them are newly added.
150191
pub(crate) fn add_elements(&mut self, row: N, locations: &IntervalSet<PointIndex>) -> bool {
151192
debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations);
193+
194+
// When available, record the loans flowing into this region as live at the given points.
195+
if let Some(loans) = self.loans.as_mut() {
196+
if let Some(inflowing) = loans.inflowing_loans.row(row) {
197+
if !inflowing.is_empty() {
198+
for point in locations.iter() {
199+
loans.live_loans.union_row(point, inflowing);
200+
}
201+
}
202+
}
203+
}
204+
152205
self.points.union_row(row, locations)
153206
}
154207

@@ -182,6 +235,15 @@ impl<N: Idx> LivenessValues<N> {
182235
pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
183236
self.elements.point_from_location(location)
184237
}
238+
239+
/// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
240+
pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
241+
self.loans
242+
.as_ref()
243+
.expect("Accessing live loans requires `-Zpolonius=next`")
244+
.live_loans
245+
.contains(point, loan_idx)
246+
}
185247
}
186248

187249
/// Maps from `ty::PlaceholderRegion` values that are used in the rest of

compiler/rustc_borrowck/src/type_check/liveness/trace.rs

+16-51
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
22
use rustc_data_structures::graph::WithSuccessors;
3-
use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix};
3+
use rustc_index::bit_set::HybridBitSet;
44
use rustc_index::interval::IntervalSet;
55
use rustc_infer::infer::canonical::QueryRegionConstraints;
66
use rustc_infer::infer::outlives::for_liveness;
77
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
88
use rustc_middle::traits::query::DropckOutlivesResult;
9-
use rustc_middle::ty::{RegionVid, Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
9+
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
1010
use rustc_span::DUMMY_SP;
1111
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
1212
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -16,9 +16,8 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
1616
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
1717
use rustc_mir_dataflow::ResultsCursor;
1818

19-
use crate::dataflow::BorrowIndex;
2019
use crate::{
21-
region_infer::values::{self, PointIndex, RegionValueElements},
20+
region_infer::values::{self, LiveLoans, PointIndex, RegionValueElements},
2221
type_check::liveness::local_use_map::LocalUseMap,
2322
type_check::liveness::polonius,
2423
type_check::NormalizeLocation,
@@ -54,17 +53,17 @@ pub(super) fn trace<'mir, 'tcx>(
5453
let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body);
5554

5655
// When using `-Zpolonius=next`, compute the set of loans that can reach a given region.
57-
let num_loans = typeck.borrowck_context.borrow_set.len();
58-
let mut inflowing_loans = SparseBitMatrix::new(num_loans);
5956
if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() {
60-
let borrowck_context = &typeck.borrowck_context;
57+
let borrowck_context = &mut typeck.borrowck_context;
58+
6159
let borrow_set = &borrowck_context.borrow_set;
62-
let constraint_set = &borrowck_context.constraints.outlives_constraints;
60+
let mut live_loans = LiveLoans::new(borrow_set.len());
6361

6462
let num_region_vars = typeck.infcx.num_region_vars();
65-
let graph = constraint_set.graph(num_region_vars);
63+
let outlives_constraints = &borrowck_context.constraints.outlives_constraints;
64+
let graph = outlives_constraints.graph(num_region_vars);
6665
let region_graph =
67-
graph.region_graph(constraint_set, borrowck_context.universal_regions.fr_static);
66+
graph.region_graph(outlives_constraints, borrowck_context.universal_regions.fr_static);
6867

6968
// Traverse each issuing region's constraints, and record the loan as flowing into the
7069
// outlived region.
@@ -75,9 +74,13 @@ pub(super) fn trace<'mir, 'tcx>(
7574
continue;
7675
}
7776

78-
inflowing_loans.insert(succ, loan);
77+
live_loans.inflowing_loans.insert(succ, loan);
7978
}
8079
}
80+
81+
// Store the inflowing loans in the liveness constraints: they will be used to compute live
82+
// loans when liveness data is recorded there.
83+
borrowck_context.constraints.liveness_constraints.loans = Some(live_loans);
8184
};
8285

8386
let cx = LivenessContext {
@@ -88,7 +91,6 @@ pub(super) fn trace<'mir, 'tcx>(
8891
local_use_map,
8992
move_data,
9093
drop_data: FxIndexMap::default(),
91-
inflowing_loans,
9294
};
9395

9496
let mut results = LivenessResults::new(cx);
@@ -126,9 +128,6 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
126128
/// Index indicating where each variable is assigned, used, or
127129
/// dropped.
128130
local_use_map: &'me LocalUseMap,
129-
130-
/// Set of loans that flow into a given region, when using `-Zpolonius=next`.
131-
inflowing_loans: SparseBitMatrix<RegionVid, BorrowIndex>,
132131
}
133132

134133
struct DropData<'tcx> {
@@ -519,14 +518,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
519518
live_at: &IntervalSet<PointIndex>,
520519
) {
521520
debug!("add_use_live_facts_for(value={:?})", value);
522-
523-
Self::make_all_regions_live(
524-
self.elements,
525-
self.typeck,
526-
value,
527-
live_at,
528-
&self.inflowing_loans,
529-
);
521+
Self::make_all_regions_live(self.elements, self.typeck, value, live_at);
530522
}
531523

532524
/// Some variable with type `live_ty` is "drop live" at `location`
@@ -577,14 +569,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
577569
// All things in the `outlives` array may be touched by
578570
// the destructor and must be live at this point.
579571
for &kind in &drop_data.dropck_result.kinds {
580-
Self::make_all_regions_live(
581-
self.elements,
582-
self.typeck,
583-
kind,
584-
live_at,
585-
&self.inflowing_loans,
586-
);
587-
572+
Self::make_all_regions_live(self.elements, self.typeck, kind, live_at);
588573
polonius::add_drop_of_var_derefs_origin(self.typeck, dropped_local, &kind);
589574
}
590575
}
@@ -594,20 +579,13 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
594579
typeck: &mut TypeChecker<'_, 'tcx>,
595580
value: impl TypeVisitable<TyCtxt<'tcx>>,
596581
live_at: &IntervalSet<PointIndex>,
597-
inflowing_loans: &SparseBitMatrix<RegionVid, BorrowIndex>,
598582
) {
599583
debug!("make_all_regions_live(value={:?})", value);
600584
debug!(
601585
"make_all_regions_live: live_at={}",
602586
values::location_set_str(elements, live_at.iter()),
603587
);
604588

605-
// When using `-Zpolonius=next`, we want to record the loans that flow into this value's
606-
// regions as being live at the given `live_at` points: this will be used to compute the
607-
// location where a loan goes out of scope.
608-
let num_loans = typeck.borrowck_context.borrow_set.len();
609-
let value_loans = &mut HybridBitSet::new_empty(num_loans);
610-
611589
value.visit_with(&mut for_liveness::FreeRegionsVisitor {
612590
tcx: typeck.tcx(),
613591
param_env: typeck.param_env,
@@ -619,21 +597,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
619597
.constraints
620598
.liveness_constraints
621599
.add_elements(live_region_vid, live_at);
622-
623-
// There can only be inflowing loans for this region when we are using
624-
// `-Zpolonius=next`.
625-
if let Some(inflowing) = inflowing_loans.row(live_region_vid) {
626-
value_loans.union(inflowing);
627-
}
628600
},
629601
});
630-
631-
// Record the loans reaching the value.
632-
if !value_loans.is_empty() {
633-
for point in live_at.iter() {
634-
typeck.borrowck_context.live_loans.union_row(point, value_loans);
635-
}
636-
}
637602
}
638603

639604
fn compute_drop_data(

0 commit comments

Comments
 (0)