Skip to content

Commit 8876906

Browse files
committed
Auto merge of rust-lang#54468 - matthewjasper:fix-polonius, r=nikomatsakis
[NLL] Get Polonius borrow check to work in simple cases * Restores the generation of outlives facts from subtyping. * Restore liveness facts. * Generate invalidates facts at the start point of each location, where we check for errors. * Add a small test for simple cases (previously these cases have compiled, and more recently ICEd). Closes rust-lang#54212 cc rust-lang#53142 (will need test) ### Known limitations * Two phase borrows aren't implemented for Polonius yet * Invalidation facts haven't been updated for some of the recent changes to make `Drop` terminators access fewer things. * Fact generation is not as optimized as it could be. * Around 30 tests fail in compare mode, often tests that are ignored in nll compare mode r? @nikomatsakis
2 parents f1694ea + 610903f commit 8876906

File tree

10 files changed

+172
-80
lines changed

10 files changed

+172
-80
lines changed

src/librustc_mir/borrow_check/nll/invalidation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
479479

480480
/// Generate a new invalidates(L, B) fact
481481
fn generate_invalidates(&mut self, b: BorrowIndex, l: Location) {
482-
let lidx = self.location_table.mid_index(l);
482+
let lidx = self.location_table.start_index(l);
483483
self.all_facts.invalidates.push((lidx, b));
484484
}
485485
}

src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs

-25
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::location::LocationTable;
1211
use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
13-
use borrow_check::nll::facts::AllFacts;
1412
use borrow_check::nll::region_infer::TypeTest;
1513
use borrow_check::nll::type_check::Locations;
1614
use borrow_check::nll::universal_regions::UniversalRegions;
@@ -26,43 +24,37 @@ use syntax_pos::DUMMY_SP;
2624
crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
2725
tcx: TyCtxt<'a, 'gcx, 'tcx>,
2826
universal_regions: &'a UniversalRegions<'tcx>,
29-
location_table: &'a LocationTable,
3027
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
3128
implicit_region_bound: Option<ty::Region<'tcx>>,
3229
param_env: ty::ParamEnv<'tcx>,
3330
locations: Locations,
3431
category: ConstraintCategory,
3532
outlives_constraints: &'a mut ConstraintSet,
3633
type_tests: &'a mut Vec<TypeTest<'tcx>>,
37-
all_facts: &'a mut Option<AllFacts>,
3834
}
3935

4036
impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
4137
crate fn new(
4238
tcx: TyCtxt<'a, 'gcx, 'tcx>,
4339
universal_regions: &'a UniversalRegions<'tcx>,
44-
location_table: &'a LocationTable,
4540
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
4641
implicit_region_bound: Option<ty::Region<'tcx>>,
4742
param_env: ty::ParamEnv<'tcx>,
4843
locations: Locations,
4944
category: ConstraintCategory,
5045
outlives_constraints: &'a mut ConstraintSet,
5146
type_tests: &'a mut Vec<TypeTest<'tcx>>,
52-
all_facts: &'a mut Option<AllFacts>,
5347
) -> Self {
5448
Self {
5549
tcx,
5650
universal_regions,
57-
location_table,
5851
region_bound_pairs,
5952
implicit_region_bound,
6053
param_env,
6154
locations,
6255
category,
6356
outlives_constraints,
6457
type_tests,
65-
all_facts,
6658
}
6759
}
6860

@@ -101,23 +93,6 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
10193
let r1_vid = self.to_region_vid(r1);
10294
let r2_vid = self.to_region_vid(r2);
10395
self.add_outlives(r1_vid, r2_vid);
104-
105-
// In the new analysis, all outlives relations etc
106-
// "take effect" at the mid point of the statement
107-
// that requires them, so ignore the `at_location`.
108-
if let Some(all_facts) = &mut self.all_facts {
109-
if let Some(from_location) = self.locations.from_location() {
110-
all_facts.outlives.push((
111-
r1_vid,
112-
r2_vid,
113-
self.location_table.mid_index(from_location),
114-
));
115-
} else {
116-
for location in self.location_table.all_points() {
117-
all_facts.outlives.push((r1_vid, r2_vid, location));
118-
}
119-
}
120-
}
12196
}
12297

