diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index d21e78e70cf..d9d91b0f6be 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -83,6 +83,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// version (resolve_vars_if_possible), this version will /// also select obligations if it seems useful, in an effort /// to get more type information. + // FIXME(-Ztrait-solver=next): A lot of the calls to this method should + // probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead. pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> { self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {}) } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 420a6ee8978..1084e7acfeb 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,7 +1,6 @@ use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{needs_normalization, TraitEngineExt as _}; -use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; +use crate::traits::{needs_normalization, BoundVarReplacer, PlaceholderReplacer}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -13,22 +12,23 @@ use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex}; use rustc_middle::ty::{FallibleTypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; +use super::FulfillmentCtxt; + /// Deeply normalize all aliases in `value`. This does not handle inference and expects /// its input to be already fully resolved. pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable>>( at: At<'_, 'tcx>, value: T, ) -> Result>> { - let mut fulfill_cx = >::new(&at.infcx); - let mut folder = - NormalizationFolder { at, fulfill_cx: &mut *fulfill_cx, depth: 0, universes: Vec::new() }; + let fulfill_cx = FulfillmentCtxt::new(); + let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes: Vec::new() }; value.try_fold_with(&mut folder) } struct NormalizationFolder<'me, 'tcx> { at: At<'me, 'tcx>, - fulfill_cx: &'me mut dyn TraitEngine<'tcx>, + fulfill_cx: FulfillmentCtxt<'tcx>, depth: usize, universes: Vec>, } @@ -163,16 +163,14 @@ impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { return Ok(ty); } - let (kind, data) = match *ty.kind() { - ty::Alias(kind, alias_ty) => (kind, alias_ty), - _ => return ty.try_super_fold_with(self), - }; - // We don't normalize opaque types unless we have // `Reveal::All`, even if we're in the defining scope. - if matches!(kind, ty::Opaque) && reveal == Reveal::UserFacing { - return ty.try_super_fold_with(self); - } + let data = match *ty.kind() { + ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::UserFacing => { + alias_ty + } + _ => return ty.try_super_fold_with(self), + }; if data.has_escaping_bound_vars() { let (data, mapped_regions, mapped_types, mapped_consts) = diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 89aefc0de53..720998a51e0 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -409,7 +409,12 @@ pub fn normalize_param_env_or_error<'tcx>( ) } -/// Normalize a type and process all resulting obligations, returning any errors +/// Normalize a type and process all resulting obligations, returning any errors. +/// +/// FIXME(-Ztrait-solver=next): This should be replaced by `At::deeply_normalize` +/// which has the same behavior with the new solver. Because using a separate +/// fulfillment context worsens caching in the old solver, `At::deeply_normalize` +/// is still lazy with the old solver as it otherwise negatively impacts perf. #[instrument(skip_all)] pub fn fully_normalize<'tcx, T>( infcx: &InferCtxt<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 56724653cb8..162e51d1fd6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -58,12 +58,18 @@ pub trait NormalizeExt<'tcx> { /// Deeply normalizes `value`, replacing all aliases which can by normalized in /// the current environment. In the new solver this errors in case normalization - /// fails or is ambiguous. This only normalize opaque types with `Reveal::All`. + /// fails or is ambiguous. This only normalizes opaque types with `Reveal::All`. /// /// In the old solver this simply uses `normalizes` and adds the nested obligations /// to the `fulfill_cx`. This is necessary as we otherwise end up recomputing the /// same goals in both a temporary and the shared context which negatively impacts /// performance as these don't share caching. + /// + /// FIXME(-Ztrait-solver=next): This has the same behavior as `traits::fully_normalize` + /// in the new solver, but because of performance reasons, we currently reuse an + /// existing fulfillment context in the old solver. Once we also eagerly prove goals with + /// the old solver or have removed the old solver, remove `traits::fully_normalize` and + /// rename this function to `At::fully_normalize`. fn deeply_normalize>>( self, value: T,