]> git.lizzy.rs Git - rust.git/commitdiff
consolidate and use `find_sub_region_live_at` for everything
authorNiko Matsakis <niko@alum.mit.edu>
Mon, 23 Jul 2018 19:03:08 +0000 (22:03 +0300)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 25 Jul 2018 03:38:21 +0000 (06:38 +0300)
remove the old blame system

src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr

index bc4646b7c789a1724cdc51d0e89589a9cf2c8d0c..0039958b6b14d3e724948fd7b6e2b77233e13fb9 100644 (file)
@@ -54,7 +54,7 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
             borrow_region_vid
         );
 
-        let region_sub = regioncx.find_constraint(borrow_region_vid, context.loc);
+        let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, context.loc);
 
         debug!(
             "explain_why_borrow_contains_point: region_sub={:?}",
index 054af74881957377d67babedc8bc714ca675de9b..acc1a33ea698dd9fdff445bfa6a106c774168404 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::region_infer::values::ToElementIndex;
 use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext};
 use borrow_check::nll::type_check::Locations;
 use rustc::hir::def_id::DefId;
@@ -75,11 +74,11 @@ fn best_blame_constraint(
         mir: &Mir<'tcx>,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> (ConstraintCategory, Span) {
+    ) -> (ConstraintCategory, Span, RegionVid) {
         debug!("best_blame_constraint(from_region={:?})", from_region);
 
         // Find all paths
-        let path = self
+        let (path, target_region) = self
             .find_constraint_paths_between_regions(from_region, target_test)
             .unwrap();
         debug!("best_blame_constraint: path={:#?}", path);
@@ -98,7 +97,9 @@ fn best_blame_constraint(
         categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
         debug!("best_blame_constraint: sorted_path={:?}", categorized_path);
 
-        *categorized_path.first().unwrap()
+        let &(category, span) = categorized_path.first().unwrap();
+
+        (category, span, target_region)
     }
 
     /// Walks the graph of constraints (where `'a: 'b` is considered
@@ -106,11 +107,14 @@ fn best_blame_constraint(
     /// `to_region`. The paths are accumulated into the vector
     /// `results`. The paths are stored as a series of
     /// `ConstraintIndex` values -- in other words, a list of *edges*.
+    ///
+    /// Returns: a series of constraints as well as the region `R`
+    /// that passed the target test.
     fn find_constraint_paths_between_regions(
         &self,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> Option<Vec<ConstraintIndex>> {
+    ) -> Option<(Vec<ConstraintIndex>, RegionVid)> {
         let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
         context[from_region] = Trace::StartRegion;
 
@@ -138,7 +142,7 @@ fn find_constraint_paths_between_regions(
 
                         Trace::StartRegion => {
                             result.reverse();
-                            return Some(result);
+                            return Some((result, r));
                         }
                     }
                 }
@@ -253,7 +257,7 @@ pub(super) fn report_error(
     ) {
         debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (category, span) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr);
+        let (category, span, _) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr);
 
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
@@ -393,82 +397,21 @@ fn report_general_error(
         diag.buffer(errors_buffer);
     }
 
-    // Find some constraint `X: Y` where:
-    // - `fr1: X` transitively
-    // - and `Y` is live at `elem`
-    crate fn find_constraint(&self, fr1: RegionVid, elem: Location) -> RegionVid {
-        let index = self.blame_constraint(fr1, elem);
-        self.constraints[index].sub
-    }
-
-    /// Tries to finds a good span to blame for the fact that `fr1`
-    /// contains `fr2`.
-    pub(super) fn blame_constraint(
-        &self,
-        fr1: RegionVid,
-        elem: impl ToElementIndex,
-    ) -> ConstraintIndex {
-        // Find everything that influenced final value of `fr`.
-        let influenced_fr1 = self.dependencies(fr1);
-
-        // Try to find some outlives constraint `'X: fr2` where `'X`
-        // influenced `fr1`. Blame that.
-        //
-        // NB, this is a pretty bad choice most of the time. In
-        // particular, the connection between `'X` and `fr1` may not
-        // be obvious to the user -- not to mention the naive notion
-        // of dependencies, which doesn't account for the locations of
-        // contraints at all. But it will do for now.
-        let relevant_constraint = self.constraints
-            .iter_enumerated()
-            .filter_map(|(i, constraint)| {
-                if !self.liveness_constraints.contains(constraint.sub, elem) {
-                    None
-                } else {
-                    influenced_fr1[constraint.sup]
-                        .map(|distance| (distance, i))
-                }
+    // Finds some region R such that `fr1: R` and `R` is live at
+    // `elem`.
+    crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
+        // Find all paths
+        let (_path, r) = self
+            .find_constraint_paths_between_regions(fr1, |r| {
+                self.liveness_constraints.contains(r, elem)
             })
-            .min() // constraining fr1 with fewer hops *ought* to be more obvious
-            .map(|(_dist, i)| i);
-
-        relevant_constraint.unwrap_or_else(|| {
-            bug!(
-                "could not find any constraint to blame for {:?}: {:?}",
-                fr1,
-                elem,
-            );
-        })
+            .unwrap();
+        r
     }
 
-    /// Finds all regions whose values `'a` may depend on in some way.
-    /// For each region, returns either `None` (does not influence
-    /// `'a`) or `Some(d)` which indicates that it influences `'a`
-    /// with distinct `d` (minimum number of edges that must be
-    /// traversed).
-    ///
-    /// Used during error reporting, extremely naive and inefficient.
-    fn dependencies(&self, r0: RegionVid) -> IndexVec<RegionVid, Option<usize>> {
-        let mut result_set = IndexVec::from_elem(None, &self.definitions);
-        let mut changed = true;
-        result_set[r0] = Some(0); // distance 0 from `r0`
-
-        while changed {
-            changed = false;
-            for constraint in self.constraints.iter() {
-                if let Some(n) = result_set[constraint.sup] {
-                    let m = n + 1;
-                    if result_set[constraint.sub]
-                        .map(|distance| m < distance)
-                        .unwrap_or(true)
-                    {
-                        result_set[constraint.sub] = Some(m);
-                        changed = true;
-                    }
-                }
-            }
-        }
-
-        result_set
+    // Finds a good span to blame for the fact that `fr1` outlives `fr2`.
+    crate fn find_outlives_blame_span(&self, mir: &Mir<'tcx>, fr1: RegionVid, fr2: RegionVid) -> Span {
+        let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
+        span
     }
 }
index ea1e8b346bd42b8dd88e9c1a645dee992c0495d2..cf64f22084534367a0d64a1983560a97ef95a854 100644 (file)
@@ -884,8 +884,7 @@ fn check_universal_region<'gcx>(
                 longer_fr, shorter_fr,
             );
 
-            let blame_index = self.blame_constraint(longer_fr, shorter_fr);
-            let blame_span = self.constraints[blame_index].locations.span(mir);
+            let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr);
 
             if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
                 // Shrink `fr` until we find a non-local region (if we do).
index 2284f0784c545d4bbe5223f5837907619a374364..92225369c92711806bdc6a8bd65f132df1dcef5e 100644 (file)
@@ -2,28 +2,37 @@ error[E0499]: cannot borrow `*arg` as mutable more than once at a time
   --> $DIR/mut-borrow-in-loop.rs:20:25
    |
 LL |             (self.func)(arg) //~ ERROR cannot borrow
-   |             ------------^^^-
-   |             |           |
-   |             |           mutable borrow starts here in previous iteration of loop
-   |             borrow later used here
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
+  --> $DIR/mut-borrow-in-loop.rs:17:6
+   |
+LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
+   |      ^^
 
 error[E0499]: cannot borrow `*arg` as mutable more than once at a time
   --> $DIR/mut-borrow-in-loop.rs:26:25
    |
 LL |             (self.func)(arg) //~ ERROR cannot borrow
-   |             ------------^^^-
-   |             |           |
-   |             |           mutable borrow starts here in previous iteration of loop
-   |             borrow later used here
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
+  --> $DIR/mut-borrow-in-loop.rs:17:6
+   |
+LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
+   |      ^^
 
 error[E0499]: cannot borrow `*arg` as mutable more than once at a time
   --> $DIR/mut-borrow-in-loop.rs:33:25
    |
 LL |             (self.func)(arg) //~ ERROR cannot borrow
-   |             ------------^^^-
-   |             |           |
-   |             |           mutable borrow starts here in previous iteration of loop
-   |             borrow later used here
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
+  --> $DIR/mut-borrow-in-loop.rs:17:6
+   |
+LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
+   |      ^^
 
 error: aborting due to 3 previous errors