From aa1c8f41e9fdc919abcf77089d350c0d6cbfcc91 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 6 May 2026 10:19:52 +0800 Subject: [PATCH 1/7] convert `replace_bound_vars_uncached` --- compiler/rustc_middle/src/ty/fold.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 3d9148d6ed7ba..56a2bcd10d55b 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -4,7 +4,7 @@ use rustc_type_ir::data_structures::DelayedMap; use crate::ty::{ self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + TypeVisitableExt, Unnormalized, }; /////////////////////////////////////////////////////////////////////////// @@ -265,8 +265,8 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, delegate: impl BoundVarReplacerDelegate<'tcx>, - ) -> T { - self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate) + ) -> Unnormalized<'tcx, T> { + Unnormalized::new(self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate)) } /// Replaces any late-bound regions bound in `value` with From d7064cc5d84926b54311eef4887546537bf072d5 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 6 May 2026 09:36:12 +0800 Subject: [PATCH 2/7] convert `instantiate_binder_with_fresh_vars` --- .../rustc_borrowck/src/diagnostics/mod.rs | 19 ++++++++------ .../src/type_check/input_output.rs | 3 ++- compiler/rustc_borrowck/src/type_check/mod.rs | 3 +++ compiler/rustc_codegen_ssa/src/base.rs | 1 + .../src/check/compare_eii.rs | 1 + .../src/check/compare_impl_item.rs | 5 ++-- compiler/rustc_hir_typeck/src/callee.rs | 6 +++-- compiler/rustc_hir_typeck/src/closure.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 26 ++++++++++++------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 13 ++++++---- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 1 + .../rustc_hir_typeck/src/method/confirm.rs | 9 +++++-- compiler/rustc_hir_typeck/src/method/mod.rs | 1 + compiler/rustc_hir_typeck/src/method/probe.rs | 4 +++ .../rustc_hir_typeck/src/method/suggest.rs | 2 ++ compiler/rustc_infer/src/infer/context.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 7 ++--- .../src/infer/relate/type_relating.rs | 4 +++ .../src/error_reporting/traits/ambiguity.rs | 2 +- .../traits/fulfillment_errors.rs | 4 +++ .../src/error_reporting/traits/suggestions.rs | 4 +++ .../src/traits/effects.rs | 13 ++++++---- .../src/traits/project.rs | 1 + .../src/traits/select/confirmation.rs | 4 +++ .../src/traits/select/mod.rs | 7 +++++ 25 files changed, 103 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 9245e5f05f4c1..6925fb7dc1cb3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1460,14 +1460,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let ty::Adt(def, args) = ty.peel_refs().kind() && tcx.is_lang_item(def.did(), LangItem::Pin) && let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind() - && let self_ty = self.infcx.instantiate_binder_with_fresh_vars( - fn_call_span, - BoundRegionConversionTime::FnCall, - tcx.fn_sig(method_did) - .instantiate(tcx, method_args) - .skip_norm_wip() - .input(0), - ) + && let self_ty = self + .infcx + .instantiate_binder_with_fresh_vars( + fn_call_span, + BoundRegionConversionTime::FnCall, + tcx.fn_sig(method_did) + .instantiate(tcx, method_args) + .skip_norm_wip() + .input(0), + ) + .skip_norm_wip() && self.infcx.can_eq(self.infcx.param_env, ty, self_ty) { err.subdiagnostic(CaptureReasonSuggest::FreshReborrow { diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 64c5f5f0c560b..6e31a60aba89d 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -48,11 +48,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Then replace the bound items in the fn sig with fresh variables, // so that they represent the view from "inside" the closure. let user_provided_sig = self.instantiate_canonical(self.body.span, &user_provided_poly_sig); - let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( + let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( self.body.span, BoundRegionConversionTime::FnCall, user_provided_sig, ); + let mut user_provided_sig = user_provided_sig.skip_norm_wip(); // FIXME(async_closures): It's kind of wacky that we must apply this // transformation here, since we do the same thing in HIR typeck. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8998ced10bf9e..9a03aa6700ce6 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1052,6 +1052,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { BoundRegionConversionTime::HigherRankedType, src_sig, ); + let src_sig = src_sig.skip_norm_wip(); let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig)); self.prove_predicate( ty::ClauseKind::WellFormed(src_ty.into()), @@ -1642,6 +1643,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { BoundRegionConversionTime::HigherRankedType, binder_ty.into(), ); + let expected_ty = expected_ty.skip_norm_wip(); self.sub_types( operand_ty, expected_ty, @@ -1883,6 +1885,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { BoundRegionConversionTime::HigherRankedType, binder_ty.into(), ); + let found_ty = found_ty.skip_norm_wip(); self.relate_types( ty, context.ambient_variance(), diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 4e2884c8cb63f..916eb58fbcdc2 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -132,6 +132,7 @@ pub fn validate_trivial_unsize<'tcx>( BoundRegionConversionTime::HigherRankedType, hr_source_principal, ); + let source_principal = source_principal.skip_norm_wip(); let Ok(()) = ocx.eq( &ObligationCause::dummy(), param_env, diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index 1bcdfd9f25a5b..7099cf94ce0a4 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -82,6 +82,7 @@ pub(crate) fn compare_eii_function_types<'tcx>( ) .skip_norm_wip(), ); + let unnormalized_external_impl_sig = unnormalized_external_impl_sig.skip_norm_wip(); let external_impl_sig = ocx.normalize( &norm_cause, param_env, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 234231ed37fed..e913adf9e5dcd 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -331,6 +331,7 @@ fn compare_method_predicate_entailment<'tcx>( BoundRegionConversionTime::HigherRankedType, tcx.fn_sig(impl_m.def_id).instantiate_identity().skip_norm_wip(), ); + let unnormalized_impl_sig = unnormalized_impl_sig.skip_norm_wip(); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id); let impl_sig = @@ -537,11 +538,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_sig = ocx.normalize( &misc_cause, param_env, - Unnormalized::new_wip(infcx.instantiate_binder_with_fresh_vars( + infcx.instantiate_binder_with_fresh_vars( return_span, BoundRegionConversionTime::HigherRankedType, tcx.fn_sig(impl_m.def_id).instantiate_identity().skip_norm_wip(), - )), + ), ); impl_sig.error_reported()?; let impl_return_ty = impl_sig.output(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 9730e08c90c37..039df05fee5bc 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -12,7 +12,7 @@ use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; -use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, Unnormalized}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, sym}; @@ -232,6 +232,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, closure_sig, ); + let closure_sig = closure_sig.skip_norm_wip(); let adjustments = self.adjust_steps(autoderef); self.record_deferred_call_resolution( def_id, @@ -259,6 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, closure_args.coroutine_closure_sig(), ); + let coroutine_closure_sig = coroutine_closure_sig.skip_norm_wip(); let tupled_upvars_ty = self.next_ty_var(callee_expr.span); // We may actually receive a coroutine back whose kind is different // from the closure that this dispatched from. This is because when @@ -584,7 +586,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, fn_sig, ); - let fn_sig = self.normalize(call_expr.span, Unnormalized::new_wip(fn_sig)); + let fn_sig = self.normalize(call_expr.span, fn_sig); self.check_argument_types( call_expr.span, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 763d2a27e6cc0..7527a2a215948 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -828,6 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, supplied_sig, ); + let supplied_sig = supplied_sig.skip_norm_wip(); // The liberated version of this signature should be a subtype // of the liberated form of the expectation. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index fd9c1bc8780ee..53eedd363bc4c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -652,6 +652,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::FnCall, fn_sig.input(i), ); + let input = input.skip_norm_wip(); self.require_type_is_sized_deferred( input, span, @@ -669,6 +670,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::FnCall, fn_sig.output(), ); + let output = output.skip_norm_wip(); self.require_type_is_sized_deferred( output, call_expr_and_args.map_or(expr.span, |(e, _)| e.span), @@ -1571,11 +1573,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty); let hint_ty = match *binder_ty.kind() { - ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars( - inner_expr.span, - infer::BoundRegionConversionTime::HigherRankedType, - binder.into(), - ), + ty::UnsafeBinder(binder) => self + .instantiate_binder_with_fresh_vars( + inner_expr.span, + infer::BoundRegionConversionTime::HigherRankedType, + binder.into(), + ) + .skip_norm_wip(), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { let guar = self @@ -1608,11 +1612,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // if it's not an unsafe binder. let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty); match *binder_ty.kind() { - ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars( - inner_expr.span, - infer::BoundRegionConversionTime::HigherRankedType, - binder.into(), - ), + ty::UnsafeBinder(binder) => self + .instantiate_binder_with_fresh_vars( + inner_expr.span, + infer::BoundRegionConversionTime::HigherRankedType, + binder.into(), + ) + .skip_norm_wip(), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { let guar = self diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 415630dab38b3..b3f8ec8580134 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -3034,11 +3034,14 @@ impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> { .instantiate(self.call_ctxt.fn_ctxt.tcx, args) .skip_norm_wip(); - self.call_ctxt.fn_ctxt.instantiate_binder_with_fresh_vars( - call_name.span, - BoundRegionConversionTime::FnCall, - fn_sig, - ); + self.call_ctxt + .fn_ctxt + .instantiate_binder_with_fresh_vars( + call_name.span, + BoundRegionConversionTime::FnCall, + fn_sig, + ) + .skip_norm_wip(); } None } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 63bd49f080309..e6908b8eb28e0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -392,6 +392,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id), poly_trait_ref, ); + let trait_ref = trait_ref.skip_norm_wip(); let item_args = self.lowerer().lower_generic_args_of_assoc_item( span, diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 0c83c1948d6f2..ba179c18224f3 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -325,6 +325,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id); let upcast_trait_ref = this.instantiate_binder_with_fresh_vars(upcast_poly_trait_ref); + let upcast_trait_ref = upcast_trait_ref.skip_norm_wip(); debug!( "original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}", original_poly_trait_ref, upcast_trait_ref, trait_def_id @@ -347,7 +348,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { probe::WhereClausePick(poly_trait_ref) => { // Where clauses can have bound regions in them. We need to instantiate // those to convert from a poly-trait-ref to a trait-ref. - self.instantiate_binder_with_fresh_vars(poly_trait_ref).args + self.instantiate_binder_with_fresh_vars(poly_trait_ref).skip_norm_wip().args } } } @@ -597,6 +598,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { debug!("type scheme instantiated, sig={:?}", sig); let sig = self.instantiate_binder_with_fresh_vars(sig); + let sig = sig.skip_norm_wip(); debug!("late-bound lifetimes from method instantiated, sig={:?}", sig); (sig, method_predicates) @@ -788,7 +790,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } } - fn instantiate_binder_with_fresh_vars(&self, value: ty::Binder<'tcx, T>) -> T + fn instantiate_binder_with_fresh_vars( + &self, + value: ty::Binder<'tcx, T>, + ) -> Unnormalized<'tcx, T> where T: TypeFoldable> + Copy, { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 49126ff0e964c..c3e72a9fe0bc8 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -427,6 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, fn_sig, ); + let fn_sig = fn_sig.skip_norm_wip(); let InferOk { value: fn_sig, obligations: o } = self.at(&obligation.cause, self.param_env).normalize(Unnormalized::new_wip(fn_sig)); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 4258896deec70..2272ee437098f 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1080,6 +1080,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { BoundRegionConversionTime::FnCall, fty, ); + let fty = fty.skip_norm_wip(); self.can_eq(self.param_env, fty.output(), expected) }), _ => false, @@ -1906,6 +1907,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { BoundRegionConversionTime::FnCall, trait_ref, ); + let trait_ref = trait_ref.skip_norm_wip(); let (xform_self_ty, _) = self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args); // Guide the trait selection to show impls that have methods whose type matches @@ -2040,6 +2042,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { BoundRegionConversionTime::FnCall, poly_trait_ref, ); + let trait_ref = trait_ref.skip_norm_wip(); let trait_ref = ocx.normalize(cause, self.param_env, Unnormalized::new_wip(trait_ref)); (xform_self_ty, xform_ret_ty) = @@ -2105,6 +2108,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { BoundRegionConversionTime::FnCall, poly_trait_ref, ); + let trait_ref = trait_ref.skip_norm_wip(); (xform_self_ty, xform_ret_ty) = self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index d773420512590..240b0b6191dd9 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2292,6 +2292,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, fn_sig, ); + let fn_sig = fn_sig.skip_norm_wip(); if similar_candidate.is_method() { if let Some(args) = args && fn_sig.inputs()[1..].len() == args.len() @@ -2379,6 +2380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, fn_sig, ); + let fn_sig = fn_sig.skip_norm_wip(); let name = inherent_method.name(); let inputs = fn_sig.inputs(); let expected_inputs = diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 74da4d4c6db8b..a21fa86c8ee34 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -169,6 +169,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { BoundRegionConversionTime::HigherRankedType, value, ) + .skip_norm_wip() } fn enter_forall>, U>( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 05043f8617a92..ccb0796066c46 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -31,7 +31,8 @@ use rustc_middle::ty::{ self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueTypeKey, ProvisionalHiddenType, PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, + TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, Unnormalized, + fold_regions, }; use rustc_span::{DUMMY_SP, Span, Symbol}; use snapshot::undo_log::InferCtxtUndoLogs; @@ -1310,12 +1311,12 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, - ) -> T + ) -> Unnormalized<'tcx, T> where T: TypeFoldable> + Copy, { if let Some(inner) = value.no_bound_vars() { - return inner; + return Unnormalized::new(inner); } let bound_vars = value.bound_vars(); diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 595392fcfb524..ada4f3bc665eb 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -301,12 +301,14 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { ty::Covariant => { infcx.enter_forall(b, |b| { let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); + let a = a.skip_norm_wip(); self.relate(a, b) })?; } ty::Contravariant => { infcx.enter_forall(a, |a| { let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); + let b = b.skip_norm_wip(); self.relate(a, b) })?; } @@ -324,12 +326,14 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { ty::Invariant => { infcx.enter_forall(b, |b| { let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); + let a = a.skip_norm_wip(); self.relate(a, b) })?; // Check if `exists<..> B == for<..> A`. infcx.enter_forall(a, |a| { let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); + let b = b.skip_norm_wip(); self.relate(a, b) })?; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 108262d507ef7..9088e614a87ae 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -113,7 +113,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( let param_env_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, - Unnormalized::new_wip(param_env_predicate.trait_ref), + param_env_predicate.map(|pred| pred.trait_ref), ); if let Err(_) = ocx.eq( diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 785118bc6d7eb..a6ad706502125 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1435,6 +1435,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::HigherRankedType, assumption, ); + let trait_assumption = trait_assumption.skip_norm_wip(); self.can_eq(param_env, goal.trait_ref, trait_assumption.trait_ref) } @@ -1450,6 +1451,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::HigherRankedType, assumption, ); + let assumption = assumption.skip_norm_wip(); assumption.constness.satisfies(goal.constness) && self.can_eq(param_env, goal.trait_ref, assumption.trait_ref) @@ -1475,6 +1477,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::HigherRankedType, assumption, ); + let assumption = assumption.skip_norm_wip(); self.can_eq(param_env, goal.projection_term, assumption.projection_term) && self.can_eq(param_env, goal.term, assumption.term) @@ -1550,6 +1553,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); + let data = data.skip_norm_wip(); let unnormalized_term = data.projection_term.to_term(self.tcx); // FIXME(-Znext-solver): For diagnostic purposes, it would be nice // to deeply normalize this type. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 148f1471b1b66..ed543994f2306 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1019,6 +1019,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, trait_pred.self_ty(), ); + let self_ty = self_ty.skip_norm_wip(); let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(obligation.cause.body_id, obligation.param_env, self_ty) @@ -1563,6 +1564,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, output, ); + let output = output.skip_norm_wip(); let inputs = inputs .skip_binder() .iter() @@ -1572,6 +1574,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, inputs.rebind(*ty), ) + .skip_norm_wip() }) .collect(); @@ -4860,6 +4863,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, failed_pred, ); + let failed_pred = failed_pred.skip_norm_wip(); let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 0f36edcdd830e..e9c736967991a 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -89,11 +89,14 @@ fn match_candidate<'tcx>( return Err(NoSolution); } - let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars( - obligation.cause.span, - BoundRegionConversionTime::HigherRankedType, - candidate, - ); + let mut candidate = selcx + .infcx + .instantiate_binder_with_fresh_vars( + obligation.cause.span, + BoundRegionConversionTime::HigherRankedType, + candidate, + ) + .skip_norm_wip(); let mut nested = thin_vec![]; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5423e394119c4..a46bbf0568640 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1914,6 +1914,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( BoundRegionConversionTime::HigherRankedType, poly_cache_entry, ); + let cache_entry = cache_entry.skip_norm_wip(); let cache_projection = cache_entry.projection_term; let mut nested_obligations = PredicateObligations::new(); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 11ce6235eb7ff..5cff215c212c0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -176,6 +176,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BoundRegionConversionTime::HigherRankedType, candidate, ); + let candidate = candidate.skip_norm_wip(); let mut obligations = PredicateObligations::new(); let candidate = normalize_with_depth_to( self, @@ -504,6 +505,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BoundRegionConversionTime::HigherRankedType, object_trait_ref, ); + let object_trait_ref = object_trait_ref.skip_norm_wip(); let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty); let mut nested = PredicateObligations::new(); @@ -517,6 +519,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BoundRegionConversionTime::HigherRankedType, unnormalized_upcast_trait_ref, ); + let upcast_trait_ref = upcast_trait_ref.skip_norm_wip(); let upcast_trait_ref = normalize_with_depth_to( self, obligation.param_env, @@ -967,6 +970,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BoundRegionConversionTime::HigherRankedType, found_trait_ref, ); + let found_trait_ref = found_trait_ref.skip_norm_wip(); // Normalize the obligation and expected trait refs together, because why not let Normalized { obligations: nested, value: (obligation_trait_ref, found_trait_ref) } = ensure_sufficient_stack(|| { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9eca0f31a4402..380927dd50e9d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1720,6 +1720,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { HigherRankedType, trait_bound, ); + let trait_bound = trait_bound.skip_norm_wip(); let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| { normalize_with_depth( self, @@ -1777,6 +1778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BoundRegionConversionTime::HigherRankedType, env_predicate, ); + let infer_predicate = infer_predicate.skip_norm_wip(); let infer_projection = if potentially_unnormalized_candidates { ensure_sufficient_stack(|| { normalize_with_depth_to( @@ -2623,6 +2625,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { HigherRankedType, hr_source_principal, ); + let source_principal = source_principal.skip_norm_wip(); self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( DefineOpaqueTypes::Yes, ToTrace::to_trace( @@ -2660,6 +2663,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { HigherRankedType, hr_source_projection, ); + let source_projection = + source_projection.skip_norm_wip(); self.infcx .at(&obligation.cause, obligation.param_env) .eq_trace( @@ -2692,6 +2697,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { HigherRankedType, hr_source_projection, ); + let source_projection = source_projection.skip_norm_wip(); self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( DefineOpaqueTypes::Yes, ToTrace::to_trace( @@ -2752,6 +2758,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { HigherRankedType, poly_trait_ref, ); + let trait_ref = trait_ref.skip_norm_wip(); self.infcx .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::No, predicate.trait_ref, trait_ref) From b5129447bf2681b4d1ed71818e303eac41b1703b Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 6 May 2026 09:40:38 +0800 Subject: [PATCH 3/7] convert `instantiate_binder_with_infer` --- compiler/rustc_infer/src/infer/context.rs | 3 +-- .../src/solve/assembly/structural_traits.rs | 7 ++++--- .../src/solve/effect_goals.rs | 4 ++-- .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/solve/normalizes_to/mod.rs | 10 ++++++--- .../src/solve/trait_goals.rs | 21 ++++++++++++------- compiler/rustc_type_ir/src/infer_ctxt.rs | 2 +- .../src/relate/solver_relating.rs | 8 +++---- 8 files changed, 33 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index a21fa86c8ee34..a769e49c610ab 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -163,13 +163,12 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn instantiate_binder_with_infer> + Copy>( &self, value: ty::Binder<'tcx, T>, - ) -> T { + ) -> ty::Unnormalized<'tcx, T> { self.instantiate_binder_with_fresh_vars( DUMMY_SP, BoundRegionConversionTime::HigherRankedType, value, ) - .skip_norm_wip() } fn enter_forall>, U>( diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 0bbc6f483104f..e9e42a4ad75e5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -879,7 +879,7 @@ where I: Interner, { let cx = ecx.cx(); - let trait_ref = ecx.instantiate_binder_with_infer(trait_ref); + let trait_ref = ecx.instantiate_binder_with_infer(trait_ref).skip_norm_wip(); let mut requirements = vec![]; // Elaborating all supertrait outlives obligations here is not soundness critical, // since if we just used the unelaborated set, then the transitive supertraits would @@ -963,7 +963,8 @@ where .ecx .probe(|_| ProbeKind::ProjectionCompatibility) .enter_without_propagated_nested_goals(|ecx| -> Result<_, NoSolution> { - let source_projection = ecx.instantiate_binder_with_infer(source_projection); + let source_projection = + ecx.instantiate_binder_with_infer(source_projection).skip_norm_wip(); ecx.eq(self.param_env, source_projection.projection_term, target_projection)?; ecx.try_evaluate_added_goals() }) @@ -1004,7 +1005,7 @@ where return Err(Ambiguous); } - let replacement = self.ecx.instantiate_binder_with_infer(*replacement); + let replacement = self.ecx.instantiate_binder_with_infer(*replacement).skip_norm_wip(); self.nested.extend( self.ecx .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term) diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index aa49997253dc2..2811de013494f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -64,7 +64,7 @@ where ) -> QueryResult { let host_clause = assumption.as_host_effect_clause().unwrap(); - let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); + let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause).skip_norm_wip(); ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; then(ecx) @@ -293,7 +293,7 @@ where let self_ty = goal.predicate.self_ty(); let (inputs_and_output, def_id, args) = structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?; - let (inputs, output) = ecx.instantiate_binder_with_infer(inputs_and_output); + let (inputs, output) = ecx.instantiate_binder_with_infer(inputs_and_output).skip_norm_wip(); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 615cc9e8f81d2..3dfd4447aee99 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1074,7 +1074,7 @@ where pub(super) fn instantiate_binder_with_infer + Copy>( &self, value: ty::Binder, - ) -> T { + ) -> ty::Unnormalized { self.delegate.instantiate_binder_with_infer(value) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index d93b7843b2251..7050612130e78 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -168,7 +168,8 @@ where ) -> QueryResult { let cx = ecx.cx(); let projection_pred = assumption.as_projection_clause().unwrap(); - let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); + let assumption_projection_pred = + ecx.instantiate_binder_with_infer(projection_pred).skip_norm_wip(); ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); @@ -461,7 +462,8 @@ where else { return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS); }; - let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output); + let (inputs, output) = + ecx.instantiate_binder_with_infer(tupled_inputs_and_output).skip_norm_wip(); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -510,7 +512,9 @@ where tupled_inputs_ty, output_coroutine_ty, coroutine_return_ty, - } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine); + } = ecx + .instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine) + .skip_norm_wip(); // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index b97d895bec15f..54c03feac9b27 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -192,7 +192,7 @@ where return Self::match_assumption(ecx, goal, meta_sized_clause, then); } - let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); + let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause).skip_norm_wip(); ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; then(ecx) @@ -376,7 +376,8 @@ where else { return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS); }; - let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output); + let (inputs, output) = + ecx.instantiate_binder_with_infer(tupled_inputs_and_output).skip_norm_wip(); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -417,7 +418,9 @@ where tupled_inputs_ty, output_coroutine_ty, coroutine_return_ty: _, - } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine); + } = ecx + .instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine) + .skip_norm_wip(); // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -1066,8 +1069,9 @@ where .probe(|_| ProbeKind::ProjectionCompatibility) .enter(|ecx| -> Result<_, NoSolution> { ecx.enter_forall(target_projection, |ecx, target_projection| { - let source_projection = - ecx.instantiate_binder_with_infer(source_projection); + let source_projection = ecx + .instantiate_binder_with_infer(source_projection) + .skip_norm_wip(); ecx.eq(param_env, source_projection, target_projection)?; ecx.try_evaluate_added_goals() }) @@ -1085,7 +1089,7 @@ where let target_principal = bound.rebind(target_principal); ecx.enter_forall(target_principal, |ecx, target_principal| { let source_principal = - ecx.instantiate_binder_with_infer(source_principal); + ecx.instantiate_binder_with_infer(source_principal).skip_norm_wip(); ecx.eq(param_env, source_principal, target_principal)?; ecx.try_evaluate_added_goals() })?; @@ -1110,8 +1114,9 @@ where ); } ecx.enter_forall(target_projection, |ecx, target_projection| { - let source_projection = - ecx.instantiate_binder_with_infer(source_projection); + let source_projection = ecx + .instantiate_binder_with_infer(source_projection) + .skip_norm_wip(); ecx.eq(param_env, source_projection, target_projection)?; ecx.try_evaluate_added_goals() })?; diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 1b6bdf8c34dd8..4d861bb1ad9d8 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -271,7 +271,7 @@ pub trait InferCtxtLike: Sized { fn instantiate_binder_with_infer + Copy>( &self, value: ty::Binder, - ) -> T; + ) -> ty::Unnormalized; fn enter_forall, U>( &self, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index a643d22c17643..c4dd52739d751 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -312,13 +312,13 @@ where // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html ty::Covariant => { self.infcx.enter_forall(b, |b| { - let a = self.infcx.instantiate_binder_with_infer(a); + let a = self.infcx.instantiate_binder_with_infer(a).skip_norm_wip(); self.relate(a, b) })?; } ty::Contravariant => { self.infcx.enter_forall(a, |a| { - let b = self.infcx.instantiate_binder_with_infer(b); + let b = self.infcx.instantiate_binder_with_infer(b).skip_norm_wip(); self.relate(a, b) })?; } @@ -335,13 +335,13 @@ where // Check if `exists<..> A == for<..> B` ty::Invariant => { self.infcx.enter_forall(b, |b| { - let a = self.infcx.instantiate_binder_with_infer(a); + let a = self.infcx.instantiate_binder_with_infer(a).skip_norm_wip(); self.relate(a, b) })?; // Check if `exists<..> B == for<..> A`. self.infcx.enter_forall(a, |a| { - let b = self.infcx.instantiate_binder_with_infer(b); + let b = self.infcx.instantiate_binder_with_infer(b).skip_norm_wip(); self.relate(a, b) })?; } From d1139393fe88b3cc1f077c1e783a2abe79e5fe99 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 6 May 2026 10:16:04 +0800 Subject: [PATCH 4/7] convert `instantiate_binder_with_existentials` --- .../rustc_borrowck/src/type_check/relate_tys.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index f18884df0b44d..48fcb13066eb2 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -211,12 +211,15 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn instantiate_binder_with_existentials(&mut self, binder: ty::Binder<'tcx, T>) -> T + fn instantiate_binder_with_existentials( + &mut self, + binder: ty::Binder<'tcx, T>, + ) -> ty::Unnormalized<'tcx, T> where T: ty::TypeFoldable> + Copy, { if let Some(inner) = binder.no_bound_vars() { - return inner; + return ty::Unnormalized::new(inner); } let infcx = self.type_checker.infcx; @@ -499,7 +502,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(b, |this, b| { - let a = this.instantiate_binder_with_existentials(a); + let a = this.instantiate_binder_with_existentials(a).skip_norm_wip(); this.relate(a, b) })?; } @@ -514,7 +517,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(a, |this, a| { - let b = this.instantiate_binder_with_existentials(b); + let b = this.instantiate_binder_with_existentials(b).skip_norm_wip(); this.relate(a, b) })?; } @@ -529,13 +532,13 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(b, |this, b| { - let a = this.instantiate_binder_with_existentials(a); + let a = this.instantiate_binder_with_existentials(a).skip_norm_wip(); this.relate(a, b) })?; // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(a, |this, a| { - let b = this.instantiate_binder_with_existentials(b); + let b = this.instantiate_binder_with_existentials(b).skip_norm_wip(); this.relate(a, b) })?; } From 2b2cfac093e5ee6cbc624a1b8d59ac14e3da3ece Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 6 May 2026 09:47:53 +0800 Subject: [PATCH 5/7] convert `enter_forall_leaked` --- .../src/infer/relate/higher_ranked.rs | 9 ++-- .../traits/fulfillment_errors.rs | 8 +-- .../src/solve/fulfill/derive_errors.rs | 16 +++--- .../src/traits/coherence.rs | 3 +- .../src/traits/fulfill.rs | 2 +- .../src/traits/project.rs | 3 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 53 ++++++++++++------- .../src/traits/select/mod.rs | 5 +- 9 files changed, 65 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 324725a079bbe..f1ba1fee34cea 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -21,13 +21,16 @@ impl<'tcx> InferCtxt<'tcx> { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[instrument(level = "debug", skip(self), ret)] - pub fn enter_forall_and_leak_universe(&self, binder: ty::Binder<'tcx, T>) -> T + pub fn enter_forall_and_leak_universe( + &self, + binder: ty::Binder<'tcx, T>, + ) -> ty::Unnormalized<'tcx, T> where T: TypeFoldable>, { // Inlined `no_bound_vars`. if !binder.as_ref().skip_binder().has_escaping_bound_vars() { - return binder.skip_binder(); + return ty::Unnormalized::new(binder.skip_binder()); } let next_universe = self.create_next_universe(); @@ -71,7 +74,7 @@ impl<'tcx> InferCtxt<'tcx> { // used after exiting `f`. For example region subtyping can result in outlives constraints // that name placeholders created in this function. Nested goals from type relations can // also contain placeholders created by this function. - let value = self.enter_forall_and_leak_universe(forall); + let value = self.enter_forall_and_leak_universe(forall).skip_norm_wip(); debug!(?value); f(value) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index a6ad706502125..823fa794c4daa 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1690,9 +1690,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; }; - let trait_ref = self.enter_forall_and_leak_universe( - predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)), - ); + let trait_ref = self + .enter_forall_and_leak_universe( + predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)), + ) + .skip_norm_wip(); let Ok(Some(ImplSource::UserDefined(impl_data))) = SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref)) else { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 12dfe730aa303..4d6bf5b317c44 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -59,16 +59,20 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) } ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.enter_forall_and_leak_universe( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); + let (a, b) = infcx + .enter_forall_and_leak_universe( + obligation.predicate.kind().rebind((pred.a, pred.b)), + ) + .skip_norm_wip(); let expected_found = ExpectedFound::new(a, b); FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) } ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.enter_forall_and_leak_universe( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); + let (a, b) = infcx + .enter_forall_and_leak_universe( + obligation.predicate.kind().rebind((pred.a, pred.b)), + ) + .skip_norm_wip(); let expected_found = ExpectedFound::new(b, a); FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 49cc2833cd978..2b321c16c8fe0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -748,7 +748,8 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { // For bound predicates we simply call `infcx.enter_forall` // and then prove the resulting predicate as a nested goal. let Goal { param_env, predicate } = goal.goal(); - let predicate_kind = goal.infcx().enter_forall_and_leak_universe(predicate.kind()); + let predicate_kind = + goal.infcx().enter_forall_and_leak_universe(predicate.kind()).skip_norm_wip(); let trait_ref = match predicate_kind { ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref, ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 0b1d4a8453d05..a839141ca1a5a 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -444,7 +444,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // pred instead of just instantiating it with placeholders b/c of // higher-ranked implied bound issues in the old solver. | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => { - let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder)); + let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder).skip_norm_wip()); let mut obligations = PredicateObligations::with_capacity(1); obligations.push(obligation.with(infcx.tcx, pred)); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a46bbf0568640..379dd2faf0739 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -178,7 +178,8 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>( ) -> ProjectAndUnifyResult<'tcx> { let infcx = selcx.infcx; let r = infcx.commit_if_ok(|_snapshot| { - let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); match project_and_unify_term(selcx, &placeholder_obligation) { 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 f7614e7c9730a..0e543f5737889 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -207,7 +207,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|_| { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = - self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); + self.infcx.enter_forall_and_leak_universe(poly_trait_predicate).skip_norm_wip(); // The bounds returned by `item_bounds` may contain duplicates after // normalization, so try to deduplicate when possible to avoid diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 5cff215c212c0..c985514bedd75 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -146,8 +146,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, idx: usize, ) -> Result, SelectionError<'tcx>> { - let placeholder_trait_predicate = - self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref; + let placeholder_trait_predicate = self + .infcx + .enter_forall_and_leak_universe(obligation.predicate) + .skip_norm_wip() + .trait_ref; let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty()); let candidate_predicate = self .for_each_item_bound( @@ -237,7 +240,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let trait_def = obligation.predicate.def_id(); let self_ty = self.infcx.shallow_resolve( - self.infcx.enter_forall_and_leak_universe(obligation.predicate.self_ty()), + self.infcx + .enter_forall_and_leak_universe(obligation.predicate.self_ty()) + .skip_norm_wip(), ); let types = match tcx.as_lang_item(trait_def) { Some(LangItem::Sized) => self.sizedness_conditions(self_ty, SizedTraitKind::Sized), @@ -268,7 +273,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => ty::Binder::dummy(vec![]), other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"), }; - let types = self.infcx.enter_forall_and_leak_universe(types); + let types = self.infcx.enter_forall_and_leak_universe(types).skip_norm_wip(); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); self.collect_predicates_for_types( @@ -349,7 +354,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let mut assume = predicate.trait_ref.args.const_at(2); if self.tcx().features().generic_const_exprs() { @@ -390,10 +396,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty)); - let self_ty = self.infcx.enter_forall_and_leak_universe(self_ty); + let self_ty = self.infcx.enter_forall_and_leak_universe(self_ty).skip_norm_wip(); let constituents = self.constituent_types_for_auto_trait(self_ty)?; - let constituents = self.infcx.enter_forall_and_leak_universe(constituents); + let constituents = + self.infcx.enter_forall_and_leak_universe(constituents).skip_norm_wip(); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); let mut obligations = self.collect_predicates_for_types( @@ -491,7 +498,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); debug!(?obligation, ?index, "confirm_object_candidate"); - let trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let trait_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty()); let ty::Dynamic(data, ..) = *self_ty.kind() else { span_bug!(obligation.cause.span, "object candidate with non-object"); @@ -601,7 +609,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); - let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); @@ -620,7 +629,7 @@ 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 = self.infcx.enter_forall_and_leak_universe(sig.output()).skip_norm_wip(); let output_ty = normalize_with_depth_to( self, obligation.param_env, @@ -645,7 +654,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> PredicateObligations<'tcx> { debug!(?obligation, "confirm_trait_alias_candidate"); - let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let args = trait_ref.args; @@ -668,7 +678,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { - let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); @@ -698,7 +709,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { - let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); @@ -728,7 +740,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { - let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); @@ -758,7 +771,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { - let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { bug!("closure candidate for non-closure {:?}", obligation); @@ -789,7 +803,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { - let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let trait_ref = match *self_ty.kind() { @@ -818,7 +833,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { - let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let placeholder_predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); @@ -884,7 +900,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We must additionally check that the return type impls `Future + Sized`. let future_trait_def_id = tcx.require_lang_item(LangItem::Future, obligation.cause.span); - let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output()); + let placeholder_output_ty = + self.infcx.enter_forall_and_leak_universe(sig.output()).skip_norm_wip(); nested.push(obligation.with( tcx, ty::TraitRef::new(tcx, future_trait_def_id, [placeholder_output_ty]), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 380927dd50e9d..a8dd5ce716bb2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2527,7 +2527,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation: &PolyTraitObligation<'tcx>, ) -> Result>, ()> { let placeholder_obligation = - self.infcx.enter_forall_and_leak_universe(obligation.predicate); + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); @@ -2752,7 +2752,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation: &PolyTraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result, ()> { - let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).skip_norm_wip(); let trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, HigherRankedType, From a2272710742241fe19a478e347e85100d6483bbf Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 6 May 2026 09:52:32 +0800 Subject: [PATCH 6/7] convert `enter_forall` --- compiler/rustc_borrowck/src/type_check/relate_tys.rs | 4 ++-- compiler/rustc_infer/src/infer/context.rs | 2 +- compiler/rustc_infer/src/infer/relate/higher_ranked.rs | 8 ++++++-- .../rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs | 2 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 48fcb13066eb2..3c6527fb316f2 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -167,13 +167,13 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { fn enter_forall( &mut self, binder: ty::Binder<'tcx, T>, - f: impl FnOnce(&mut Self, T) -> U, + f: impl FnOnce(&mut Self, ty::Unnormalized<'tcx, T>) -> U, ) -> U where T: ty::TypeFoldable> + Copy, { let value = if let Some(inner) = binder.no_bound_vars() { - inner + ty::Unnormalized::new(inner) } else { let infcx = self.type_checker.infcx; let mut lazy_universe = None; diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index a769e49c610ab..0555ae19ed95d 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -174,7 +174,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn enter_forall>, U>( &self, value: ty::Binder<'tcx, T>, - f: impl FnOnce(T) -> U, + f: impl FnOnce(ty::Unnormalized<'tcx, T>) -> U, ) -> U { self.enter_forall(value, f) } diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index f1ba1fee34cea..e0f5d004cb8e1 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -66,7 +66,11 @@ impl<'tcx> InferCtxt<'tcx> { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[instrument(level = "debug", skip(self, f))] - pub fn enter_forall(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U + pub fn enter_forall( + &self, + forall: ty::Binder<'tcx, T>, + f: impl FnOnce(ty::Unnormalized<'tcx, T>) -> U, + ) -> U where T: TypeFoldable>, { @@ -74,7 +78,7 @@ impl<'tcx> InferCtxt<'tcx> { // used after exiting `f`. For example region subtyping can result in outlives constraints // that name placeholders created in this function. Nested goals from type relations can // also contain placeholders created by this function. - let value = self.enter_forall_and_leak_universe(forall).skip_norm_wip(); + let value = self.enter_forall_and_leak_universe(forall); debug!(?value); f(value) } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 3dfd4447aee99..5425d62b36b41 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1083,7 +1083,7 @@ where pub(super) fn enter_forall, U>( &mut self, value: ty::Binder, - f: impl FnOnce(&mut Self, T) -> U, + f: impl FnOnce(&mut Self, ty::Unnormalized) -> U, ) -> U { self.delegate.enter_forall(value, |value| f(self, value)) } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 4d861bb1ad9d8..758a95124b625 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -276,7 +276,7 @@ pub trait InferCtxtLike: Sized { fn enter_forall, U>( &self, value: ty::Binder, - f: impl FnOnce(T) -> U, + f: impl FnOnce(ty::Unnormalized) -> U, ) -> U; fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); From c2ef1851e133dc38917ce0f33e12ec986c498a7f Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 6 May 2026 10:12:56 +0800 Subject: [PATCH 7/7] convert use sites of `enter_forall` --- .../src/type_check/relate_tys.rs | 4 ++++ compiler/rustc_codegen_ssa/src/base.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 3 ++- .../src/infer/relate/type_relating.rs | 4 ++++ .../src/opaque_hidden_inferred_bound.rs | 1 + .../src/solve/effect_goals.rs | 1 + .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/solve/trait_goals.rs | 4 ++++ .../src/error_reporting/traits/ambiguity.rs | 4 ++-- .../traits/fulfillment_errors.rs | 8 ++++++++ .../src/error_reporting/traits/suggestions.rs | 18 ++++++++++-------- .../src/traits/auto_trait.rs | 1 + .../src/traits/select/candidate_assembly.rs | 1 + .../src/traits/select/mod.rs | 5 +++++ .../src/relate/solver_relating.rs | 4 ++++ 15 files changed, 49 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 3c6527fb316f2..d2b7fd3eccd52 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -502,6 +502,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(b, |this, b| { + let b = b.skip_norm_wip(); let a = this.instantiate_binder_with_existentials(a).skip_norm_wip(); this.relate(a, b) })?; @@ -517,6 +518,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(a, |this, a| { + let a = a.skip_norm_wip(); let b = this.instantiate_binder_with_existentials(b).skip_norm_wip(); this.relate(a, b) })?; @@ -532,12 +534,14 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(b, |this, b| { + let b = b.skip_norm_wip(); let a = this.instantiate_binder_with_existentials(a).skip_norm_wip(); this.relate(a, b) })?; // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! self.enter_forall(a, |this, a| { + let a = a.skip_norm_wip(); let b = this.instantiate_binder_with_existentials(b).skip_norm_wip(); this.relate(a, b) })?; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 916eb58fbcdc2..bbf23ab601e5d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -127,6 +127,7 @@ pub fn validate_trivial_unsize<'tcx>( let universe = infcx.universe(); let ocx = ObligationCtxt::new(&infcx); infcx.enter_forall(hr_target_principal, |target_principal| { + let target_principal = target_principal.skip_norm_wip(); let source_principal = infcx.instantiate_binder_with_fresh_vars( DUMMY_SP, BoundRegionConversionTime::HigherRankedType, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index ccb0796066c46..8ba1114044ae7 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -773,7 +773,8 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { + self.enter_forall(predicate, |pred| { + let ty::SubtypePredicate { a_is_expected, a, b } = pred.skip_norm_wip(); if a_is_expected { Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) } else { diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index ada4f3bc665eb..3dcd6ec0f7094 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -300,6 +300,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html ty::Covariant => { infcx.enter_forall(b, |b| { + let b = b.skip_norm_wip(); let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); let a = a.skip_norm_wip(); self.relate(a, b) @@ -307,6 +308,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { } ty::Contravariant => { infcx.enter_forall(a, |a| { + let a = a.skip_norm_wip(); let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); let b = b.skip_norm_wip(); self.relate(a, b) @@ -325,6 +327,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { // Check if `exists<..> A == for<..> B` ty::Invariant => { infcx.enter_forall(b, |b| { + let b = b.skip_norm_wip(); let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); let a = a.skip_norm_wip(); self.relate(a, b) @@ -332,6 +335,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { // Check if `exists<..> B == for<..> A`. infcx.enter_forall(a, |a| { + let a = a.skip_norm_wip(); let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); let b = b.skip_norm_wip(); self.relate(a, b) diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 97df4ebc8ae13..4f3dad56b520b 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -95,6 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { .map(Unnormalized::skip_norm_wip) { infcx.enter_forall(pred.kind(), |predicate| { + let predicate = predicate.skip_norm_wip(); let ty::ClauseKind::Projection(proj) = predicate else { return; }; diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 2811de013494f..67139c819e83c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -258,6 +258,7 @@ where ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { ecx.enter_forall(constituent_tys, |ecx, tys| { + let tys = tys.skip_norm_wip(); ecx.add_goals( GoalSource::ImplWhereBound, tys.into_iter().map(|ty| { diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 5425d62b36b41..14733df370459 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -587,7 +587,7 @@ where pub(super) fn compute_goal(&mut self, goal: Goal) -> QueryResult { let Goal { param_env, predicate } = goal; let kind = predicate.kind(); - self.enter_forall(kind, |ecx, kind| match kind { + self.enter_forall(kind, |ecx, kind| match kind.skip_norm_wip() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => { ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r) } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 54c03feac9b27..f306fed71ec83 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1069,6 +1069,7 @@ where .probe(|_| ProbeKind::ProjectionCompatibility) .enter(|ecx| -> Result<_, NoSolution> { ecx.enter_forall(target_projection, |ecx, target_projection| { + let target_projection = target_projection.skip_norm_wip(); let source_projection = ecx .instantiate_binder_with_infer(source_projection) .skip_norm_wip(); @@ -1088,6 +1089,7 @@ where let source_principal = upcast_principal.unwrap(); let target_principal = bound.rebind(target_principal); ecx.enter_forall(target_principal, |ecx, target_principal| { + let target_principal = target_principal.skip_norm_wip(); let source_principal = ecx.instantiate_binder_with_infer(source_principal).skip_norm_wip(); ecx.eq(param_env, source_principal, target_principal)?; @@ -1114,6 +1116,7 @@ where ); } ecx.enter_forall(target_projection, |ecx, target_projection| { + let target_projection = target_projection.skip_norm_wip(); let source_projection = ecx .instantiate_binder_with_infer(source_projection) .skip_norm_wip(); @@ -1346,6 +1349,7 @@ where self.probe_trait_candidate(source).enter(|ecx| { let goals = ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| { + let tys = tys.skip_norm_wip(); tys.into_iter() .map(|ty| { goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty)) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 9088e614a87ae..64cb411475b57 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -44,7 +44,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( let obligation_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, - Unnormalized::new_wip(placeholder_obligation.trait_ref), + placeholder_obligation.map(|o| o.trait_ref), ); let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); @@ -102,7 +102,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( let obligation_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, - Unnormalized::new_wip(placeholder_obligation.trait_ref), + placeholder_obligation.map(|o| o.trait_ref), ); let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 823fa794c4daa..871295a3f1ccf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -835,6 +835,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Ok(Some(ImplSource::UserDefined(impl_data))) = self.enter_forall(trait_ref, |trait_ref_for_select| { + let trait_ref_for_select = trait_ref_for_select.skip_norm_wip(); SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref_for_select)) }) { @@ -959,7 +960,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Verify that the arguments are compatible. If the signature is // mismatched, then we have a totally different error to report. if self.enter_forall(found_args, |found_args| { + let found_args = found_args.skip_norm_wip(); self.enter_forall(expected_args, |expected_args| { + let expected_args = expected_args.skip_norm_wip(); !self.can_eq(obligation.param_env, expected_args, found_args) }) }) { @@ -1403,6 +1406,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { while let Some((next_code, next_pred)) = code.parent_with_predicate() { if let Some(pred) = pred { self.enter_forall(pred, |pred| { + let pred = pred.skip_norm_wip(); let ty = self.tcx.short_string(pred.self_ty(), diag.long_ty_path()); let trait_path = self .tcx @@ -1505,18 +1509,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(error) = error.predicate.as_trait_clause() { self.enter_forall(error, |error| { + let error = error.skip_norm_wip(); elaborate(self.tcx, std::iter::once(cond.predicate)) .filter_map(|implied| implied.as_trait_clause()) .any(|implied| self.can_match_trait(param_env, error, implied)) }) } else if let Some(error) = Self::as_host_effect_clause(error.predicate) { self.enter_forall(error, |error| { + let error = error.skip_norm_wip(); elaborate(self.tcx, std::iter::once(cond.predicate)) .filter_map(Self::as_host_effect_clause) .any(|implied| self.can_match_host_effect(param_env, error, implied)) }) } else if let Some(error) = error.predicate.as_projection_clause() { self.enter_forall(error, |error| { + let error = error.skip_norm_wip(); elaborate(self.tcx, std::iter::once(cond.predicate)) .filter_map(|implied| implied.as_projection_clause()) .any(|implied| self.can_match_projection(param_env, error, implied)) @@ -2079,6 +2086,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let ocx = ObligationCtxt::new(self); self.enter_forall(trait_pred, |obligation_trait_ref| { + let obligation_trait_ref = obligation_trait_ref.skip_norm_wip(); let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); let impl_trait_ref = ocx.normalize( &ObligationCause::dummy(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ed543994f2306..0770c93f92f2a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1347,7 +1347,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); - self.enter_forall(self_ty, |ty: Ty<'_>| { + self.enter_forall(self_ty, |ty: Unnormalized<'tcx, Ty<'_>>| { + let ty = ty.skip_norm_wip(); let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_id) else { return false; }; @@ -4858,6 +4859,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && where_pred.def_id() == failed_pred.def_id() { self.enter_forall(where_pred, |where_pred| { + let where_pred = where_pred.skip_norm_wip(); let failed_pred = self.instantiate_binder_with_fresh_vars( expr.span, BoundRegionConversionTime::FnCall, @@ -5602,11 +5604,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.probe(|_| { let ocx = ObligationCtxt::new(self); self.enter_forall(pred, |pred| { - let pred = ocx.normalize( - &ObligationCause::dummy(), - param_env, - Unnormalized::new_wip(pred), - ); + let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); ocx.register_obligation(Obligation::new( self.tcx, ObligationCause::dummy(), @@ -6074,13 +6072,17 @@ fn hint_missing_borrow<'tcx>( } let found_args = match found.kind() { - ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()), + ty::FnPtr(sig_tys, _) => { + infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.skip_norm_wip().inputs().iter()) + } kind => { span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind) } }; let expected_args = match expected.kind() { - ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()), + ty::FnPtr(sig_tys, _) => { + infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.skip_norm_wip().inputs().iter()) + } kind => { span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind) } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index ef99b7772d6be..75609d53fe220 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -738,6 +738,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); selcx.infcx.enter_forall(binder, |pred| { + let pred = pred.skip_norm_wip(); selcx.infcx.register_region_outlives_constraint(pred, ty::VisibleForLeakCheck::Yes,&dummy_cause); }); } 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 0e543f5737889..f5765fb400a85 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -923,6 +923,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|_snapshot| { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| { + let placeholder_trait_predicate = placeholder_trait_predicate.skip_norm_wip(); let self_ty = placeholder_trait_predicate.self_ty(); let principal_trait_ref = match self_ty.kind() { ty::Dynamic(data, ..) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a8dd5ce716bb2..4fc708a0bc9ab 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -620,6 +620,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => { self.infcx.enter_forall(bound_predicate.rebind(data), |data| { + let data = data.skip_norm_wip(); match effects::evaluate_host_effect_obligation( self, &obligation.with(self.tcx(), data), @@ -2619,6 +2620,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx .enter_forall(hr_target_principal, |target_principal| { + let target_principal = target_principal.skip_norm_wip(); let source_principal = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, @@ -2657,6 +2659,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { && self.infcx.probe(|_| { self.infcx .enter_forall(hr_target_projection, |target_projection| { + let target_projection = + target_projection.skip_norm_wip(); let source_projection = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, @@ -2691,6 +2695,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx .enter_forall(hr_target_projection, |target_projection| { + let target_projection = target_projection.skip_norm_wip(); let source_projection = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index c4dd52739d751..022d9cf17ac4b 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -312,12 +312,14 @@ where // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html ty::Covariant => { self.infcx.enter_forall(b, |b| { + let b = b.skip_norm_wip(); let a = self.infcx.instantiate_binder_with_infer(a).skip_norm_wip(); self.relate(a, b) })?; } ty::Contravariant => { self.infcx.enter_forall(a, |a| { + let a = a.skip_norm_wip(); let b = self.infcx.instantiate_binder_with_infer(b).skip_norm_wip(); self.relate(a, b) })?; @@ -335,12 +337,14 @@ where // Check if `exists<..> A == for<..> B` ty::Invariant => { self.infcx.enter_forall(b, |b| { + let b = b.skip_norm_wip(); let a = self.infcx.instantiate_binder_with_infer(a).skip_norm_wip(); self.relate(a, b) })?; // Check if `exists<..> B == for<..> A`. self.infcx.enter_forall(a, |a| { + let a = a.skip_norm_wip(); let b = self.infcx.instantiate_binder_with_infer(b).skip_norm_wip(); self.relate(a, b) })?;