Skip to content

Commit

Permalink
Get Polonius borrow check to work in simple cases
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
matthewjasper committed Sep 26, 2018
1 parent c7df1f5 commit 610903f
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/invalidation.rs
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
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
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
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
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
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

0 comments on commit 610903f

Please sign in to comment.