diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 85bb727a6c80..f34a5395cfe7 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -69,7 +69,7 @@ impl<'tcx> PredicateObligation<'tcx> { } } -impl TraitObligation<'_> { +impl<'tcx> TraitObligation<'tcx> { /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. pub fn is_const(&self) -> bool { match (self.predicate.skip_binder().constness, self.param_env.constness()) { @@ -77,6 +77,13 @@ impl TraitObligation<'_> { _ => false, } } + + pub fn derived_cause( + &self, + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, + ) -> ObligationCause<'tcx> { + self.cause.clone().derived_cause(self.predicate, variant) + } } // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index e5d4dfe891ef..550f5a086e94 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -179,6 +179,30 @@ impl<'tcx> ObligationCause<'tcx> { None => Lrc::new(MISC_OBLIGATION_CAUSE_CODE), })); } + + pub fn derived_cause( + mut self, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, + ) -> ObligationCause<'tcx> { + /*! + * Creates a cause for obligations that are derived from + * `obligation` by a recursive search (e.g., for a builtin + * bound, or eventually a `auto trait Foo`). If `obligation` + * is itself a derived obligation, this is just a clone, but + * otherwise we create a "derived obligation" cause so as to + * keep track of the original root obligation for error + * reporting. + */ + + // NOTE(flaper87): As of now, it keeps track of the whole error + // chain. Ideally, we should have a way to configure this either + // by using -Z verbose or just a CLI argument. + self.map_code(|parent_code| { + variant(DerivedObligationCause { parent_trait_pred, parent_code }).into() + }); + self + } } #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 771a3072af5d..613ac8a760ef 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; -use crate::traits::select::TraitObligationExt; use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def}; use crate::traits::{ BuiltinDerivedObligation, DerivedObligationCause, ImplDerivedObligation, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6584d33032a4..0790e5d56d5f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2342,42 +2342,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } -trait TraitObligationExt<'tcx> { - fn derived_cause( - &self, - variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, - ) -> ObligationCause<'tcx>; -} - -impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> { - fn derived_cause( - &self, - variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, - ) -> ObligationCause<'tcx> { - /*! - * Creates a cause for obligations that are derived from - * `obligation` by a recursive search (e.g., for a builtin - * bound, or eventually a `auto trait Foo`). If `obligation` - * is itself a derived obligation, this is just a clone, but - * otherwise we create a "derived obligation" cause so as to - * keep track of the original root obligation for error - * reporting. - */ - - let obligation = self; - - // NOTE(flaper87): As of now, it keeps track of the whole error - // chain. Ideally, we should have a way to configure this either - // by using -Z verbose or just a CLI argument. - let derived_cause = DerivedObligationCause { - parent_trait_pred: obligation.predicate, - parent_code: obligation.cause.clone_code(), - }; - let derived_code = variant(derived_cause); - ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code) - } -} - impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> { fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> { TraitObligationStackList::with(self) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 9752e8e73e79..18afc6dbcd80 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -301,14 +301,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let extend = |traits::PredicateObligation { predicate, mut cause, .. }| { if let Some(parent_trait_pred) = predicate.to_opt_poly_trait_pred() { - cause.map_code(|parent_code| { - { - traits::ObligationCauseCode::DerivedObligation( - traits::DerivedObligationCause { parent_trait_pred, parent_code }, - ) - } - .into() - }); + cause = cause.derived_cause( + parent_trait_pred, + traits::ObligationCauseCode::DerivedObligation, + ); } extend_cause_with_original_assoc_item_obligation( tcx, trait_ref, item, &mut cause, predicate,