diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 12b9940a83f44..8700044cb05b6 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -29,7 +29,7 @@ use super::{ }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::{InferCtxt, TyOrConstInferVar}; -use crate::traits::normalize::normalize_with_depth_to; +use crate::traits::normalize::normalize_with_depth_to_preresolved; use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{EvaluateConstErr, sizedness_fast_path}; @@ -401,7 +401,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { if obligation.predicate.has_aliases() { let mut obligations = PredicateObligations::new(); - let predicate = normalize_with_depth_to( + // The predicate was already brought to its resolution fixpoint + // above, so normalization does not need to resolve it again. + let predicate = normalize_with_depth_to_preresolved( &mut self.selcx, obligation.param_env, obligation.cause.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 2a28fab776a12..a67faf6827b2d 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -129,6 +129,29 @@ where result } +/// Like [`normalize_with_depth_to`], for values the caller has already brought +/// to their inference resolution fixpoint: the initial full resolving fold is +/// skipped, since it could not change the value. +pub(crate) fn normalize_with_depth_to_preresolved<'a, 'b, 'tcx, T>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + value: T, + obligations: &mut PredicateObligations<'tcx>, +) -> T +where + T: TypeFoldable>, +{ + debug!(obligations.len = obligations.len()); + let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); + let result = + ensure_sufficient_stack(|| AssocTypeNormalizer::fold_preresolved(&mut normalizer, value)); + debug!(?result, obligations.len = normalizer.obligations.len()); + debug!(?normalizer.obligations,); + result +} + pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( infcx: &InferCtxt<'tcx>, value: &T, @@ -172,6 +195,12 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { fn fold>>(&mut self, value: T) -> T { let value = self.selcx.infcx.resolve_vars_if_possible(value); + self.fold_preresolved(value) + } + + /// [`Self::fold`] for values already at their inference resolution + /// fixpoint, where the resolving fold would be the identity. + fn fold_preresolved>>(&mut self, value: T) -> T { debug!(?value); assert!(