From 611a06a37526470617f08cdefc56ac4525286eb1 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 19 Apr 2022 20:53:35 -0400 Subject: [PATCH] Add an explicit `Span` field to `OutlivesConstraint` Previously, we would retrieve the span from the `Body` using the `locations` field. However, we may end up changing the `locations` field when moving a constraint from a promoted to a different body. We now store the original `Span` in a dedication field, so that changes to the `locations` do not affect the quality of our diagnostics. --- .../rustc_borrowck/src/constraints/graph.rs | 1 + .../rustc_borrowck/src/constraints/mod.rs | 7 +++ .../src/region_infer/dump_mir.rs | 8 ++- .../rustc_borrowck/src/region_infer/mod.rs | 7 +-- .../src/type_check/constraint_conversion.rs | 6 ++- .../src/type_check/free_region_relations.rs | 1 + .../src/type_check/input_output.rs | 1 + compiler/rustc_borrowck/src/type_check/mod.rs | 2 + .../src/type_check/relate_tys.rs | 1 + .../nll/named_lifetimes_basic.use_x.nll.0.mir | 16 +++--- ...egion_subtyping_basic.main.nll.0.32bit.mir | 4 +- ...egion_subtyping_basic.main.nll.0.64bit.mir | 4 +- .../mir-opt/storage_ranges.main.nll.0.mir | 2 +- src/test/ui/rfc1623.base.stderr | 2 +- src/test/ui/rfc1623.nll.stderr | 52 +++++-------------- src/test/ui/rfc1623.rs | 8 +-- 16 files changed, 58 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs index cb9e0234c49ff..4ceca60e23cee 100644 --- a/compiler/rustc_borrowck/src/constraints/graph.rs +++ b/compiler/rustc_borrowck/src/constraints/graph.rs @@ -156,6 +156,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> { sup: self.static_region, sub: next_static_idx.into(), locations: Locations::All(DUMMY_SP), + span: DUMMY_SP, category: ConstraintCategory::Internal, variance_info: VarianceDiagInfo::default(), }) diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index d41143ee763ad..14f0e5f620aee 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -2,6 +2,7 @@ use rustc_data_structures::graph::scc::Sccs; use rustc_index::vec::IndexVec; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; +use rustc_span::Span; use std::fmt; use std::ops::Index; @@ -87,6 +88,12 @@ pub struct OutlivesConstraint<'tcx> { /// Where did this constraint arise? pub locations: Locations, + /// The `Span` associated with the creation of this constraint. + /// This should be used in preference to obtaining the span from + /// `locations`, since the `locations` may give a poor span + /// in some cases (e.g. converting a constraint from a promoted). + pub span: Span, + /// What caused this constraint? pub category: ConstraintCategory, diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index 97233b930c395..fe5193102f958 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -74,14 +74,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); constraints.sort_by_key(|c| (c.sup, c.sub)); for constraint in &constraints { - let OutlivesConstraint { sup, sub, locations, category, variance_info: _ } = constraint; + let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } = + constraint; let (name, arg) = match locations { Locations::All(span) => { ("All", tcx.sess.source_map().span_to_embeddable_string(*span)) } Locations::Single(loc) => ("Single", format!("{:?}", loc)), }; - with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?; + with_msg(&format!( + "{:?}: {:?} due to {:?} at {}({}) ({:?}", + sup, sub, category, name, arg, span + ))?; } Ok(()) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index dabf61715ce58..cf03f34a4ec5f 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1733,7 +1733,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { crate fn retrieve_closure_constraint_info( &self, - body: &Body<'tcx>, + _body: &Body<'tcx>, constraint: &OutlivesConstraint<'tcx>, ) -> BlameConstraint<'tcx> { let loc = match constraint.locations { @@ -1760,7 +1760,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { .unwrap_or(BlameConstraint { category: constraint.category, from_closure: false, - cause: ObligationCause::dummy_with_span(body.source_info(loc).span), + cause: ObligationCause::dummy_with_span(constraint.span), variance_info: constraint.variance_info, }) } @@ -1869,6 +1869,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { sup: r, sub: constraint.min_choice, locations: Locations::All(p_c.definition_span), + span: p_c.definition_span, category: ConstraintCategory::OpaqueType, variance_info: ty::VarianceDiagInfo::default(), }; @@ -2017,7 +2018,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { category: constraint.category, from_closure: false, cause: ObligationCause::new( - constraint.locations.span(body), + constraint.span, CRATE_HIR_ID, cause_code.clone(), ), diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 5022cb98b821d..21190a850b7b1 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::DUMMY_SP; +use rustc_span::{Span, DUMMY_SP}; use crate::{ constraints::OutlivesConstraint, @@ -26,6 +26,7 @@ crate struct ConstraintConversion<'a, 'tcx> { implicit_region_bound: Option>, param_env: ty::ParamEnv<'tcx>, locations: Locations, + span: Span, category: ConstraintCategory, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } @@ -38,6 +39,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { implicit_region_bound: Option>, param_env: ty::ParamEnv<'tcx>, locations: Locations, + span: Span, category: ConstraintCategory, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, ) -> Self { @@ -49,6 +51,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { implicit_region_bound, param_env, locations, + span, category, constraints, } @@ -153,6 +156,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { self.constraints.outlives_constraints.push(OutlivesConstraint { locations: self.locations, category: self.category, + span: self.span, sub, sup, variance_info: ty::VarianceDiagInfo::default(), diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index f8439d2e16355..f08f2e1b12da6 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -316,6 +316,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.implicit_region_bound, self.param_env, Locations::All(DUMMY_SP), + DUMMY_SP, ConstraintCategory::Internal, &mut self.constraints, ) diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 83c8ecba1f17a..e6f996491a41b 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -235,6 +235,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(self.implicit_region_bound), self.param_env, Locations::All(DUMMY_SP), + DUMMY_SP, ConstraintCategory::Internal, &mut self.borrowck_context.constraints, ) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index ece801716b2db..6dcdd46816e0d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1141,6 +1141,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(self.implicit_region_bound), self.param_env, locations, + locations.span(self.body), category, &mut self.borrowck_context.constraints, ) @@ -2401,6 +2402,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { sup: ref_region.to_region_vid(), sub: borrow_region.to_region_vid(), locations: location.to_locations(), + span: location.to_locations().span(body), category, variance_info: ty::VarianceDiagInfo::default(), }); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index f0106630797d3..f98d2c3128c52 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -116,6 +116,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> sup, sub, locations: self.locations, + span: self.locations.span(self.type_checker.body), category: self.category, variance_info: info, }, diff --git a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir index 9f235248ca59f..8423128123ab7 100644 --- a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir +++ b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir @@ -25,14 +25,14 @@ | '_#2r live at {bb0[0..=1]} | '_#3r live at {bb0[0..=1]} | '_#4r live at {bb0[0..=1]} -| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) -| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) -| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) -| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) -| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) -| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) -| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) -| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) +| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0) +| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0) +| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0) +| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0) +| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0) +| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0) +| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0) +| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0) | fn use_x(_1: &'_#6r mut i32, _2: &'_#7r u32, _3: &'_#8r u32, _4: &'_#9r u32) -> bool { debug w => _1; // in scope 0 at $DIR/named-lifetimes-basic.rs:12:26: 12:27 diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index ed94a1ecf0062..f79e2705ad29c 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -18,8 +18,8 @@ | '_#3r live at {bb1[0]} | '_#4r live at {bb1[1..=3]} | '_#5r live at {bb1[4..=7], bb2[0..=2]} -| '_#3r: '_#4r due to Assignment at Single(bb1[0]) -| '_#4r: '_#5r due to Assignment at Single(bb1[3]) +| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0) +| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0) | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11 diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 95997b2070172..162cacef8a54a 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -18,8 +18,8 @@ | '_#3r live at {bb1[0]} | '_#4r live at {bb1[1..=3]} | '_#5r live at {bb1[4..=7], bb2[0..=2]} -| '_#3r: '_#4r due to Assignment at Single(bb1[0]) -| '_#4r: '_#5r due to Assignment at Single(bb1[3]) +| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0) +| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0) | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11 diff --git a/src/test/mir-opt/storage_ranges.main.nll.0.mir b/src/test/mir-opt/storage_ranges.main.nll.0.mir index e02580135af38..b383c5ec9dc60 100644 --- a/src/test/mir-opt/storage_ranges.main.nll.0.mir +++ b/src/test/mir-opt/storage_ranges.main.nll.0.mir @@ -16,7 +16,7 @@ | '_#1r live at {bb0[0..=22]} | '_#3r live at {bb0[10]} | '_#4r live at {bb0[11]} -| '_#3r: '_#4r due to Assignment at Single(bb0[10]) +| '_#3r: '_#4r due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:6:17: 6:25 (#0) | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/storage_ranges.rs:3:11: 3:11 diff --git a/src/test/ui/rfc1623.base.stderr b/src/test/ui/rfc1623.base.stderr index 6d389a1317a9f..364c8c8f7069e 100644 --- a/src/test/ui/rfc1623.base.stderr +++ b/src/test/ui/rfc1623.base.stderr @@ -1,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:36:8 + --> $DIR/rfc1623.rs:32:8 | LL | f: &id, | ^^^ implementation of `FnOnce` is not general enough diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr index f85b6ff8ff75b..2eff4708547d8 100644 --- a/src/test/ui/rfc1623.nll.stderr +++ b/src/test/ui/rfc1623.nll.stderr @@ -1,63 +1,35 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:29:35 + --> $DIR/rfc1623.rs:32:8 | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { - | ___________________________________^ -LL | | -LL | | -LL | | -... | -LL | | -LL | | }; - | |_^ one type is more general than the other +LL | f: &id, + | ^^^ one type is more general than the other | = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>` found type `Fn<(&Foo<'_>,)>` error[E0308]: mismatched types - --> $DIR/rfc1623.rs:29:35 + --> $DIR/rfc1623.rs:32:8 | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { - | ___________________________________^ -LL | | -LL | | -LL | | -... | -LL | | -LL | | }; - | |_^ one type is more general than the other +LL | f: &id, + | ^^^ one type is more general than the other | = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>` found type `Fn<(&Foo<'_>,)>` error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:29:35 + --> $DIR/rfc1623.rs:32:8 | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { - | ___________________________________^ -LL | | -LL | | -LL | | -... | -LL | | -LL | | }; - | |_^ implementation of `FnOnce` is not general enough +LL | f: &id, + | ^^^ implementation of `FnOnce` is not general enough | = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:29:35 + --> $DIR/rfc1623.rs:32:8 | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { - | ___________________________________^ -LL | | -LL | | -LL | | -... | -LL | | -LL | | }; - | |_^ implementation of `FnOnce` is not general enough +LL | f: &id, + | ^^^ implementation of `FnOnce` is not general enough | = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2` diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 0e9d214032425..443da0aa955f9 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -27,14 +27,14 @@ fn id(t: T) -> T { } static SOME_STRUCT: &SomeStruct = &SomeStruct { - //[nll]~^ ERROR mismatched types - //[nll]~| ERROR mismatched types - //[nll]~| ERROR implementation of `FnOnce` is not general enough - //[nll]~| ERROR implementation of `FnOnce` is not general enough foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, //[base]~^ ERROR implementation of `FnOnce` is not general enough + //[nll]~^^ ERROR mismatched types + //[nll]~| ERROR mismatched types + //[nll]~| ERROR implementation of `FnOnce` is not general enough + //[nll]~| ERROR implementation of `FnOnce` is not general enough }; // very simple test for a 'static static with default lifetime