From bea75baa717126f13a5fc78b850803a0862f160f Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sat, 11 Jul 2026 07:25:53 +0000 Subject: [PATCH] 1. DeeplyNormalize QueryTpeOp and normalize_with_depth_to takes Unnormalized as input 2. add unnormalized producing API's 3. merge Deeply Normalize and Normalize 4. make normalize_with_category accept unnormalized --- .../src/diagnostics/bound_region_errors.rs | 72 ++----- .../src/type_check/canonical.rs | 16 +- .../src/type_check/constraint_conversion.rs | 12 +- .../src/type_check/free_region_relations.rs | 39 ++-- compiler/rustc_borrowck/src/type_check/mod.rs | 10 +- compiler/rustc_infer/src/infer/mod.rs | 34 ++- compiler/rustc_middle/src/queries.rs | 8 +- compiler/rustc_middle/src/traits/query.rs | 19 +- compiler/rustc_middle/src/ty/sty.rs | 5 + .../src/traits/effects.rs | 4 +- .../src/traits/fulfill.rs | 2 +- .../src/traits/normalize.rs | 9 +- .../src/traits/project.rs | 200 +++++++++--------- .../src/traits/query/type_op/normalize.rs | 70 ++---- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 25 +-- .../src/traits/select/mod.rs | 47 ++-- .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_traits/src/type_op.rs | 16 +- compiler/rustc_type_ir/src/ty_kind.rs | 14 +- compiler/rustc_type_ir/src/ty_kind/closure.rs | 30 ++- compiler/rustc_type_ir/src/unnormalized.rs | 16 +- 22 files changed, 316 insertions(+), 336 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 538c5887118e6..d7fe7ddf261ed 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -9,12 +9,12 @@ use rustc_infer::infer::{ }; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::query::{ - CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpDeeplyNormalizeGoal, - CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, + CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal, + CanonicalTypeOpProvePredicateGoal, }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, Unnormalized, + self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, }; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -109,14 +109,6 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable> + 'tcx> ToUnivers } } -impl<'tcx, T: Copy + fmt::Display + TypeFoldable> + 'tcx> ToUniverseInfo<'tcx> - for CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> -{ - fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - UniverseInfo::TypeOp(Rc::new(DeeplyNormalizeQuery { canonical_query: self, base_universe })) - } -} - impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> { fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe })) @@ -247,7 +239,14 @@ where fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> { tcx.dcx().create_err(HigherRankedLifetimeError { cause: Some(HigherRankedErrorCause::CouldNotNormalize { - value: self.canonical_query.canonical.value.value.value.to_string(), + value: self + .canonical_query + .canonical + .value + .value + .value + .skip_normalization() + .to_string(), }), span, }) @@ -275,54 +274,7 @@ where // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` // test. Check after #85499 lands to see if its fixes have erased this difference. let ty::ParamEnvAnd { param_env, value } = key; - let _ = ocx.normalize(&cause, param_env, Unnormalized::new_wip(value.value)); - - let diag = try_extract_error_from_fulfill_cx( - &ocx, - mbcx.mir_def_id(), - placeholder_region, - error_region, - )? - .with_dcx(mbcx.dcx()); - Some(diag) - } -} - -struct DeeplyNormalizeQuery<'tcx, T> { - canonical_query: CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>, - base_universe: ty::UniverseIndex, -} - -impl<'tcx, T> TypeOpInfo<'tcx> for DeeplyNormalizeQuery<'tcx, T> -where - T: Copy + fmt::Display + TypeFoldable> + 'tcx, -{ - fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> { - tcx.dcx().create_err(HigherRankedLifetimeError { - cause: Some(HigherRankedErrorCause::CouldNotNormalize { - value: self.canonical_query.canonical.value.value.value.to_string(), - }), - span, - }) - } - - fn base_universe(&self) -> ty::UniverseIndex { - self.base_universe - } - - fn nice_error<'infcx>( - &self, - mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, - cause: ObligationCause<'tcx>, - placeholder_region: ty::Region<'tcx>, - error_region: Option>, - ) -> Option> { - let (infcx, key, _) = - mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let ocx = ObligationCtxt::new(&infcx); - - let ty::ParamEnvAnd { param_env, value } = key; - let _ = ocx.deeply_normalize(&cause, param_env, Unnormalized::new_wip(value.value)); + let _ = ocx.normalize(&cause, param_env, value.value); let diag = try_extract_error_from_fulfill_cx( &ocx, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 56c800dcf7c7e..8bb916704996d 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -194,16 +194,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.normalize_with_category(value, location, ConstraintCategory::Boring) } - pub(super) fn deeply_normalize(&mut self, value: T, location: impl NormalizeLocation) -> T + pub(super) fn deeply_normalize( + &mut self, + value: Unnormalized<'tcx, T>, + location: impl NormalizeLocation, + ) -> Result where T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, { - let result: Result<_, ErrorGuaranteed> = self.fully_perform_op( + self.fully_perform_op( location.to_locations(), ConstraintCategory::Boring, - self.infcx.param_env.and(type_op::normalize::DeeplyNormalize { value }), - ); - result.unwrap_or(value) + self.infcx.param_env.and(type_op::normalize::Normalize { value }), + ) } #[instrument(skip(self), level = "debug")] @@ -216,14 +219,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { where T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, { - let value = value.skip_normalization(); let param_env = self.infcx.param_env; let result: Result<_, ErrorGuaranteed> = self.fully_perform_op( location.to_locations(), category, param_env.and(type_op::normalize::Normalize { value }), ); - result.unwrap_or(value) + result.unwrap_or(value.skip_norm_wip()) } #[instrument(skip(self), level = "debug")] diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 82e623bb42535..17d75986d28e7 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::canonical::{QueryRegionConstraint, QueryRegionConstraint use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; -use rustc_infer::traits::query::type_op::DeeplyNormalize; +use rustc_infer::traits::query::type_op::Normalize; use rustc_middle::bug; use rustc_middle::ty::{ self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions, @@ -183,7 +183,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // in the new trait solver. if infcx.next_trait_solver() { t1 = self.normalize_and_add_type_outlives_constraints( - t1, + ty::Unnormalized::new_wip(t1), &mut next_outlives_predicates, ); } @@ -279,15 +279,17 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { self.constraints.type_tests.push(type_test); } + // FIXME(trait-refactor-initiative#260): This function needs to + // be removed. fn normalize_and_add_type_outlives_constraints( &self, - ty: Ty<'tcx>, + ty: ty::Unnormalized<'tcx, Ty<'tcx>>, next_outlives_predicates: &mut Vec<( ty::ArgOutlivesPredicate<'tcx>, ConstraintCategory<'tcx>, )>, ) -> Ty<'tcx> { - match self.infcx.fully_perform(DeeplyNormalize { value: ty }, self.span) { + match self.infcx.fully_perform(Normalize { value: ty }, self.span) { Ok(TypeOpOutput { output: ty, constraints, .. }) => { // FIXME(higher_ranked_auto): What should we do with the assumptions here? if let Some(QueryRegionConstraints { constraints, assumptions: _ }) = constraints { @@ -299,7 +301,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } ty } - Err(_) => ty, + Err(_) => ty.skip_norm_wip(), } } } diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 62becc8e298f4..a89d45c4b0b2a 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::GenericKind; -use rustc_infer::traits::query::type_op::DeeplyNormalize; +use rustc_infer::traits::query::type_op::Normalize; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::OutlivesBound; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; @@ -244,7 +244,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { } let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self .infcx - .fully_perform(DeeplyNormalize { value: ty }, span) + .fully_perform(Normalize { value: ty::Unnormalized::new_wip(ty) }, span) .unwrap_or_else(|guar| TypeOpOutput { output: Ty::new_error(self.infcx.tcx, guar), constraints: None, @@ -298,8 +298,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst { .. }) { for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) { - let result: Result<_, ErrorGuaranteed> = - self.infcx.fully_perform(DeeplyNormalize { value: ty }, span); + let result: Result<_, ErrorGuaranteed> = self + .infcx + .fully_perform(Normalize { value: ty::Unnormalized::new_wip(ty) }, span); let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else { continue; }; @@ -348,18 +349,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { ) { // In the new solver, normalize the type-outlives obligation assumptions. if self.infcx.next_trait_solver() { - let Ok(TypeOpOutput { - output: normalized_outlives, - constraints: constraints_normalize, - error_info: _, - }) = self.infcx.fully_perform(DeeplyNormalize { value: outlives }, span) - else { - self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}")); - return; - }; - outlives = normalized_outlives; - if let Some(c) = constraints_normalize { - constraints.push(c); + match self + .infcx + .fully_perform(Normalize { value: ty::Unnormalized::new_wip(outlives) }, span) + { + Ok(TypeOpOutput { + output: normalized_outlives, + constraints: constraints_normalize, + error_info: _, + }) => { + outlives = normalized_outlives; + if let Some(c) = constraints_normalize { + constraints.push(c); + } + } + Err(guar) => { + let _: ErrorGuaranteed = guar; + return; + } } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 123bc1f568495..a0cfe000c5a2a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -829,7 +829,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ConstraintCategory::Boring, ); - let sig = self.deeply_normalize(unnormalized_sig, term_location); + let sig = match self + .deeply_normalize(ty::Unnormalized::new_wip(unnormalized_sig), term_location) + { + Ok(sig) => sig, + Err(guar) => { + let _: ErrorGuaranteed = guar; + return; + } + }; // HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))` // with built-in `Fn` implementations, since the impl may not be // well-formed itself. diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aa2fe2ee21dfa..4e04a42cccb72 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1394,24 +1394,17 @@ impl<'tcx> InferCtxt<'tcx> { } } - // Instantiates the bound variables in a given binder with fresh inference - // variables in the current universe. - // - // Use this method if you'd like to find some generic parameters of the binder's - // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`] - // that corresponds to your use case, consider whether or not you should - // use [`InferCtxt::enter_forall`] instead. - pub fn instantiate_binder_with_fresh_vars( + pub fn instantiate_binder_with_fresh_vars_unnormalized( &self, span: Span, lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, - ) -> T + ) -> ty::Unnormalized<'tcx, T> where T: TypeFoldable> + Copy, { if let Some(inner) = value.no_bound_vars() { - return inner; + return ty::Unnormalized::new(inner); } let bound_vars = value.bound_vars(); @@ -1444,7 +1437,26 @@ impl<'tcx> InferCtxt<'tcx> { } } let delegate = ToFreshVars { args }; - self.tcx.replace_bound_vars_uncached(value, delegate) + ty::Unnormalized::new(self.tcx.replace_bound_vars_uncached(value, delegate)) + } + + // Instantiates the bound variables in a given binder with fresh inference + // variables in the current universe. + // + // Use this method if you'd like to find some generic parameters of the binder's + // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`] + // that corresponds to your use case, consider whether or not you should + // use [`InferCtxt::enter_forall`] instead. + pub fn instantiate_binder_with_fresh_vars( + &self, + span: Span, + lbrct: BoundRegionConversionTime, + value: ty::Binder<'tcx, T>, + ) -> T + where + T: TypeFoldable> + Copy, + { + self.instantiate_binder_with_fresh_vars_unnormalized(span, lbrct, value).skip_norm_wip() } /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index f0557c3d3381a..8c887bf6da691 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2510,7 +2510,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, NoSolution, > { - desc { "normalizing `{}`", goal.canonical.value.value.value } + desc { "normalizing `{}`", goal.canonical.value.value.value.skip_normalization() } } /// Do not call this query directly: part of the `Normalize` type-op @@ -2520,7 +2520,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } + desc { "normalizing `{:?}`", goal.canonical.value.value.value.skip_normalization() } } /// Do not call this query directly: part of the `Normalize` type-op @@ -2530,7 +2530,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } + desc { "normalizing `{:?}`", goal.canonical.value.value.value.skip_normalization() } } /// Do not call this query directly: part of the `Normalize` type-op @@ -2540,7 +2540,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } + desc { "normalizing `{:?}`", goal.canonical.value.value.value.skip_normalization() } } query instantiate_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool { diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index d6e6c56c00312..92aa6fe47a7e4 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -17,7 +17,7 @@ use crate::ty::{self, GenericArg, Ty, TyCtxt}; pub mod type_op { use rustc_macros::{StableHash, TypeFoldable, TypeVisitable}; - use crate::ty::{Predicate, Ty, UserType}; + use crate::ty::{Predicate, Ty, Unnormalized, UserType}; #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, StableHash, TypeFoldable, TypeVisitable)] pub struct AscribeUserType<'tcx> { @@ -42,16 +42,10 @@ pub mod type_op { pub predicate: Predicate<'tcx>, } - /// Normalizes, but not in the new solver. + /// Normalizes a value that may contain unnormalized aliases. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, StableHash, TypeFoldable, TypeVisitable)] - pub struct Normalize { - pub value: T, - } - - /// Normalizes, and deeply normalizes in the new solver. - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, StableHash, TypeFoldable, TypeVisitable)] - pub struct DeeplyNormalize { - pub value: T, + pub struct Normalize<'tcx, T> { + pub value: Unnormalized<'tcx, T>, } #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, StableHash, TypeFoldable, TypeVisitable)] @@ -89,10 +83,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> = CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>; pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = - CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize>>; - -pub type CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> = - CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DeeplyNormalize>>; + CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<'tcx, T>>>; pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> = CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0042c87c3eda7..72f04282ac8ec 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1630,6 +1630,11 @@ impl<'tcx> Ty<'tcx> { self.kind().fn_sig(tcx) } + #[tracing::instrument(level = "trace", skip(tcx))] + pub fn unnormalized_fn_sig(self, tcx: TyCtxt<'tcx>) -> ty::Unnormalized<'tcx, PolyFnSig<'tcx>> { + self.kind().unnormalized_fn_sig(tcx) + } + #[inline] pub fn is_fn(self) -> bool { matches!(self.kind(), FnDef(..) | FnPtr(..)) diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index f6a7bbdc686ec..18be3570b5325 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -104,7 +104,7 @@ fn match_candidate<'tcx>( obligation.param_env, obligation.cause.clone(), obligation.recursion_depth, - candidate, + Unnormalized::new_wip(candidate), &mut nested, ); } @@ -245,7 +245,7 @@ fn evaluate_host_effect_from_conditionally_const_item_bounds<'tcx>( obligation.param_env, obligation.cause.clone(), obligation.recursion_depth, - trait_ref.skip_norm_wip(), + trait_ref, nested, ); (trait_ref, span) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 12b9940a83f44..af961560ac7f5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -406,7 +406,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - obligation.predicate, + ty::Unnormalized::new_wip(obligation.predicate), &mut obligations, ); if predicate != obligation.predicate { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 2a28fab776a12..adb2e7a7060a5 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -35,7 +35,6 @@ impl<'tcx> At<'_, 'tcx> { let Normalized { value, obligations } = crate::solve::normalize(*self, value); InferOk { value, obligations } } else { - let value = value.skip_normalization(); let mut selcx = SelectionContext::new(self.infcx); let Normalized { value, obligations } = normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); @@ -99,7 +98,7 @@ pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>( param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - value: T, + value: Unnormalized<'tcx, T>, ) -> Normalized<'tcx, T> where T: TypeFoldable>, @@ -115,7 +114,7 @@ pub(crate) fn normalize_with_depth_to<'a, 'b, 'tcx, T>( param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - value: T, + value: Unnormalized<'tcx, T>, obligations: &mut PredicateObligations<'tcx>, ) -> T where @@ -123,7 +122,9 @@ where { debug!(obligations.len = obligations.len()); let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); - let result = ensure_sufficient_stack(|| AssocTypeNormalizer::fold(&mut normalizer, value)); + let result = ensure_sufficient_stack(|| { + AssocTypeNormalizer::fold(&mut normalizer, value.skip_normalization()) + }); debug!(?result, obligations.len = normalizer.obligations.len()); debug!(?normalizer.obligations,); result diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e2257703f5775..7c47a6150f933 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -401,7 +401,10 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( Normalized { value: normalized_ty, obligations: projected_obligations } } else { - Normalized { value: projected_term, obligations: projected_obligations } + Normalized { + value: projected_term.skip_normalization(), + obligations: projected_obligations, + } }; let mut deduped = SsoHashSet::with_capacity(result.obligations.len()); @@ -551,7 +554,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( param_env, cause.clone(), depth + 1, - predicate.skip_norm_wip(), + predicate, obligations, ); @@ -574,10 +577,17 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( )); } - let term: Term<'tcx> = if alias_term.kind.is_type() { - tcx.type_of(def_id).instantiate(tcx, args).skip_norm_wip().into() + let term: ty::Unnormalized<'tcx, Term<'tcx>> = if alias_term.kind.is_type() { + tcx.type_of(def_id).instantiate(tcx, args).map(Into::into) + } else { + tcx.const_of_item(def_id).instantiate(tcx, args).map(Into::into) + }; + + let term = selcx.infcx.resolve_vars_if_possible(term); + let term = if term.has_aliases() { + normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, term, obligations) } else { - tcx.const_of_item(def_id).instantiate(tcx, args).skip_norm_wip().into() + term.skip_normalization() }; push_const_arg_has_type_obligation( @@ -591,12 +601,6 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( args, ); - let mut term = selcx.infcx.resolve_vars_if_possible(term); - if term.has_aliases() { - term = - normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, term, obligations); - } - term } @@ -615,31 +619,21 @@ pub fn compute_inherent_assoc_term_args<'a, 'b, 'tcx>( let impl_def_id = tcx.parent(alias_def_id); let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id); - let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(); - if !selcx.infcx.next_trait_solver() { - impl_ty = normalize_with_depth_to( - selcx, - param_env, - cause.clone(), - depth + 1, - impl_ty, - obligations, - ); - } + let impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args); + let impl_ty = if !selcx.infcx.next_trait_solver() { + normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations) + } else { + impl_ty.skip_normalization() + }; // Infer the generic parameters of the impl by unifying the // impl type with the self type of the projection. - let mut self_ty = alias_term.self_ty(); - if !selcx.infcx.next_trait_solver() { - self_ty = normalize_with_depth_to( - selcx, - param_env, - cause.clone(), - depth + 1, - self_ty, - obligations, - ); - } + let self_ty = ty::Unnormalized::dummy(alias_term.self_ty()); + let self_ty = if !selcx.infcx.next_trait_solver() { + normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, self_ty, obligations) + } else { + self_ty.skip_normalization() + }; match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::Yes, impl_ty, self_ty) { Ok(mut ok) => obligations.append(&mut ok.obligations), @@ -660,7 +654,7 @@ enum Projected<'tcx> { } struct Progress<'tcx> { - term: ty::Term<'tcx>, + term: ty::Unnormalized<'tcx, ty::Term<'tcx>>, obligations: PredicateObligations<'tcx>, } @@ -675,7 +669,10 @@ impl<'tcx> Progress<'tcx> { } else { ty::Const::new_error(tcx, guar).into() }; - Progress { term: err_term, obligations: PredicateObligations::new() } + Progress { + term: ty::Unnormalized::dummy(err_term), + obligations: PredicateObligations::new(), + } } fn with_addl_obligations(mut self, mut obligations: PredicateObligations<'tcx>) -> Self { @@ -1103,14 +1100,15 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( |ty| { // We throw away any obligations we get from this, since we normalize // and confirm these obligations once again during confirmation - normalize_with_depth( + let mut obligations = PredicateObligations::new(); + normalize_with_depth_to( selcx, obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - ty.skip_norm_wip(), + ty, + &mut obligations, ) - .value }, || {}, ); @@ -1346,7 +1344,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( "expected coroutine self type for built-in coroutine candidate, found {self_ty}" ) }; - let coroutine_sig = args.as_coroutine().sig(); + let coroutine_sig = args.as_coroutine().unnormalized_sig(); let Normalized { value: coroutine_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -1402,7 +1400,7 @@ fn confirm_future_candidate<'cx, 'tcx>( "expected coroutine self type for built-in async future candidate, found {self_ty}" ) }; - let coroutine_sig = args.as_coroutine().sig(); + let coroutine_sig = args.as_coroutine().unnormalized_sig(); let Normalized { value: coroutine_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -1447,7 +1445,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( let ty::Coroutine(_, args) = self_ty.kind() else { unreachable!("expected coroutine self type for built-in gen candidate, found {self_ty}") }; - let gen_sig = args.as_coroutine().sig(); + let gen_sig = args.as_coroutine().unnormalized_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -1492,7 +1490,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( else { unreachable!() }; - let gen_sig = args.as_coroutine().sig(); + let gen_sig = args.as_coroutine().unnormalized_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -1563,7 +1561,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - ty.skip_norm_wip(), + ty, &mut obligations, ) }; @@ -1626,7 +1624,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); - let sig = fn_type.fn_sig(tcx); + let sig = fn_type.unnormalized_fn_sig(tcx); let Normalized { value: sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -1648,7 +1646,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let closure_sig = match *self_ty.kind() { - ty::Closure(_, args) => args.as_closure().sig(), + ty::Closure(_, args) => args.as_closure().unnormalized_sig(), // Construct a "normal" `FnOnce` signature for coroutine-closure. This is // basically duplicated with the `AsyncFnOnce::CallOnce` confirmation, but @@ -1656,49 +1654,51 @@ fn confirm_closure_candidate<'cx, 'tcx>( ty::CoroutineClosure(def_id, args) => { let args = args.as_coroutine_closure(); let kind_ty = args.kind_ty(); - args.coroutine_closure_sig().map_bound(|sig| { - // If we know the kind and upvars, use that directly. - // Otherwise, defer to `AsyncFnKindHelper::Upvars` to delay - // the projection, like the `AsyncFn*` traits do. - let output_ty = if let Some(_) = kind_ty.to_opt_closure_kind() + args.unnormalized_coroutine_closure_sig().map(|sig| { + sig.map_bound(|sig| { + // If we know the kind and upvars, use that directly. + // Otherwise, defer to `AsyncFnKindHelper::Upvars` to delay + // the projection, like the `AsyncFn*` traits do. + let output_ty = if let Some(_) = kind_ty.to_opt_closure_kind() // Fall back to projection if upvars aren't constrained && !args.tupled_upvars_ty().is_ty_var() - { - sig.to_coroutine_given_kind_and_upvars( - tcx, - args.parent_args(), - tcx.coroutine_for_closure(def_id), - ty::ClosureKind::FnOnce, - tcx.lifetimes.re_static, - args.tupled_upvars_ty(), - args.coroutine_captures_by_ref_ty(), - ) - } else { - let upvars_projection_def_id = - tcx.require_lang_item(LangItem::AsyncFnKindUpvars, obligation.cause.span); - let tupled_upvars_ty = Ty::new_projection( - tcx, - ty::IsRigid::No, - upvars_projection_def_id, - [ - ty::GenericArg::from(kind_ty), - Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce).into(), - tcx.lifetimes.re_static.into(), - sig.tupled_inputs_ty.into(), - args.tupled_upvars_ty().into(), - args.coroutine_captures_by_ref_ty().into(), - ], - ); - sig.to_coroutine( - tcx, - args.parent_args(), - Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce), - tcx.coroutine_for_closure(def_id), - tupled_upvars_ty, - ) - }; - - tcx.mk_fn_sig([sig.tupled_inputs_ty], output_ty, sig.fn_sig_kind) + { + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(def_id), + ty::ClosureKind::FnOnce, + tcx.lifetimes.re_static, + args.tupled_upvars_ty(), + args.coroutine_captures_by_ref_ty(), + ) + } else { + let upvars_projection_def_id = tcx + .require_lang_item(LangItem::AsyncFnKindUpvars, obligation.cause.span); + let tupled_upvars_ty = Ty::new_projection( + tcx, + ty::IsRigid::No, + upvars_projection_def_id, + [ + ty::GenericArg::from(kind_ty), + Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce).into(), + tcx.lifetimes.re_static.into(), + sig.tupled_inputs_ty.into(), + args.tupled_upvars_ty().into(), + args.coroutine_captures_by_ref_ty().into(), + ], + ); + sig.to_coroutine( + tcx, + args.parent_args(), + Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce), + tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ) + }; + + tcx.mk_fn_sig([sig.tupled_inputs_ty], output_ty, sig.fn_sig_kind) + }) }) } @@ -1962,13 +1962,13 @@ fn confirm_param_env_candidate<'cx, 'tcx>( let cause = &obligation.cause; let param_env = obligation.param_env; - let cache_entry = infcx.instantiate_binder_with_fresh_vars( + let cache_entry = infcx.instantiate_binder_with_fresh_vars_unnormalized( cause.span, BoundRegionConversionTime::HigherRankedType, poly_cache_entry, ); - let cache_projection = cache_entry.projection_term; + let cache_projection = cache_entry.map(|entry| entry.projection_term); let mut nested_obligations = PredicateObligations::new(); let obligation_projection = obligation.predicate; let obligation_projection = ensure_sufficient_stack(|| { @@ -1977,7 +1977,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - obligation_projection, + ty::Unnormalized::new_wip(obligation_projection), &mut nested_obligations, ) }); @@ -1993,7 +1993,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ) }) } else { - cache_projection + cache_projection.skip_normalization() }; debug!(?cache_projection, ?obligation_projection); @@ -2006,7 +2006,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); assoc_term_own_obligations(selcx, obligation, &mut nested_obligations); - Progress { term: cache_entry.term, obligations: nested_obligations } + Progress { term: cache_entry.map(|entry| entry.term), obligations: nested_obligations } } Err(e) => { let msg = format!( @@ -2014,7 +2014,10 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); debug!("confirm_param_env_candidate: {}", msg); let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg); - Progress { term: err.into(), obligations: PredicateObligations::new() } + Progress { + term: ty::Unnormalized::dummy(err.into()), + obligations: PredicateObligations::new(), + } } } } @@ -2063,11 +2066,11 @@ fn confirm_impl_candidate<'cx, 'tcx>( return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx, ty::IsRigid::No))); } else { return Ok(Projected::Progress(Progress { - term: if obligation.predicate.kind.is_type() { + term: ty::Unnormalized::dummy(if obligation.predicate.kind.is_type() { Ty::new_misc_error(tcx).into() } else { ty::Const::new_misc_error(tcx).into() - }, + }), obligations: nested, })); } @@ -2096,17 +2099,18 @@ fn confirm_impl_candidate<'cx, 'tcx>( } else { ty::Const::new_error_with_message(tcx, span, msg).into() }; - Progress { term: err, obligations: nested } + Progress { term: ty::Unnormalized::dummy(err), obligations: nested } } else { assoc_term_own_obligations(selcx, obligation, &mut nested); - let instantiated_term: Term<'tcx> = term.instantiate(tcx, args).skip_norm_wip(); + let instantiated_term = term.instantiate(tcx, args); + let term_for_obligation = instantiated_term.skip_normalization(); push_const_arg_has_type_obligation( tcx, &mut nested, &obligation.cause, obligation.recursion_depth + 1, obligation.param_env, - instantiated_term, + term_for_obligation, assoc_term.item.def_id, args, ); @@ -2135,7 +2139,7 @@ fn assoc_term_own_obligations<'cx, 'tcx>( obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - predicate.skip_norm_wip(), + predicate, nested, ); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs index 577a5564c6312..1eef77b436ac6 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs @@ -2,23 +2,25 @@ use std::fmt; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; -pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize}; -use rustc_middle::ty::{ - self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Unnormalized, -}; +pub use rustc_middle::traits::query::type_op::Normalize; +use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse}; use crate::traits::ObligationCtxt; -impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize +impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<'tcx, T> where T: Normalizable<'tcx> + 'tcx, { type QueryResponse = T; fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option { - if !key.value.value.has_aliases() { Some(key.value.value) } else { None } + if !key.value.value.skip_normalization().has_aliases() { + Some(key.value.value.skip_normalization()) + } else { + None + } } fn perform_query( @@ -36,49 +38,7 @@ where ocx.deeply_normalize( &ObligationCause::dummy_with_span(span), key.param_env, - Unnormalized::new_wip(key.value.value), - ) - .map_err(|_| NoSolution) - } -} - -impl<'tcx, T> super::QueryTypeOp<'tcx> for DeeplyNormalize -where - T: Normalizable<'tcx> + 'tcx, -{ - type QueryResponse = T; - - fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option { - if !key.value.value.has_aliases() { Some(key.value.value) } else { None } - } - - fn perform_query( - tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>, - ) -> Result, NoSolution> { - T::type_op_method( - tcx, - CanonicalQueryInput { - typing_mode: canonicalized.typing_mode, - canonical: canonicalized.canonical.unchecked_map( - |ty::ParamEnvAnd { param_env, value }| ty::ParamEnvAnd { - param_env, - value: Normalize { value: value.value }, - }, - ), - }, - ) - } - - fn perform_locally_with_next_solver( - ocx: &ObligationCtxt<'_, 'tcx>, - key: ParamEnvAnd<'tcx, Self>, - span: Span, - ) -> Result { - ocx.deeply_normalize( - &ObligationCause::dummy_with_span(span), - key.param_env, - Unnormalized::new_wip(key.value.value), + key.value.value, ) .map_err(|_| NoSolution) } @@ -89,14 +49,14 @@ pub trait Normalizable<'tcx>: { fn type_op_method( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Self>>>, ) -> Result, NoSolution>; } impl<'tcx> Normalizable<'tcx> for Ty<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Self>>>, ) -> Result, NoSolution> { tcx.type_op_normalize_ty(canonicalized) } @@ -105,7 +65,7 @@ impl<'tcx> Normalizable<'tcx> for Ty<'tcx> { impl<'tcx> Normalizable<'tcx> for ty::Clause<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Self>>>, ) -> Result, NoSolution> { tcx.type_op_normalize_clause(canonicalized) } @@ -114,7 +74,7 @@ impl<'tcx> Normalizable<'tcx> for ty::Clause<'tcx> { impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Self>>>, ) -> Result, NoSolution> { tcx.type_op_normalize_poly_fn_sig(canonicalized) } @@ -123,7 +83,7 @@ impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> { impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Self>>>, ) -> Result, NoSolution> { tcx.type_op_normalize_fn_sig(canonicalized) } @@ -134,7 +94,7 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> { impl<'tcx> Normalizable<'tcx> for ty::PolyTypeOutlivesPredicate<'tcx> { fn type_op_method( _tcx: TyCtxt<'tcx>, - _canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + _canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Self>>>, ) -> Result, NoSolution> { unreachable!("we never normalize PolyTypeOutlivesPredicate") } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b278c32cb61ae..b2c9e872da7d6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1055,7 +1055,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if upcast_trait_ref.def_id() == target_trait_did && let Ok(nested) = self.match_upcast_principal( obligation, - upcast_trait_ref, + ty::Unnormalized::new_wip(upcast_trait_ref), a_data, b_data, a_region, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 11ce6235eb7ff..1fad988a7f85c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -171,7 +171,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate = candidate_predicate.map_bound(|t| t.trait_ref); - let candidate = self.infcx.instantiate_binder_with_fresh_vars( + let candidate = self.infcx.instantiate_binder_with_fresh_vars_unnormalized( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, candidate, @@ -416,7 +416,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, cause.clone(), obligation.recursion_depth + 1, - assumption, + Unnormalized::new_wip(assumption), &mut obligations, ); self.infcx.register_region_assumption(assumption); @@ -512,7 +512,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let unnormalized_upcast_trait_ref = supertraits.nth(index).expect("supertraits iterator no longer has as many elements"); - let upcast_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( + let upcast_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_unnormalized( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, unnormalized_upcast_trait_ref, @@ -536,10 +536,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check supertraits hold. This is so that their associated type bounds // will be checked in the code below. - for (supertrait, _) in tcx + for supertrait in tcx .explicit_super_predicates_of(trait_predicate.def_id()) .iter_instantiated_copied(tcx, trait_predicate.trait_ref.args) - .map(Unnormalized::skip_norm_wip) + .map(|pred| pred.unzip().0) { let normalized_supertrait = normalize_with_depth_to( self, @@ -581,7 +581,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - bound.instantiate(tcx, trait_predicate.trait_ref.args).skip_norm_wip(), + bound.instantiate(tcx, trait_predicate.trait_ref.args), &mut nested, ); nested.push(obligation.with(tcx, normalized_bound)); @@ -602,7 +602,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); - let sig = self_ty.fn_sig(tcx); + let sig = self_ty.unnormalized_fn_sig(tcx); + let output_ty = sig.map(|sig| self.infcx.enter_forall_and_leak_universe(sig.output())); + let sig = sig.skip_norm_wip(); let trait_ref = closure_trait_ref_and_return_type( tcx, obligation.predicate.def_id(), @@ -617,7 +619,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); // Confirm the `type Output: Sized;` bound that is present on `FnOnce` - let output_ty = self.infcx.enter_forall_and_leak_universe(sig.output()); let output_ty = normalize_with_depth_to( self, obligation.param_env, @@ -975,7 +976,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - (obligation.predicate.trait_ref, found_trait_ref), + Unnormalized::new_wip((obligation.predicate.trait_ref, found_trait_ref)), ) }); @@ -1018,7 +1019,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let source_principal = a_data.principal().unwrap().with_self_ty(tcx, a_ty); let unnormalized_upcast_principal = - util::supertraits(tcx, source_principal).nth(idx).unwrap(); + ty::Unnormalized::new_wip(util::supertraits(tcx, source_principal).nth(idx).unwrap()); let nested = self .match_upcast_principal( @@ -1182,7 +1183,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - tail_field_ty.instantiate(tcx, args_a).skip_norm_wip(), + tail_field_ty.instantiate(tcx, args_a), &mut nested, ); let target_tail = normalize_with_depth_to( @@ -1190,7 +1191,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - tail_field_ty.instantiate(tcx, args_b).skip_norm_wip(), + tail_field_ty.instantiate(tcx, args_b), &mut nested, ); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 73dc9bff6343d..1b49c06fee236 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1080,7 +1080,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - obligation.predicate, + Unnormalized::new_wip(obligation.predicate), &mut nested_obligations, ); if predicate != obligation.predicate { @@ -1716,7 +1716,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let trait_bound = self.infcx.instantiate_binder_with_fresh_vars( + let trait_bound = self.infcx.instantiate_binder_with_fresh_vars_unnormalized( obligation.cause.span, HigherRankedType, trait_bound, @@ -1774,11 +1774,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug_assert_eq!(def_id, env_predicate.item_def_id()); let mut nested_obligations = PredicateObligations::new(); - let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars( + let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars_unnormalized( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, env_predicate, ); + let infer_projection = infer_predicate.map(|predicate| predicate.projection_term); let infer_projection = if potentially_unnormalized_candidates { ensure_sufficient_stack(|| { normalize_with_depth_to( @@ -1786,12 +1787,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - infer_predicate.projection_term, + infer_projection, &mut nested_obligations, ) }) } else { - infer_predicate.projection_term + infer_projection.skip_normalization() }; let is_match = self @@ -2472,7 +2473,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { param_env, cause.clone(), recursion_depth, - placeholder_ty, + Unnormalized::new_wip(placeholder_ty), ) }); @@ -2535,20 +2536,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); - let trait_ref = - impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args).skip_norm_wip(); + let trait_ref = impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args); debug!(?impl_trait_header); - let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } = - ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_ref, - ) - }); + let mut nested_obligations = PredicateObligations::new(); + let impl_trait_ref = ensure_sufficient_stack(|| { + normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + trait_ref, + &mut nested_obligations, + ) + }); debug!(?impl_trait_ref, ?placeholder_obligation_trait_ref); @@ -2580,7 +2581,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn match_upcast_principal( &mut self, obligation: &PolyTraitObligation<'tcx>, - unnormalized_upcast_principal: ty::PolyTraitRef<'tcx>, + unnormalized_upcast_principal: ty::Unnormalized<'tcx, ty::PolyTraitRef<'tcx>>, a_data: &'tcx ty::List>, b_data: &'tcx ty::List>, a_region: ty::Region<'tcx>, @@ -2868,7 +2869,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { param_env, cause.clone(), recursion_depth, - predicate.skip_norm_wip(), + predicate, &mut obligations, ); obligations.push(Obligation { @@ -2881,11 +2882,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Register any outlives obligations from the trait here, cc #124336. if tcx.def_kind(def_id) == (DefKind::Impl { of_trait: true }) { - for clause in tcx - .impl_super_outlives(def_id) - .iter_instantiated(tcx, args) - .map(Unnormalized::skip_norm_wip) - { + for clause in tcx.impl_super_outlives(def_id).iter_instantiated(tcx, args) { let clause = normalize_with_depth_to( self, param_env, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index a47f933f5c25e..a816ae56918c4 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -362,7 +362,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { param_env, cause.clone(), self.recursion_depth, - obligation.predicate, + ty::Unnormalized::new_wip(obligation.predicate), &mut obligations, ); obligation.predicate = normalized_predicate; diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index f77e1994cf472..510226cf141b0 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -38,42 +38,44 @@ fn type_op_ascribe_user_type<'tcx>( fn type_op_normalize<'tcx, T>( ocx: &ObligationCtxt<'_, 'tcx>, - key: ParamEnvAnd<'tcx, Normalize>, + key: ParamEnvAnd<'tcx, Normalize<'tcx, T>>, ) -> Result where T: fmt::Debug + TypeFoldable>, { let ParamEnvAnd { param_env, value: Normalize { value } } = key; - let Normalized { value, obligations } = - ocx.infcx.at(&ObligationCause::dummy(), param_env).query_normalize(value)?; + let Normalized { value, obligations } = ocx + .infcx + .at(&ObligationCause::dummy(), param_env) + .query_normalize(value.skip_normalization())?; ocx.register_obligations(obligations); Ok(value) } fn type_op_normalize_ty<'tcx>( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Ty<'tcx>>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } fn type_op_normalize_clause<'tcx>( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Clause<'tcx>>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Clause<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } fn type_op_normalize_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, FnSig<'tcx>>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } fn type_op_normalize_poly_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, - canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, PolyFnSig<'tcx>>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 31824b61cfb27..5946d1c8d0ada 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -22,7 +22,7 @@ use crate::ty::AliasTy; use crate::visit::TypeVisitable; use crate::{ self as ty, BoundVarIndexKind, FloatTy, FreeAliasTy, InherentAliasTy, IntTy, Interner, - OpaqueAliasTy, ProjectionAliasTy, UintTy, + OpaqueAliasTy, ProjectionAliasTy, UintTy, Unnormalized, }; mod closure; @@ -352,14 +352,16 @@ impl Eq for TyKind {} impl TyKind { pub fn fn_sig(self, interner: I) -> ty::Binder> { + self.unnormalized_fn_sig(interner).skip_normalization() + } + + pub fn unnormalized_fn_sig(self, interner: I) -> Unnormalized>> { match self { - ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), - ty::FnDef(def_id, args) => { - interner.fn_sig(def_id).instantiate(interner, args).skip_norm_wip() - } + ty::FnPtr(sig_tys, hdr) => Unnormalized::new(sig_tys.with(hdr)), + ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args), ty::Error(_) => { // ignore errors (#54954) - ty::Binder::dummy(ty::FnSig::dummy()) + Unnormalized::dummy(ty::Binder::dummy(ty::FnSig::dummy())) } ty::Closure(..) => panic!( "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 9453d30ce91c9..9da8fc7d1ee8f 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -9,7 +9,7 @@ use crate::data_structures::DelayedMap; use crate::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region}; use crate::inherent::*; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::{self as ty, FnSigKind, Interner}; +use crate::{self as ty, FnSigKind, Interner, Unnormalized}; /// A closure can be modeled as a struct that looks like: /// ```ignore (illustrative) @@ -200,8 +200,13 @@ impl ClosureArgs { /// Extracts the signature from the closure. pub fn sig(self) -> ty::Binder> { + self.unnormalized_sig().skip_norm_wip() + } + + /// Extracts the signature from the closure without assuming it has been normalized. + pub fn unnormalized_sig(self) -> Unnormalized>> { match self.sig_as_fn_ptr_ty().kind() { - ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), + ty::FnPtr(sig_tys, hdr) => Unnormalized::new(sig_tys.with(hdr)), ty => panic!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"), } } @@ -294,8 +299,14 @@ impl CoroutineClosureArgs { } pub fn coroutine_closure_sig(self) -> ty::Binder> { + self.unnormalized_coroutine_closure_sig().skip_norm_wip() + } + + pub fn unnormalized_coroutine_closure_sig( + self, + ) -> Unnormalized>> { let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() }; - sig_tys.map_bound(|sig_tys| { + Unnormalized::new(sig_tys.map_bound(|sig_tys| { let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else { panic!(); }; @@ -309,7 +320,7 @@ impl CoroutineClosureArgs { return_ty, fn_sig_kind: hdr.fn_sig_kind, } - }) + })) } pub fn coroutine_captures_by_ref_ty(self) -> I::Ty { @@ -661,7 +672,16 @@ impl CoroutineArgs { /// Returns the "coroutine signature", which consists of its resume, yield /// and return types. pub fn sig(self) -> GenSig { + self.unnormalized_sig().skip_norm_wip() + } + + /// Returns the "coroutine signature" without assuming it has been normalized. + pub fn unnormalized_sig(self) -> Unnormalized> { let parts = self.split(); - GenSig { resume_ty: parts.resume_ty, yield_ty: parts.yield_ty, return_ty: parts.return_ty } + Unnormalized::new(GenSig { + resume_ty: parts.resume_ty, + yield_ty: parts.yield_ty, + return_ty: parts.return_ty, + }) } } diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index 0981a8a7e0e18..a685f32bced2c 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -1,8 +1,11 @@ use std::marker::PhantomData; use derive_where::derive_where; +#[cfg(feature = "nightly")] +use rustc_macros::StableHash_NoContext; use rustc_type_ir_macros::TypeVisitable_Generic; +use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use crate::inherent::*; use crate::upcast::Upcast; use crate::{ @@ -25,7 +28,8 @@ use crate::{ /// e.g., `Unnormalized`. /// /// [here]: https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/Eager.20normalization.2C.20ahoy.21/with/582996293 -#[derive_where(Clone, Copy, PartialOrd, PartialEq, Debug; T)] +#[derive_where(Clone, Copy, PartialOrd, PartialEq, Eq, Hash, Debug; T)] +#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))] #[derive(TypeVisitable_Generic)] pub struct Unnormalized { value: T, @@ -87,6 +91,16 @@ impl Unnormalized { } } +impl> TypeFoldable for Unnormalized { + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(Unnormalized::new(self.value.try_fold_with(folder)?)) + } + + fn fold_with>(self, folder: &mut F) -> Self { + Unnormalized::new(self.value.fold_with(folder)) + } +} + impl Unnormalized { pub fn unzip(self) -> (Unnormalized, Unnormalized) { (Unnormalized::new(self.value.0), Unnormalized::new(self.value.1))