represent `LivenessValues` with a specialized type

This commit is contained in:
Niko Matsakis 2018-07-23 22:28:28 +03:00
parent 2fda456ddf
commit 2584216364
4 changed files with 76 additions and 42 deletions

View File

@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::LocationTable;
use borrow_check::nll::ToRegionVid;
use borrow_check::nll::facts::AllFacts;
use borrow_check::nll::region_infer::values::RegionValues;
use borrow_check::nll::region_infer::values::LivenessValues;
use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
@ -24,7 +24,7 @@ use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, RegionVid};
pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
liveness_constraints: &mut RegionValues<RegionVid>,
liveness_constraints: &mut LivenessValues<RegionVid>,
all_facts: &mut Option<AllFacts>,
location_table: &LocationTable,
mir: &Mir<'tcx>,
@ -48,7 +48,7 @@ struct ConstraintGeneration<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> {
infcx: &'cg InferCtxt<'cx, 'gcx, 'tcx>,
all_facts: &'cg mut Option<AllFacts>,
location_table: &'cg LocationTable,
liveness_constraints: &'cg mut RegionValues<RegionVid>,
liveness_constraints: &'cg mut LivenessValues<RegionVid>,
borrow_set: &'cg BorrowSet<'tcx>,
}

View File

@ -37,7 +37,7 @@ mod dump_mir;
mod error_reporting;
mod graphviz;
pub mod values;
use self::values::{RegionValueElements, RegionValues};
use self::values::{RegionValueElements, RegionValues, LivenessValues};
use super::ToRegionVid;
@ -52,7 +52,7 @@ pub struct RegionInferenceContext<'tcx> {
/// regions, these start out empty and steadily grow, though for
/// each universally quantified region R they start out containing
/// the entire CFG and `end(R)`.
liveness_constraints: RegionValues<RegionVid>,
liveness_constraints: LivenessValues<RegionVid>,
/// The outlives constraints computed by the type-check.
constraints: Rc<ConstraintSet>,
@ -199,7 +199,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
_mir: &Mir<'tcx>,
outlives_constraints: ConstraintSet,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: RegionValues<RegionVid>,
liveness_constraints: LivenessValues<RegionVid>,
elements: &Rc<RegionValueElements>,
) -> Self {
let universal_regions = Rc::new(universal_regions);
@ -216,9 +216,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let mut scc_values = RegionValues::new(elements);
for region in liveness_constraints.regions_with_points() {
for region in liveness_constraints.rows() {
let scc = constraint_sccs.scc(region);
scc_values.merge_row(scc, region, &liveness_constraints);
scc_values.merge_liveness(scc, region, &liveness_constraints);
}
let mut result = Self {
@ -283,7 +283,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.scc_values.add_all_points(variable_scc);
// Add `end(X)` into the set for X.
self.add_live_element(variable, variable);
self.add_element_to_scc_of(variable, variable);
}
}
@ -314,27 +314,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.scc_values.region_value_str(scc)
}
/// Indicates that the region variable `v` is live at the point `point`.
///
/// Returns `true` if this constraint is new and `false` is the
/// constraint was already present.
pub(super) fn add_live_element(
&mut self,
v: RegionVid,
elem: impl ToElementIndex,
) -> bool {
/// Adds `elem` to the value of the SCC in which `v` appears.
fn add_element_to_scc_of(&mut self, v: RegionVid, elem: impl ToElementIndex) {
debug!("add_live_element({:?}, {:?})", v, elem);
// Add to the liveness values for `v`...
if self.liveness_constraints.add_element(v, elem) {
// ...but also add to the SCC in which `v` appears.
let scc = self.constraint_sccs.scc(v);
self.scc_values.add_element(scc, elem);
true
} else {
false
}
let scc = self.constraint_sccs.scc(v);
self.scc_values.add_element(scc, elem);
}
/// Perform region inference and report errors if we see any

View File

@ -117,6 +117,65 @@ crate enum RegionElement {
RootUniversalRegion(RegionVid),
}
/// When we initially compute liveness, we use a bit matrix storing
/// points for each region-vid.
crate struct LivenessValues<N: Idx> {
elements: Rc<RegionValueElements>,
points: SparseBitMatrix<N, PointIndex>,
}
impl<N: Idx> LivenessValues<N> {
/// Creates a new set of "region values" that tracks causal information.
/// Each of the regions in num_region_variables will be initialized with an
/// empty set of points and no causal information.
crate fn new(elements: &Rc<RegionValueElements>) -> Self {
Self {
elements: elements.clone(),
points: SparseBitMatrix::new(elements.num_points),
}
}
/// Iterate through each region that has a value in this set.
crate fn rows<'a>(&'a self) -> impl Iterator<Item = N> {
self.points.rows()
}
/// Adds the given element to the value for the given region. Returns true if
/// the element is newly added (i.e., was not already present).
crate fn add_element(
&mut self,
row: N,
location: Location,
) -> bool {
debug!("LivenessValues::add(r={:?}, location={:?})", row, location);
let index = self.elements.point_from_location(location);
self.points.add(row, index)
}
/// Adds all the control-flow points to the values for `r`.
crate fn add_all_points(&mut self, row: N) {
self.points.add_all(row);
}
/// True if the region `r` contains the given element.
crate fn contains(&self, row: N, location: Location) -> bool {
let index = self.elements.point_from_location(location);
self.points.contains(row, index)
}
/// Returns a "pretty" string value of the region. Meant for debugging.
crate fn region_value_str(&self, r: N) -> String {
region_value_str(
self.points
.row(r)
.into_iter()
.flat_map(|set| set.iter())
.map(|p| self.elements.to_location(p))
.map(RegionElement::Location)
)
}
}
/// Stores the values for a set of regions. These are stored in a
/// compact `SparseBitMatrix` representation, with one row per region
/// variable. The columns consist of either universal regions or
@ -172,22 +231,13 @@ impl<N: Idx> RegionValues<N> {
elem.contained_in_row(self, r)
}
/// Iterate through each region that has a value in this set.
crate fn regions_with_points<'a>(&'a self) -> impl Iterator<Item = N> {
self.points.rows()
}
/// `self[to] |= values[from]`, essentially: that is, take all the
/// elements for the region `from` from `values` and add them to
/// the region `to` in `self`.
crate fn merge_row<M: Idx>(&mut self, to: N, from: M, values: &RegionValues<M>) {
crate fn merge_liveness<M: Idx>(&mut self, to: N, from: M, values: &LivenessValues<M>) {
if let Some(set) = values.points.row(from) {
self.points.merge_into(to, set);
}
if let Some(set) = values.free_regions.row(from) {
self.free_regions.merge_into(to, set);
}
}
/// True if `sup_region` contains all the CFG points that

View File

@ -15,8 +15,8 @@ use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::LocationTable;
use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
use borrow_check::nll::facts::AllFacts;
use borrow_check::nll::region_infer::values::{RegionValueElements, LivenessValues};
use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
use borrow_check::nll::region_infer::values::{RegionValues, RegionValueElements};
use borrow_check::nll::universal_regions::UniversalRegions;
use borrow_check::nll::ToRegionVid;
use borrow_check::nll::LocalWithRegion;
@ -121,7 +121,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
) -> MirTypeckRegionConstraints<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
let mut constraints = MirTypeckRegionConstraints {
liveness_constraints: RegionValues::new(elements),
liveness_constraints: LivenessValues::new(elements),
outlives_constraints: ConstraintSet::default(),
type_tests: Vec::default(),
};
@ -638,7 +638,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
/// not otherwise appear in the MIR -- in particular, the
/// late-bound regions that it instantiates at call-sites -- and
/// hence it must report on their liveness constraints.
crate liveness_constraints: RegionValues<RegionVid>,
crate liveness_constraints: LivenessValues<RegionVid>,
crate outlives_constraints: ConstraintSet,