diff options
Diffstat (limited to 'compiler/rustc_trait_selection')
4 files changed, 59 insertions, 22 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 402b09419c8..969e5fa64b0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -322,7 +322,9 @@ fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> b let selcx = &mut SelectionContext::new(&infcx); let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id); let (subject2, obligations) = - impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs); + impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs, |_, _| { + ObligationCause::dummy() + }); !equate(&infcx, impl_env, subject1, subject2, obligations, impl1_def_id) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index b162e5b8995..38daca5377a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -55,7 +55,9 @@ pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::specialization_graph::FutureCompatOverlapError; pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; -pub use self::specialize::{specialization_graph, translate_substs, OverlapError}; +pub use self::specialize::{ + specialization_graph, translate_substs, translate_substs_with_cause, OverlapError, +}; pub use self::structural_match::{ search_for_adt_const_param_violation, search_for_structural_match_violation, }; diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 233d35aed38..9a4b72013b8 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -83,6 +83,30 @@ pub fn translate_substs<'tcx>( source_substs: SubstsRef<'tcx>, target_node: specialization_graph::Node, ) -> SubstsRef<'tcx> { + translate_substs_with_cause( + infcx, + param_env, + source_impl, + source_substs, + target_node, + |_, _| ObligationCause::dummy(), + ) +} + +/// Like [translate_substs], but obligations from the parent implementation +/// are registered with the provided `ObligationCause`. +/// +/// This is for reporting *region* errors from those bounds. Type errors should +/// not happen because the specialization graph already checks for those, and +/// will result in an ICE. +pub fn translate_substs_with_cause<'tcx>( + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + source_impl: DefId, + source_substs: SubstsRef<'tcx>, + target_node: specialization_graph::Node, + cause: impl Fn(usize, Span) -> ObligationCause<'tcx>, +) -> SubstsRef<'tcx> { debug!( "translate_substs({:?}, {:?}, {:?}, {:?})", param_env, source_impl, source_substs, target_node @@ -99,14 +123,13 @@ pub fn translate_substs<'tcx>( return source_substs; } - fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else( - |()| { + fulfill_implication(infcx, param_env, source_trait_ref, source_impl, target_impl, cause) + .unwrap_or_else(|()| { bug!( "When translating substitutions from {source_impl:?} to {target_impl:?}, \ the expected specialization failed to hold" ) - }, - ) + }) } specialization_graph::Node::Trait(..) => source_trait_ref.substs, }; @@ -153,20 +176,12 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // Create an infcx, taking the predicates of impl1 as assumptions: let infcx = tcx.infer_ctxt().build(); - let impl1_trait_ref = - match traits::fully_normalize(&infcx, ObligationCause::dummy(), penv, impl1_trait_ref) { - Ok(impl1_trait_ref) => impl1_trait_ref, - Err(_errors) => { - tcx.sess.delay_span_bug( - tcx.def_span(impl1_def_id), - format!("failed to fully normalize {impl1_trait_ref}"), - ); - impl1_trait_ref - } - }; // Attempt to prove that impl2 applies, given all of the above. - fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok() + fulfill_implication(&infcx, penv, impl1_trait_ref, impl1_def_id, impl2_def_id, |_, _| { + ObligationCause::dummy() + }) + .is_ok() } /// Attempt to fulfill all obligations of `target_impl` after unification with @@ -178,23 +193,41 @@ fn fulfill_implication<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, source_trait_ref: ty::TraitRef<'tcx>, + source_impl: DefId, target_impl: DefId, + error_cause: impl Fn(usize, Span) -> ObligationCause<'tcx>, ) -> Result<SubstsRef<'tcx>, ()> { debug!( "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)", param_env, source_trait_ref, target_impl ); + let source_trait_ref = match traits::fully_normalize( + &infcx, + ObligationCause::dummy(), + param_env, + source_trait_ref, + ) { + Ok(source_trait_ref) => source_trait_ref, + Err(_errors) => { + infcx.tcx.sess.delay_span_bug( + infcx.tcx.def_span(source_impl), + format!("failed to fully normalize {source_trait_ref}"), + ); + source_trait_ref + } + }; + let source_trait = ImplSubject::Trait(source_trait_ref); let selcx = &mut SelectionContext::new(&infcx); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); let (target_trait, obligations) = - util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs); + util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs, error_cause); // do the impls unify? If not, no specialization. let Ok(InferOk { obligations: more_obligations, .. }) = - infcx.at(&ObligationCause::dummy(), param_env, ).eq(DefineOpaqueTypes::No,source_trait, target_trait) + infcx.at(&ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, source_trait, target_trait) else { debug!( "fulfill_implication: {:?} does not unify with {:?}", diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 7b7e297c64b..82f3df40198 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -197,6 +197,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>( param_env: ty::ParamEnv<'tcx>, impl_def_id: DefId, impl_substs: SubstsRef<'tcx>, + cause: impl Fn(usize, Span) -> ObligationCause<'tcx>, ) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) { let subject = selcx.tcx().impl_subject(impl_def_id); let subject = subject.subst(selcx.tcx(), impl_substs); @@ -208,8 +209,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>( let predicates = predicates.instantiate(selcx.tcx(), impl_substs); let InferOk { value: predicates, obligations: normalization_obligations2 } = selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(predicates); - let impl_obligations = - super::predicates_for_generics(|_, _| ObligationCause::dummy(), param_env, predicates); + let impl_obligations = super::predicates_for_generics(cause, param_env, predicates); let impl_obligations = impl_obligations .chain(normalization_obligations1.into_iter()) |
