Skip to content

[NLL] Get Polonius borrow check to work in simple cases #54468

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

Merged
merged 1 commit into from
Sep 27, 2018
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
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/invalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {

/// Generate a new invalidates(L, B) fact
fn generate_invalidates(&mut self, b: BorrowIndex, l: Location) {
let lidx = self.location_table.mid_index(l);
let lidx = self.location_table.start_index(l);
self.all_facts.invalidates.push((lidx, b));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::location::LocationTable;
use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
use borrow_check::nll::facts::AllFacts;
use borrow_check::nll::region_infer::TypeTest;
use borrow_check::nll::type_check::Locations;
use borrow_check::nll::universal_regions::UniversalRegions;
Expand All @@ -26,43 +24,37 @@ use syntax_pos::DUMMY_SP;
crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
location_table: &'a LocationTable,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
category: ConstraintCategory,
outlives_constraints: &'a mut ConstraintSet,
type_tests: &'a mut Vec<TypeTest<'tcx>>,
all_facts: &'a mut Option<AllFacts>,
}

impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
crate fn new(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
location_table: &'a LocationTable,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
category: ConstraintCategory,
outlives_constraints: &'a mut ConstraintSet,
type_tests: &'a mut Vec<TypeTest<'tcx>>,
all_facts: &'a mut Option<AllFacts>,
) -> Self {
Self {
tcx,
universal_regions,
location_table,
region_bound_pairs,
implicit_region_bound,
param_env,
locations,
category,
outlives_constraints,
type_tests,
all_facts,
}
}

Expand Down Expand Up @@ -101,23 +93,6 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
let r1_vid = self.to_region_vid(r1);
let r2_vid = self.to_region_vid(r2);
self.add_outlives(r1_vid, r2_vid);

// In the new analysis, all outlives relations etc
// "take effect" at the mid point of the statement
// that requires them, so ignore the `at_location`.
if let Some(all_facts) = &mut self.all_facts {
if let Some(from_location) = self.locations.from_location() {
all_facts.outlives.push((
r1_vid,
r2_vid,
self.location_table.mid_index(from_location),
));
} else {
for location in self.location_table.all_points() {
all_facts.outlives.push((r1_vid, r2_vid, location));
}
}
}
}

