represent `LivenessValues` with a specialized type
This commit is contained in:
parent
2fda456ddf
commit
2584216364
|
@ -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>,
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
Loading…
Reference in New Issue