12398
UnpackedKind::Type(t1) => {

src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs

-10
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::location::LocationTable;
12-
use borrow_check::nll::facts::AllFacts;
1311
use borrow_check::nll::type_check::constraint_conversion;
1412
use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
1513
use borrow_check::nll::universal_regions::UniversalRegions;
@@ -69,19 +67,15 @@ crate struct CreateResult<'tcx> {
6967
crate fn create(
7068
infcx: &InferCtxt<'_, '_, 'tcx>,
7169
param_env: ty::ParamEnv<'tcx>,
72-
location_table: &LocationTable,
7370
implicit_region_bound: Option<ty::Region<'tcx>>,
7471
universal_regions: &Rc<UniversalRegions<'tcx>>,
7572
constraints: &mut MirTypeckRegionConstraints<'tcx>,
76-
all_facts: &mut Option<AllFacts>,
7773
) -> CreateResult<'tcx> {
7874
UniversalRegionRelationsBuilder {
7975
infcx,
8076
param_env,
8177
implicit_region_bound,
8278
constraints,
83-
location_table,
84-
all_facts,
8579
universal_regions: universal_regions.clone(),
8680
region_bound_pairs: Vec::new(),
8781
relations: UniversalRegionRelations {
@@ -210,11 +204,9 @@ impl UniversalRegionRelations<'tcx> {
210204
struct UniversalRegionRelationsBuilder<'this, 'gcx: 'tcx, 'tcx: 'this> {
211205
infcx: &'this InferCtxt<'this, 'gcx, 'tcx>,
212206
param_env: ty::ParamEnv<'tcx>,
213-
location_table: &'this LocationTable,
214207
universal_regions: Rc<UniversalRegions<'tcx>>,
215208
implicit_region_bound: Option<ty::Region<'tcx>>,
216209
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
217-
all_facts: &'this mut Option<AllFacts>,
218210

219211
// outputs:
220212
relations: UniversalRegionRelations<'tcx>,
@@ -281,15 +273,13 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
281273
constraint_conversion::ConstraintConversion::new(
282274
self.infcx.tcx,
283275
&self.universal_regions,
284-
&self.location_table,
285276
&self.region_bound_pairs,
286277
self.implicit_region_bound,
287278
self.param_env,
288279
Locations::All(DUMMY_SP),
289280
ConstraintCategory::Internal,
290281
&mut self.constraints.outlives_constraints,
291282
&mut self.constraints.type_tests,
292-
&mut self.all_facts,
293283
).convert_all(&data);
294284
}
295285

src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//! types, instead of all variables.
1818
1919
use borrow_check::nll::ToRegionVid;
20+
use borrow_check::nll::facts::{AllFacts, AllFactsExt};
2021
use rustc::mir::{Local, Mir};
2122
use rustc::ty::{RegionVid, TyCtxt};
2223
use rustc_data_structures::fx::FxHashSet;
@@ -61,12 +62,13 @@ impl NllLivenessMap {
6162
mir: &Mir<'tcx>,
6263
) -> Self {
6364
let mut to_local = IndexVec::default();
65+
let facts_enabled = AllFacts::enabled(tcx);
6466
let from_local: IndexVec<Local, Option<_>> = mir.local_decls
6567
.iter_enumerated()
6668
.map(|(local, local_decl)| {
6769
if tcx.all_free_regions_meet(&local_decl.ty, |r| {
6870
free_regions.contains(&r.to_region_vid())
69-
}) {
71+
}) && !facts_enabled {
7072
// If all the regions in the type are free regions
7173
// (or there are no regions), then we don't need
7274
// to track liveness for this variable.

src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use borrow_check::location::LocationTable;
1112
use borrow_check::nll::region_infer::values::RegionValueElements;
1213
use borrow_check::nll::constraints::ConstraintSet;
1314
use borrow_check::nll::NllLivenessMap;
@@ -40,6 +41,7 @@ pub(super) fn generate<'gcx, 'tcx>(
4041
elements: &Rc<RegionValueElements>,
4142
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
4243
move_data: &MoveData<'tcx>,
44+
location_table: &LocationTable,
4345
) {
4446
debug!("liveness::generate");
4547
let free_regions = {
@@ -51,7 +53,7 @@ pub(super) fn generate<'gcx, 'tcx>(
5153
)
5254
};
5355
let liveness_map = NllLivenessMap::compute(typeck.tcx(), &free_regions, mir);
54-
trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map);
56+
trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map, location_table);
5557
}
5658

5759
/// Compute all regions that are (currently) known to outlive free

src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs

+27-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use borrow_check::location::LocationTable;
1112
use borrow_check::nll::constraints::ConstraintCategory;
1213
use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
1314
use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
@@ -49,6 +50,7 @@ pub(super) fn trace(
4950
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
5051
move_data: &MoveData<'tcx>,
5152
liveness_map: &NllLivenessMap,
53+
location_table: &LocationTable,
5254
) {
5355
debug!("trace()");
5456

@@ -67,6 +69,7 @@ pub(super) fn trace(
6769
move_data,
6870
liveness_map,
6971
drop_data: FxHashMap::default(),
72+
location_table,
7073
};
7174

7275
LivenessResults::new(cx).compute_for_all_locals();
@@ -105,6 +108,9 @@ where
105108

106109
/// Map tracking which variables need liveness computation.
107110
liveness_map: &'me NllLivenessMap,
111+
112+
/// Maps between a MIR Location and a LocationIndex
113+
location_table: &'me LocationTable,
108114
}
109115

110116
struct DropData<'tcx> {
@@ -453,7 +459,13 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
453459
) {
454460
debug!("add_use_live_facts_for(value={:?})", value);
455461

456-
Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at)
462+
Self::make_all_regions_live(
463+
self.elements,
464+
&mut self.typeck,
465+
value,
466+
live_at,
467+
self.location_table,
468+
)
457469
}
458470

459471
/// Some variable with type `live_ty` is "drop live" at `location`
@@ -505,7 +517,13 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
505517
// All things in the `outlives` array may be touched by
506518
// the destructor and must be live at this point.
507519
for &kind in &drop_data.dropck_result.kinds {
508-
Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at);
520+
Self::make_all_regions_live(
521+
self.elements,
522+
&mut self.typeck,
523+
kind,
524+
live_at,
525+
self.location_table,
526+
);
509527
}
510528
}
511529

@@ -514,6 +532,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
514532
typeck: &mut TypeChecker<'_, '_, 'tcx>,
515533
value: impl TypeFoldable<'tcx>,
516534
live_at: &HybridBitSet<PointIndex>,
535+
location_table: &LocationTable,
517536
) {
518537
debug!("make_all_regions_live(value={:?})", value);
519538
debug!(
@@ -532,8 +551,12 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
532551
.liveness_constraints
533552
.add_elements(live_region_vid, live_at);
534553

535-
if let Some(_) = borrowck_context.all_facts {
536-
bug!("polonius liveness facts not implemented yet")
554+
if let Some(facts) = borrowck_context.all_facts {
555+
for point in live_at.iter() {
556+
let loc = elements.to_location(point);
557+
facts.region_live_at.push((live_region_vid, location_table.start_index(loc)));
558+
facts.region_live_at.push((live_region_vid, location_table.mid_index(loc)));
559+
}
537560
}
538561
});
539562
}

0 commit comments

Comments
 (0)