]> git.lizzy.rs Git - rust.git/commitdiff
represent `LivenessValues` with a specialized type
authorNiko Matsakis <niko@alum.mit.edu>
Mon, 23 Jul 2018 19:28:28 +0000 (22:28 +0300)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 25 Jul 2018 03:38:22 +0000 (06:38 +0300)
src/librustc_mir/borrow_check/nll/constraint_generation.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/values.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs

index 01e1dfe05fe03ff472107c013253b82d42705c40..457499ded565713dfea9bf9a08efed09b935f6bc 100644 (file)
@@ -12,7 +12,7 @@
 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 @@
 
 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>,
 }
 
index cf64f22084534367a0d64a1983560a97ef95a854..4853db50a6c96b4ec66693ea2db1ca5af12d3960 100644 (file)
@@ -37,7 +37,7 @@
 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 @@ pub(crate) fn new(
         _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 @@ pub(crate) fn new(
 
         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 @@ fn init_universal_regions(&mut self) {
             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 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
         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
index b1bcccdf1a047173dd27aad091c1fe9696954263..c31698720d5a2b1f4c7a48803e74bf280d851f6a 100644 (file)
@@ -117,6 +117,65 @@ fn point_from_location(&self, location: Location) -> PointIndex {
     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
index b6c8ffcf88d65ab5588e96bc9ecf3850447f62bf..e990a99f2b416de523661a1f819bff6492ece5fb 100644 (file)
@@ -15,8 +15,8 @@
 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 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
     /// 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,