diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 76e779bfec6..366ade1a713 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -9,7 +9,7 @@ use rustc_span::Span; use rustc_trait_selection::traits::query::type_op; use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _}; -use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span}; +use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}; use std::fmt; use std::rc::Rc; @@ -45,13 +45,12 @@ impl UniverseInfo<'tcx> { mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, - span: Span, + cause: ObligationCause<'tcx>, ) { match self.0 { UniverseInfoInner::RelateTys { expected, found } => { - let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id()); let err = mbcx.infcx.report_mismatched_types( - &ObligationCause::misc(span, body_id), + &cause, expected, found, TypeError::RegionsPlaceholderMismatch, @@ -59,7 +58,7 @@ impl UniverseInfo<'tcx> { err.buffer(&mut mbcx.errors_buffer); } UniverseInfoInner::TypeOp(ref type_op_info) => { - type_op_info.report_error(mbcx, placeholder, error_element, span); + type_op_info.report_error(mbcx, placeholder, error_element, cause); } UniverseInfoInner::Other => { // FIXME: This error message isn't great, but it doesn't show @@ -68,7 +67,7 @@ impl UniverseInfo<'tcx> { mbcx.infcx .tcx .sess - .struct_span_err(span, "higher-ranked subtype error") + .struct_span_err(cause.span, "higher-ranked subtype error") .buffer(&mut mbcx.errors_buffer); } } @@ -130,7 +129,7 @@ trait TypeOpInfo<'tcx> { fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option>; @@ -140,7 +139,7 @@ fn report_error( mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, - span: Span, + cause: ObligationCause<'tcx>, ) { let tcx = mbcx.infcx.tcx; let base_universe = self.base_universe(); @@ -150,7 +149,7 @@ fn report_error( { adjusted } else { - self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer); + self.fallback_error(tcx, cause.span).buffer(&mut mbcx.errors_buffer); return; }; @@ -175,7 +174,8 @@ fn report_error( debug!(?placeholder_region); - let nice_error = self.nice_error(tcx, span, placeholder_region, error_region); + let span = cause.span; + let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region); if let Some(nice_error) = nice_error { nice_error.buffer(&mut mbcx.errors_buffer); @@ -205,15 +205,24 @@ fn base_universe(&self) -> ty::UniverseIndex { fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); - type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span)); - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) - }) + tcx.infer_ctxt().enter_with_canonical( + cause.span, + &self.canonical_query, + |ref infcx, key, _| { + let mut fulfill_cx = >::new(tcx); + type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause); + try_extract_error_from_fulfill_cx( + fulfill_cx, + infcx, + placeholder_region, + error_region, + ) + }, + ) } } @@ -239,32 +248,41 @@ fn base_universe(&self) -> ty::UniverseIndex { fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); + tcx.infer_ctxt().enter_with_canonical( + cause.span, + &self.canonical_query, + |ref infcx, key, _| { + let mut fulfill_cx = >::new(tcx); - let mut selcx = SelectionContext::new(infcx); + let mut selcx = SelectionContext::new(infcx); - // FIXME(lqd): Unify and de-duplicate the following with the actual - // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the - // `ObligationCause`. The normalization results are currently different between - // `AtExt::normalize` used in the query and `normalize` called below: the former fails - // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check - // after #85499 lands to see if its fixes have erased this difference. - let (param_env, value) = key.into_parts(); - let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize( - &mut selcx, - param_env, - ObligationCause::dummy_with_span(span), - value.value, - ); - fulfill_cx.register_predicate_obligations(infcx, obligations); + // FIXME(lqd): Unify and de-duplicate the following with the actual + // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the + // `ObligationCause`. The normalization results are currently different between + // `AtExt::normalize` used in the query and `normalize` called below: the former fails + // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check + // after #85499 lands to see if its fixes have erased this difference. + let (param_env, value) = key.into_parts(); + let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize( + &mut selcx, + param_env, + cause, + value.value, + ); + fulfill_cx.register_predicate_obligations(infcx, obligations); - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) - }) + try_extract_error_from_fulfill_cx( + fulfill_cx, + infcx, + placeholder_region, + error_region, + ) + }, + ) } } @@ -287,15 +305,25 @@ fn base_universe(&self) -> ty::UniverseIndex { fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); - type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(span)).ok()?; - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) - }) + tcx.infer_ctxt().enter_with_canonical( + cause.span, + &self.canonical_query, + |ref infcx, key, _| { + let mut fulfill_cx = >::new(tcx); + type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)) + .ok()?; + try_extract_error_from_fulfill_cx( + fulfill_cx, + infcx, + placeholder_region, + error_region, + ) + }, + ) } } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 2d12a682e7a..d5de0801ac4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -300,7 +300,7 @@ fn free_region_constraint_info( borrow_region: RegionVid, outlived_region: RegionVid, ) -> (ConstraintCategory, bool, Span, Option) { - let BlameConstraint { category, from_closure, span, variance_info: _ } = + let BlameConstraint { category, from_closure, cause, variance_info: _ } = self.regioncx.best_blame_constraint( &self.body, borrow_region, @@ -310,7 +310,7 @@ fn free_region_constraint_info( let outlived_fr_name = self.give_region_a_name(outlived_region); - (category, from_closure, span, outlived_fr_name) + (category, from_closure, cause.span, outlived_fr_name) } /// Returns structured explanation for *why* the borrow contains the diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 0761d63c665..b127330efa2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -13,6 +13,7 @@ use crate::borrowck_errors; +use super::{OutlivesSuggestionBuilder, RegionName}; use crate::region_infer::BlameConstraint; use crate::{ nll::ConstraintDescription, @@ -21,8 +22,6 @@ MirBorrowckCtxt, }; -use super::{OutlivesSuggestionBuilder, RegionName}; - impl ConstraintDescription for ConstraintCategory { fn description(&self) -> &'static str { // Must end with a space. Allows for empty names to be provided. @@ -41,7 +40,8 @@ fn description(&self) -> &'static str { ConstraintCategory::OpaqueType => "opaque type ", ConstraintCategory::ClosureUpvar(_) => "closure capture ", ConstraintCategory::Usage => "this usage ", - ConstraintCategory::Boring + ConstraintCategory::Predicate(_, _) + | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => "", } @@ -217,7 +217,7 @@ pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { let error_vid = self.regioncx.region_from_element(longer_fr, &error_element); // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let (_, span) = self.regioncx.find_outlives_blame_span( + let (_, cause) = self.regioncx.find_outlives_blame_span( &self.body, longer_fr, NllRegionVariableOrigin::Placeholder(placeholder), @@ -227,7 +227,7 @@ pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { let universe = placeholder.universe; let universe_info = self.regioncx.universe_info(universe); - universe_info.report_error(self, placeholder, error_element, span); + universe_info.report_error(self, placeholder, error_element, cause); } RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => { @@ -275,15 +275,15 @@ pub(crate) fn report_region_error( ) { debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let BlameConstraint { category, span, variance_info, from_closure: _ } = + let BlameConstraint { category, cause, variance_info, from_closure: _ } = self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| { self.regioncx.provides_universal_region(r, fr, outlived_fr) }); - debug!("report_region_error: category={:?} {:?} {:?}", category, span, variance_info); + debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info); // 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)) { - let nice = NiceRegionError::new_from_span(self.infcx, span, o, f); + let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f); if let Some(diag) = nice.try_report_from_nll() { diag.buffer(&mut self.errors_buffer); return; @@ -306,7 +306,7 @@ pub(crate) fn report_region_error( fr_is_local, outlived_fr_is_local, category, - span, + span: cause.span, }; let mut diag = match (category, fr_is_local, outlived_fr_is_local) { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 128faab8d72..cb1b0e0c934 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -6,6 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; use rustc_hir::def_id::DefId; +use rustc_hir::CRATE_HIR_ID; use rustc_index::vec::IndexVec; use rustc_infer::infer::canonical::QueryOutlivesConstraint; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound}; @@ -14,6 +15,8 @@ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint, }; +use rustc_middle::traits::ObligationCause; +use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; @@ -1596,7 +1599,7 @@ fn try_propagate_universal_region_error( propagated_outlives_requirements.push(ClosureOutlivesRequirement { subject: ClosureOutlivesSubject::Region(fr_minus), outlived_free_region: fr, - blame_span: blame_span_category.1, + blame_span: blame_span_category.1.span, category: blame_span_category.0, }); } @@ -1738,7 +1741,7 @@ fn check_member_constraints( return BlameConstraint { category: constraint.category, from_closure: false, - span, + cause: ObligationCause::dummy_with_span(span), variance_info: constraint.variance_info, }; } @@ -1751,30 +1754,30 @@ fn check_member_constraints( .map(|&(category, span)| BlameConstraint { category, from_closure: true, - span: span, + cause: ObligationCause::dummy_with_span(span), variance_info: constraint.variance_info, }) .unwrap_or(BlameConstraint { category: constraint.category, from_closure: false, - span: body.source_info(loc).span, + cause: ObligationCause::dummy_with_span(body.source_info(loc).span), variance_info: constraint.variance_info, }) } - /// Finds a good span to blame for the fact that `fr1` outlives `fr2`. + /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`. crate fn find_outlives_blame_span( &self, body: &Body<'tcx>, fr1: RegionVid, fr1_origin: NllRegionVariableOrigin, fr2: RegionVid, - ) -> (ConstraintCategory, Span) { - let BlameConstraint { category, span, .. } = + ) -> (ConstraintCategory, ObligationCause<'tcx>) { + let BlameConstraint { category, cause, .. } = self.best_blame_constraint(body, fr1, fr1_origin, |r| { self.provides_universal_region(r, fr1, fr2) }); - (category, span) + (category, cause) } /// Walks the graph of constraints (where `'a: 'b` is considered @@ -1990,6 +1993,21 @@ fn check_member_constraints( .collect::>() ); + // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint. + // Instead, we use it to produce an improved `ObligationCauseCode`. + // FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate` + // constraints. Currently, we just pick the first one. + let cause_code = path + .iter() + .find_map(|constraint| { + if let ConstraintCategory::Predicate(def_id, predicate_span) = constraint.category { + Some(ObligationCauseCode::BindingObligation(def_id, predicate_span)) + } else { + None + } + }) + .unwrap_or_else(|| ObligationCauseCode::MiscObligation); + // Classify each of the constraints along the path. let mut categorized_path: Vec> = path .iter() @@ -2000,7 +2018,11 @@ fn check_member_constraints( BlameConstraint { category: constraint.category, from_closure: false, - span: constraint.locations.span(body), + cause: ObligationCause::new( + constraint.locations.span(body), + CRATE_HIR_ID, + cause_code.clone(), + ), variance_info: constraint.variance_info, } } @@ -2083,7 +2105,8 @@ fn check_member_constraints( ConstraintCategory::OpaqueType | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal => false, + | ConstraintCategory::Internal + | ConstraintCategory::Predicate(_, _) => false, ConstraintCategory::TypeAnnotation | ConstraintCategory::Return(_) | ConstraintCategory::Yield => true, @@ -2094,7 +2117,8 @@ fn check_member_constraints( ConstraintCategory::OpaqueType | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal => false, + | ConstraintCategory::Internal + | ConstraintCategory::Predicate(_, _) => false, _ => true, } } @@ -2249,6 +2273,6 @@ fn apply_requirements( pub struct BlameConstraint<'tcx> { pub category: ConstraintCategory, pub from_closure: bool, - pub span: Span, + pub cause: ObligationCause<'tcx>, pub variance_info: ty::VarianceDiagInfo<'tcx>, } diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index e7761988222..7ff74e4b96e 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -4,6 +4,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, ToPredicate, TypeFoldable}; +use rustc_span::def_id::DefId; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; use rustc_trait_selection::traits::query::Fallible; @@ -100,12 +101,17 @@ pub(super) fn prove_trait_ref( pub(super) fn normalize_and_prove_instantiated_predicates( &mut self, + def_id: DefId, instantiated_predicates: ty::InstantiatedPredicates<'tcx>, locations: Locations, ) { - for predicate in instantiated_predicates.predicates { + for (predicate, span) in instantiated_predicates + .predicates + .into_iter() + .zip(instantiated_predicates.spans.into_iter()) + { let predicate = self.normalize(predicate, locations); - self.prove_predicate(predicate, locations, ConstraintCategory::Boring); + self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(def_id, span)); } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index cf50fa38687..4bbeed39e45 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -32,6 +32,7 @@ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, }; +use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_trait_selection::infer::InferCtxtExt as _; @@ -449,6 +450,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() { let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); self.cx.normalize_and_prove_instantiated_predicates( + def_id, instantiated_predicates, location.to_locations(), ); @@ -2572,9 +2574,9 @@ fn prove_aggregate_predicates( aggregate_kind, location ); - let instantiated_predicates = match aggregate_kind { + let (def_id, instantiated_predicates) = match aggregate_kind { AggregateKind::Adt(def, _, substs, _, _) => { - tcx.predicates_of(def.did).instantiate(tcx, substs) + (def.did, tcx.predicates_of(def.did).instantiate(tcx, substs)) } // For closures, we have some **extra requirements** we @@ -2599,13 +2601,16 @@ fn prove_aggregate_predicates( // clauses on the struct. AggregateKind::Closure(def_id, substs) | AggregateKind::Generator(def_id, substs, _) => { - self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location) + (*def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location)) } - AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(), + AggregateKind::Array(_) | AggregateKind::Tuple => { + (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty()) + } }; self.normalize_and_prove_instantiated_predicates( + def_id, instantiated_predicates, location.to_locations(), ); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d9b7022f03a..45dd8868d6c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -609,6 +609,7 @@ fn note_error_origin( err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>, exp_found: Option>>, + terr: &TypeError<'tcx>, ) { match cause.code { ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { @@ -785,7 +786,15 @@ fn note_error_origin( err.help("try adding a diverging expression, such as `return` or `panic!(..)`"); err.help("...or use `match` instead of `let...else`"); } - _ => (), + _ => { + if let ObligationCauseCode::BindingObligation(_, binding_span) = + cause.code.peel_derives() + { + if matches!(terr, TypeError::RegionsPlaceholderMismatch) { + err.span_note(*binding_span, "the lifetime requirement is introduced here"); + } + } + } } } @@ -1724,7 +1733,7 @@ enum Mismatch<'a> { // It reads better to have the error origin as the final // thing. - self.note_error_origin(diag, cause, exp_found); + self.note_error_origin(diag, cause, exp_found, terr); } pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index b003a504691..8d206d3eb1d 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -338,6 +338,11 @@ pub enum ConstraintCategory { OpaqueType, ClosureUpvar(hir::HirId), + /// A constraint from a user-written predicate + /// with the provided span, written on the item + /// with the given `DefId` + Predicate(DefId, Span), + /// 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. diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 48c46c30693..8612499623b 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -19,7 +19,7 @@ mod normalize_projection_ty; mod type_op; -pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span}; +pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}; use rustc_middle::ty::query::Providers; diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index f954cab240c..cc0b7d5817b 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -257,7 +257,7 @@ fn type_op_prove_predicate<'tcx>( canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { - type_op_prove_predicate_with_span(infcx, fulfill_cx, key, None); + type_op_prove_predicate_with_cause(infcx, fulfill_cx, key, ObligationCause::dummy()); Ok(()) }) } @@ -265,17 +265,12 @@ fn type_op_prove_predicate<'tcx>( /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors, /// this query can be re-run to better track the span of the obligation cause, and improve the error /// message. Do not call directly unless you're in that very specific context. -pub fn type_op_prove_predicate_with_span<'a, 'tcx: 'a>( +pub fn type_op_prove_predicate_with_cause<'a, 'tcx: 'a>( infcx: &'a InferCtxt<'a, 'tcx>, fulfill_cx: &'a mut dyn TraitEngine<'tcx>, key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>, - span: Option, + cause: ObligationCause<'tcx>, ) { - let cause = if let Some(span) = span { - ObligationCause::dummy_with_span(span) - } else { - ObligationCause::dummy() - }; let (param_env, ProvePredicate { predicate }) = key.into_parts(); fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate)); } diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr index e3bd0c2276e..de254b7a163 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -6,6 +6,11 @@ LL | foo(()); | = note: expected reference `&'a ()` found reference `&()` +note: the lifetime requirement is introduced here + --> $DIR/higher-ranked-projection.rs:15:33 + | +LL | where for<'a> &'a T: Mirror + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/generator/resume-arg-late-bound.nll.stderr b/src/test/ui/generator/resume-arg-late-bound.nll.stderr index 25bc6afc550..b5144c607a8 100644 --- a/src/test/ui/generator/resume-arg-late-bound.nll.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.nll.stderr @@ -6,6 +6,11 @@ LL | test(gen); | = note: expected type `for<'a> Generator<&'a mut bool>` found type `Generator<&mut bool>` +note: the lifetime requirement is introduced here + --> $DIR/resume-arg-late-bound.rs:8:17 + | +LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/issue-79187-2.nll.stderr b/src/test/ui/lifetimes/issue-79187-2.nll.stderr index 907b43d6762..04d9b64d64f 100644 --- a/src/test/ui/lifetimes/issue-79187-2.nll.stderr +++ b/src/test/ui/lifetimes/issue-79187-2.nll.stderr @@ -38,6 +38,11 @@ note: this closure does not fulfill the lifetime requirements | LL | take_foo(|a| a); | ^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:9:5 @@ -47,6 +52,11 @@ LL | take_foo(|a: &i32| a); | = note: expected reference `&i32` found reference `&i32` +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:10:5 @@ -56,6 +66,11 @@ LL | take_foo(|a: &i32| -> &i32 { a }); | = note: expected reference `&i32` found reference `&i32` +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/lifetimes/issue-79187.nll.stderr b/src/test/ui/lifetimes/issue-79187.nll.stderr index 725b132e83a..3a993e88d8a 100644 --- a/src/test/ui/lifetimes/issue-79187.nll.stderr +++ b/src/test/ui/lifetimes/issue-79187.nll.stderr @@ -11,6 +11,11 @@ note: this closure does not fulfill the lifetime requirements | LL | let f = |_| (); | ^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ^^^^^^^^^^^^ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr index 5a1294f948f..5509226cb1c 100644 --- a/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr @@ -14,6 +14,11 @@ LL | f(data, identity) | = note: expected type `for<'r> Fn<(&'r T,)>` found type `Fn<(&T,)>` +note: the lifetime requirement is introduced here + --> $DIR/issue_74400.rs:8:34 + | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | ^^^^^^^^^^^ error: implementation of `FnOnce` is not general enough --> $DIR/issue_74400.rs:12:5 diff --git a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr index f29126e6afc..bd36fab9288 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr @@ -20,6 +20,11 @@ note: this closure does not fulfill the lifetime requirements | LL | baz(|_| ()); | ^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-mismatch.rs:5:11 + | +LL | fn baz(_: T) {} + | ^^^ error: aborting due to 2 previous errors