diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-06-04 12:25:12 -0400 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2018-07-01 15:30:42 +0100 |
| commit | 0b620186fdac2a8a671d445ac25ef33d1df44153 (patch) | |
| tree | 0a15c7ae7984c7e8853e3dce5322912992a5e5e7 /src | |
| parent | 609bb27514fe71f08040aef1eb8a7acd098e9185 (diff) | |
| download | rust-0b620186fdac2a8a671d445ac25ef33d1df44153.tar.gz rust-0b620186fdac2a8a671d445ac25ef33d1df44153.zip | |
propagate boring vs interesting causal info for constraints/tests
Diffstat (limited to 'src')
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) } } |