UnpackedKind::Type(t1) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::location::LocationTable;
use borrow_check::nll::facts::AllFacts;
use borrow_check::nll::type_check::constraint_conversion;
use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
use borrow_check::nll::universal_regions::UniversalRegions;
Expand Down Expand Up @@ -69,19 +67,15 @@ crate struct CreateResult<'tcx> {
crate fn create(
infcx: &InferCtxt<'_, '_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
location_table: &LocationTable,
implicit_region_bound: Option<ty::Region<'tcx>>,
universal_regions: &Rc<UniversalRegions<'tcx>>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
all_facts: &mut Option<AllFacts>,
) -> CreateResult<'tcx> {
UniversalRegionRelationsBuilder {
infcx,
param_env,
implicit_region_bound,
constraints,
location_table,
all_facts,
universal_regions: universal_regions.clone(),
region_bound_pairs: Vec::new(),
relations: UniversalRegionRelations {
Expand Down Expand Up @@ -210,11 +204,9 @@ impl UniversalRegionRelations<'tcx> {
struct UniversalRegionRelationsBuilder<'this, 'gcx: 'tcx, 'tcx: 'this> {
infcx: &'this InferCtxt<'this, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
location_table: &'this LocationTable,
universal_regions: Rc<UniversalRegions<'tcx>>,
implicit_region_bound: Option<ty::Region<'tcx>>,
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
all_facts: &'this mut Option<AllFacts>,

// outputs:
relations: UniversalRegionRelations<'tcx>,
Expand Down Expand Up @@ -281,15 +273,13 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
constraint_conversion::ConstraintConversion::new(
self.infcx.tcx,
&self.universal_regions,
&self.location_table,
&self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
Locations::All(DUMMY_SP),
ConstraintCategory::Internal,
&mut self.constraints.outlives_constraints,
&mut self.constraints.type_tests,
&mut self.all_facts,
).convert_all(&data);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
//! types, instead of all variables.

use borrow_check::nll::ToRegionVid;
use borrow_check::nll::facts::{AllFacts, AllFactsExt};
use rustc::mir::{Local, Mir};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
Expand Down Expand Up @@ -61,12 +62,13 @@ impl NllLivenessMap {
mir: &Mir<'tcx>,
) -> Self {
let mut to_local = IndexVec::default();
let facts_enabled = AllFacts::enabled(tcx);
let from_local: IndexVec<Local, Option<_>> = mir.local_decls
.iter_enumerated()
.map(|(local, local_decl)| {
if tcx.all_free_regions_meet(&local_decl.ty, |r| {
free_regions.contains(&r.to_region_vid())
}) {
}) && !facts_enabled {
// If all the regions in the type are free regions
// (or there are no regions), then we don't need
// to track liveness for this variable.
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::location::LocationTable;
use borrow_check::nll::region_infer::values::RegionValueElements;
use borrow_check::nll::constraints::ConstraintSet;
use borrow_check::nll::NllLivenessMap;
Expand Down Expand Up @@ -40,6 +41,7 @@ pub(super) fn generate<'gcx, 'tcx>(
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
location_table: &LocationTable,
) {
debug!("liveness::generate");
let free_regions = {
Expand All @@ -51,7 +53,7 @@ pub(super) fn generate<'gcx, 'tcx>(
)
};
let liveness_map = NllLivenessMap::compute(typeck.tcx(), &free_regions, mir);
trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map);
trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map, location_table);
}

/// Compute all regions that are (currently) known to outlive free
Expand Down
31 changes: 27 additions & 4 deletions src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::location::LocationTable;
use borrow_check::nll::constraints::ConstraintCategory;
use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
Expand Down Expand Up @@ -49,6 +50,7 @@ pub(super) fn trace(
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
liveness_map: &NllLivenessMap,
location_table: &LocationTable,
) {
debug!("trace()");

Expand All @@ -67,6 +69,7 @@ pub(super) fn trace(
move_data,
liveness_map,
drop_data: FxHashMap::default(),
location_table,
};

LivenessResults::new(cx).compute_for_all_locals();
Expand Down Expand Up @@ -105,6 +108,9 @@ where

/// Map tracking which variables need liveness computation.
liveness_map: &'me NllLivenessMap,

/// Maps between a MIR Location and a LocationIndex
location_table: &'me LocationTable,
}

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

Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at)
Self::make_all_regions_live(
self.elements,
&mut self.typeck,
value,
live_at,
self.location_table,
)
}

/// Some variable with type `live_ty` is "drop live" at `location`
Expand Down Expand Up @@ -505,7 +517,13 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
// All things in the `outlives` array may be touched by
// the destructor and must be live at this point.
for &kind in &drop_data.dropck_result.kinds {
Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at);
Self::make_all_regions_live(
self.elements,
&mut self.typeck,
kind,
live_at,
self.location_table,
);
}
}

Expand All @@ -514,6 +532,7 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
typeck: &mut TypeChecker<'_, '_, 'tcx>,
value: impl TypeFoldable<'tcx>,
live_at: &HybridBitSet<PointIndex>,
location_table: &LocationTable,
) {
debug!("make_all_regions_live(value={:?})", value);
debug!(
Expand All @@ -532,8 +551,12 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> {
.liveness_constraints
.add_elements(live_region_vid, live_at);

if let Some(_) = borrowck_context.all_facts {
bug!("polonius liveness facts not implemented yet")
if let Some(facts) = borrowck_context.all_facts {
for point in live_at.iter() {
let loc = elements.to_location(point);
facts.region_live_at.push((live_region_vid, location_table.start_index(loc)));
facts.region_live_at.push((live_region_vid, location_table.mid_index(loc)));
}
}
});
}
Expand Down
Loading