diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_traits/src/type_op.rs | 68 |
1 files changed, 40 insertions, 28 deletions
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index d895b647d..bca7458ed 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -3,12 +3,12 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::TraitEngineExt as _; +use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts}; use rustc_middle::ty::{ self, EarlyBinder, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance, }; +use rustc_middle::ty::{GenericArg, UserSelfTy, UserSubsts}; use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate}; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtBuilderExt; @@ -22,6 +22,7 @@ use rustc_trait_selection::traits::query::type_op::subtype::Subtype; use rustc_trait_selection::traits::query::{Fallible, NoSolution}; use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine}; use std::fmt; +use std::iter::zip; pub(crate) fn provide(p: &mut Providers) { *p = Providers { @@ -50,7 +51,7 @@ fn type_op_ascribe_user_type<'tcx>( /// 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_ascribe_user_type_with_span<'a, 'tcx: 'a>( - infcx: &'a InferCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'tcx>, fulfill_cx: &'a mut dyn TraitEngine<'tcx>, key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>, span: Option<Span>, @@ -61,14 +62,15 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>( mir_ty, def_id, user_substs ); - let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx }; - cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs, span)?; + let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx }; + cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?; Ok(()) } struct AscribeUserTypeCx<'me, 'tcx> { - infcx: &'me InferCtxt<'me, 'tcx>, + infcx: &'me InferCtxt<'tcx>, param_env: ParamEnv<'tcx>, + span: Span, fulfill_cx: &'me mut dyn TraitEngine<'tcx>, } @@ -77,12 +79,15 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { where T: TypeFoldable<'tcx>, { + self.normalize_with_cause(value, ObligationCause::misc(self.span, hir::CRATE_HIR_ID)) + } + + fn normalize_with_cause<T>(&mut self, value: T, cause: ObligationCause<'tcx>) -> T + where + T: TypeFoldable<'tcx>, + { self.infcx - .partially_normalize_associated_types_in( - ObligationCause::misc(DUMMY_SP, hir::CRATE_HIR_ID), - self.param_env, - value, - ) + .partially_normalize_associated_types_in(cause, self.param_env, value) .into_value_registering_obligations(self.infcx, self.fulfill_cx) } @@ -91,18 +96,13 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { T: ToTrace<'tcx>, { self.infcx - .at(&ObligationCause::dummy(), self.param_env) + .at(&ObligationCause::dummy_with_span(self.span), self.param_env) .relate(a, variance, b)? .into_value_registering_obligations(self.infcx, self.fulfill_cx); Ok(()) } - fn prove_predicate(&mut self, predicate: Predicate<'tcx>, span: Option<Span>) { - let cause = if let Some(span) = span { - ObligationCause::dummy_with_span(span) - } else { - ObligationCause::dummy() - }; + fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) { self.fulfill_cx.register_predicate_obligation( self.infcx, Obligation::new(cause, self.param_env, predicate), @@ -120,20 +120,20 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { EarlyBinder(value).subst(self.tcx(), substs) } + #[instrument(level = "debug", skip(self))] fn relate_mir_and_user_ty( &mut self, mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>, - span: Option<Span>, ) -> Result<(), NoSolution> { let UserSubsts { user_self_ty, substs } = user_substs; let tcx = self.tcx(); let ty = tcx.type_of(def_id); let ty = self.subst(ty, substs); - debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); let ty = self.normalize(ty); + debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); self.relate(mir_ty, Variance::Invariant, ty)?; @@ -144,10 +144,22 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { // outlives" error messages. let instantiated_predicates = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); - debug!(?instantiated_predicates.predicates); - for instantiated_predicate in instantiated_predicates.predicates { - let instantiated_predicate = self.normalize(instantiated_predicate); - self.prove_predicate(instantiated_predicate, span); + + let cause = ObligationCause::dummy_with_span(self.span); + + debug!(?instantiated_predicates); + for (instantiated_predicate, predicate_span) in + zip(instantiated_predicates.predicates, instantiated_predicates.spans) + { + let span = if self.span == DUMMY_SP { predicate_span } else { self.span }; + let cause = ObligationCause::new( + span, + hir::CRATE_HIR_ID, + ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span), + ); + let instantiated_predicate = + self.normalize_with_cause(instantiated_predicate, cause.clone()); + self.prove_predicate(instantiated_predicate, cause); } if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { @@ -160,7 +172,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())) .to_predicate(self.tcx()), - span, + cause.clone(), ); } @@ -177,7 +189,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { // which...could happen with normalization... self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()), - span, + cause, ); Ok(()) } @@ -198,7 +210,7 @@ fn type_op_eq<'tcx>( } fn type_op_normalize<'tcx, T>( - infcx: &InferCtxt<'_, 'tcx>, + infcx: &InferCtxt<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx>, key: ParamEnvAnd<'tcx, Normalize<T>>, ) -> Fallible<T> @@ -273,7 +285,7 @@ fn type_op_prove_predicate<'tcx>( /// 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_cause<'a, 'tcx: 'a>( - infcx: &'a InferCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'tcx>, fulfill_cx: &'a mut dyn TraitEngine<'tcx>, key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>, cause: ObligationCause<'tcx>, |