about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-04 12:25:12 -0400
committerDavid Wood <david@davidtw.co>2018-07-01 15:30:42 +0100
commit0b620186fdac2a8a671d445ac25ef33d1df44153 (patch)
tree0a15c7ae7984c7e8853e3dce5322912992a5e5e7 /src
parent609bb27514fe71f08040aef1eb8a7acd098e9185 (diff)
downloadrust-0b620186fdac2a8a671d445ac25ef33d1df44153.tar.gz
rust-0b620186fdac2a8a671d445ac25ef33d1df44153.zip
propagate boring vs interesting causal info for constraints/tests
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs6
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_set.rs10
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs33
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs26
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs61
7 files changed, 70 insertions, 72 deletions
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 6e9574e2d5b..68aa9aeabf8 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -10,9 +10,10 @@
 
 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::{Cause, RegionInferenceContext};
-use borrow_check::nll::ToRegionVid;
+use borrow_check::nll::type_check::AtLocation;
 use rustc::hir;
 use rustc::infer::InferCtxt;
 use rustc::mir::visit::TyContext;
@@ -310,9 +311,8 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
                         ty::TyRef(ref_region, _, mutbl) => {
-                            let span = self.mir.source_info(location).span;
                             self.regioncx.add_outlives(
-                                span,
+                                location.boring(),
                                 ref_region.to_region_vid(),
                                 borrow_region.to_region_vid(),
                             );
diff --git a/src/librustc_mir/borrow_check/nll/constraint_set.rs b/src/librustc_mir/borrow_check/nll/constraint_set.rs
index ac3ab961d0a..3bdf78ff3db 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_set.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_set.rs
@@ -10,9 +10,9 @@
 
 use rustc::ty::RegionVid;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use borrow_check::nll::type_check::Locations;
 
 use std::fmt;
-use syntax_pos::Span;
 use std::ops::Deref;
 
 #[derive(Clone, Default)]
@@ -23,8 +23,8 @@ crate struct ConstraintSet {
 impl ConstraintSet {
     pub fn push(&mut self, constraint: OutlivesConstraint) {
         debug!(
-            "add_outlives({:?}: {:?})",
-            constraint.sup, constraint.sub
+            "add_outlives({:?}: {:?} @ {:?})",
+            constraint.sup, constraint.sub, constraint.locations
         );
         if constraint.sup == constraint.sub {
             // 'a: 'a is pretty uninteresting
@@ -96,7 +96,7 @@ pub struct OutlivesConstraint {
     pub next: Option<ConstraintIndex>,
 
     /// Where did this constraint arise?
-    pub span: Span,
+    pub locations: Locations,
 }
 
 impl fmt::Debug for OutlivesConstraint {
@@ -104,7 +104,7 @@ impl fmt::Debug for OutlivesConstraint {
         write!(
             formatter,
             "({:?}: {:?}) due to {:?}",
-            self.sup, self.sub, self.span
+            self.sup, self.sub, self.locations
         )
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
index c68bb15552f..88d9f46e340 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
@@ -82,14 +82,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let OutlivesConstraint {
                 sup,
                 sub,
-                span,
+                locations,
                 next: _,
             } = constraint;
             with_msg(&format!(
                 "{:?}: {:?} due to {:?}",
                 sup,
                 sub,
-                span
+                locations,
             ))?;
         }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
index 15896413af9..0116fbcfc88 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
@@ -44,7 +44,7 @@ impl<'this, 'tcx> dot::Labeller<'this> for RegionInferenceContext<'tcx> {
         dot::LabelText::LabelStr(format!("{:?}", n).into_cow())
     }
     fn edge_label(&'this self, e: &OutlivesConstraint) -> dot::LabelText<'this> {
-        dot::LabelText::LabelStr(format!("{:?}", e.span).into_cow())
+        dot::LabelText::LabelStr(format!("{:?}", e.locations).into_cow())
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index fd8a62b4deb..ace701eeb78 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -11,6 +11,7 @@
 use super::universal_regions::UniversalRegions;
 use borrow_check::nll::region_infer::values::ToElementIndex;
 use borrow_check::nll::constraint_set::{ConstraintIndex, ConstraintSet, OutlivesConstraint};
+use borrow_check::nll::type_check::Locations;
 use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
@@ -154,11 +155,8 @@ pub struct TypeTest<'tcx> {
     /// The region `'x` that the type must outlive.
     pub lower_bound: RegionVid,
 
-    /// The point where the outlives relation must hold.
-    pub point: Location,
-
-    /// Where did this constraint arise?
-    pub span: Span,
+    /// Where did this constraint arise and why?
+    pub locations: Locations,
 
     /// A test which, if met by the region `'x`, proves that this type
     /// constraint is satisfied.
@@ -356,13 +354,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
     pub(super) fn add_outlives(
         &mut self,
-        span: Span,
+        locations: Locations,
         sup: RegionVid,
         sub: RegionVid,
     ) {
         assert!(self.inferred_values.is_none(), "values already inferred");
         self.constraints.push(OutlivesConstraint {
-            span,
+            locations,
             sup,
             sub,
             next: None,
@@ -408,7 +406,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut());
 
-        self.check_universal_regions(infcx, mir_def_id, outlives_requirements.as_mut());
+        self.check_universal_regions(infcx, mir, mir_def_id, outlives_requirements.as_mut());
 
         let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
 
@@ -506,7 +504,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
 
             if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements {
-                if self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) {
+                if self.try_promote_type_test(infcx, mir, type_test, propagated_outlives_requirements) {
                     continue;
                 }
             }
@@ -515,9 +513,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let lower_bound_region = self.to_error_region(type_test.lower_bound);
             if let Some(lower_bound_region) = lower_bound_region {
                 let region_scope_tree = &tcx.region_scope_tree(mir_def_id);
+                let type_test_span = type_test.locations.span(mir);
                 infcx.report_generic_bound_failure(
                     region_scope_tree,
-                    type_test.span,
+                    type_test_span,
                     None,
                     type_test.generic_kind,
                     lower_bound_region,
@@ -532,8 +531,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // to report it; we could probably handle it by
                 // iterating over the universal regions and reporting
                 // an error that multiple bounds are required.
+                let type_test_span = type_test.locations.span(mir);
                 tcx.sess.span_err(
-                    type_test.span,
+                    type_test_span,
                     &format!("`{}` does not live long enough", type_test.generic_kind,),
                 );
             }
@@ -566,6 +566,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn try_promote_type_test<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        mir: &Mir<'tcx>,
         type_test: &TypeTest<'tcx>,
         propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'gcx>>,
     ) -> bool {
@@ -574,8 +575,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let TypeTest {
             generic_kind,
             lower_bound,
-            point: _,
-            span,
+            locations,
             test: _,
         } = type_test;
 
@@ -599,7 +599,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         propagated_outlives_requirements.push(ClosureOutlivesRequirement {
             subject,
             outlived_free_region: lower_bound_plus,
-            blame_span: *span,
+            blame_span: locations.span(mir),
         });
         true
     }
@@ -865,6 +865,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn check_universal_regions<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        mir: &Mir<'tcx>,
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
     ) {
@@ -881,6 +882,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         for (fr, _) in universal_definitions {
             self.check_universal_region(
                 infcx,
+                mir,
                 mir_def_id,
                 fr,
                 &mut propagated_outlives_requirements,
@@ -899,6 +901,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn check_universal_region<'gcx>(
         &self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        mir: &Mir<'tcx>,
         mir_def_id: DefId,
         longer_fr: RegionVid,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
@@ -921,7 +924,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             );
 
             let blame_index = self.blame_constraint(longer_fr, shorter_fr);
-            let blame_span = self.constraints[blame_index].span;
+            let blame_span = self.constraints[blame_index].locations.span(mir);
 
             if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
                 // Shrink `fr` until we find a non-local region (if we do).
diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
index 2ee74dc6095..27bd5042777 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
@@ -19,14 +19,12 @@ use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
 use rustc::infer::region_constraints::{GenericKind, VerifyBound};
 use rustc::infer::{self, SubregionOrigin};
-use rustc::mir::{Location, Mir};
 use rustc::ty::subst::UnpackedKind;
 use rustc::ty::{self, TyCtxt};
-use syntax::codemap::Span;
+use syntax_pos::DUMMY_SP;
 
 crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
     universal_regions: &'a UniversalRegions<'tcx>,
     location_table: &'a LocationTable,
     region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
@@ -41,7 +39,6 @@ crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
 impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
     crate fn new(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        mir: &'a Mir<'tcx>,
         universal_regions: &'a UniversalRegions<'tcx>,
         location_table: &'a LocationTable,
         region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
@@ -54,7 +51,6 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
     ) -> Self {
         Self {
             tcx,
-            mir,
             universal_regions,
             location_table,
             region_bound_pairs,
@@ -91,8 +87,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
         // will start to fail.
         let ty::OutlivesPredicate(k1, r2) =
             query_constraint.no_late_bound_regions().unwrap_or_else(|| {
-                span_bug!(
-                    self.span(),
+                bug!(
                     "query_constraint {:?} contained bound regions",
                     query_constraint,
                 );
@@ -125,7 +120,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
             UnpackedKind::Type(t1) => {
                 // we don't actually use this for anything, but
                 // the `TypeOutlives` code needs an origin.
-                let origin = infer::RelateParamBound(self.span(), t1);
+                let origin = infer::RelateParamBound(DUMMY_SP, t1);
 
                 TypeOutlives::new(
                     &mut *self,
@@ -146,15 +141,12 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
     ) -> TypeTest<'tcx> {
         let lower_bound = self.to_region_vid(region);
 
-        let point = self.locations.from_location().unwrap_or(Location::START);
-
         let test = self.verify_bound_to_region_test(&bound);
 
         TypeTest {
             generic_kind,
             lower_bound,
-            point,
-            span: self.span(),
+            locations: self.locations,
             test,
         }
     }
@@ -189,17 +181,9 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
         self.universal_regions.to_region_vid(r)
     }
 
-    fn span(&self) -> Span {
-        self.mir
-            .source_info(self.locations.from_location().unwrap_or(Location::START))
-            .span
-    }
-
     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
-        let span = self.span();
-
         self.outlives_constraints.push(OutlivesConstraint {
-            span,
+            locations: self.locations,
             sub,
             sup,
             next: None,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 404e04ef4cc..782b07d02f4 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -147,7 +147,6 @@ fn type_check_internal<'gcx, 'tcx>(
         region_bound_pairs,
         implicit_region_bound,
         borrowck_context,
-        mir,
     );
     let errors_reported = {
         let mut verifier = TypeVerifier::new(&mut checker, mir);
@@ -597,7 +596,6 @@ struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
     constraints: MirTypeckRegionConstraints<'tcx>,
     borrowck_context: Option<BorrowCheckContext<'a, 'tcx>>,
-    mir: &'a Mir<'tcx>,
 }
 
 struct BorrowCheckContext<'a, 'tcx: 'a> {
@@ -628,7 +626,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
 /// required to hold. Normally, this is at a particular point which
 /// created the obligation, but for constraints that the user gave, we
 /// want the constraint to hold at all points.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub enum Locations {
     /// Indicates that a type constraint should always be true. This
     /// is particularly important in the new borrowck analysis for
@@ -663,21 +661,42 @@ pub enum Locations {
     /// assigned to `x` are of `'static` lifetime.
     All,
 
-    Pair {
-        /// The location in the MIR that generated these constraints.
-        /// This is intended for error reporting and diagnosis; the
-        /// constraints may *take effect* at a distinct spot.
-        from_location: Location,
-    },
+    /// A "boring" constraint (caused by the given location) is one that
+    /// the user probably doesn't want to see described in diagnostics,
+    /// because it is kind of an artifact of the type system setup.
+    ///
+    /// Example: `x = Foo { field: y }` technically creates
+    /// intermediate regions representing the "type of `Foo { field: y
+    /// }`", and data flows from `y` into those variables, but they
+    /// are not very interesting. The assignment into `x` on the other
+    /// hand might be.
+    Boring(Location),
+
+    /// An *important* outlives constraint (caused by the given
+    /// location) is one that would be useful to highlight in
+    /// diagnostics, because it represents a point where references
+    /// flow from one spot to another (e.g., `x = y`)
+    Interesting(Location),
 }
 
 impl Locations {
     pub fn from_location(&self) -> Option<Location> {
         match self {
             Locations::All => None,
-            Locations::Pair { from_location, .. } => Some(*from_location),
+            Locations::Boring(from_location) | Locations::Interesting(from_location) => {
+                Some(*from_location)
+            }
         }
     }
+
+    /// Gets a span representing the location.
+    pub fn span(&self, mir: &Mir<'_>) -> Span {
+        let span_location = match self {
+            Locations::All => Location::START,
+            Locations::Boring(l) | Locations::Interesting(l) => *l,
+        };
+        mir.source_info(span_location).span
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
@@ -688,7 +707,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
         implicit_region_bound: Option<ty::Region<'tcx>>,
         borrowck_context: Option<BorrowCheckContext<'a, 'tcx>>,
-        mir: &'a Mir<'tcx>,
     ) -> Self {
         TypeChecker {
             infcx,
@@ -698,7 +716,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             region_bound_pairs,
             implicit_region_bound,
             borrowck_context,
-            mir,
             reported_errors: FxHashSet(),
             constraints: MirTypeckRegionConstraints::default(),
         }
@@ -741,7 +758,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         if let Some(borrowck_context) = &mut self.borrowck_context {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx.tcx,
-                self.mir,
                 borrowck_context.universal_regions,
                 borrowck_context.location_table,
                 self.region_bound_pairs,
@@ -886,9 +902,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 let place_ty = location.ty(mir, tcx).to_ty(tcx);
                 let rv_ty = value.ty(mir, tcx);
 
-                let locations = Locations::Pair {
-                    from_location: term_location,
-                };
+                let locations = term_location.interesting();
                 if let Err(terr) = self.sub_types(rv_ty, place_ty, locations) {
                     span_mirbug!(
                         self,
@@ -988,7 +1002,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 match mir.yield_ty {
                     None => span_mirbug!(self, term, "yield in non-generator"),
                     Some(ty) => {
-                        if let Err(terr) = self.sub_types(value_ty, ty, term_location.interesting()) {
+                        if let Err(terr) = self.sub_types(value_ty, ty, term_location.interesting())
+                        {
                             span_mirbug!(
                                 self,
                                 term,
@@ -1016,9 +1031,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         match *destination {
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
-                let locations = Locations::Pair {
-                    from_location: term_location,
-                };
+                let locations = term_location.interesting();
                 if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations) {
                     span_mirbug!(
                         self,
@@ -1630,7 +1643,7 @@ impl MirPass for TypeckMir {
     }
 }
 
-trait AtLocation {
+pub trait AtLocation {
     /// Indicates a "boring" constraint that the user probably
     /// woudln't want to see highlights.
     fn boring(self) -> Locations;
@@ -1642,13 +1655,11 @@ trait AtLocation {
 
 impl AtLocation for Location {
     fn boring(self) -> Locations {
-        Locations::Pair {
-            from_location: self,
-        }
+        Locations::Boring(self)
     }
 
     fn interesting(self) -> Locations {
-        self.boring()
+        Locations::Interesting(self)
     }
 }