From 8005608edc63cf12c0820560612e7de74597a6ad Mon Sep 17 00:00:00 2001 From: Adwin White Date: Mon, 11 May 2026 21:30:03 +0800 Subject: [PATCH 01/38] introduce `AliasTyKind::Ambiguous` --- .../opaque_types/member_constraints.rs | 4 +- .../src/region_infer/opaque_types/mod.rs | 4 +- .../rustc_const_eval/src/util/type_name.rs | 3 +- .../src/coherence/inherent_impls.rs | 3 +- .../src/coherence/orphan.rs | 26 ++++++------ .../src/variance/constraints.rs | 6 ++- .../src/infer/outlives/for_liveness.rs | 4 +- .../src/infer/outlives/obligations.rs | 2 +- .../src/infer/relate/generalize.rs | 3 ++ .../rustc_lint/src/types/improper_ctypes.rs | 1 + .../src/ty/context/impl_interner.rs | 7 +--- compiler/rustc_middle/src/ty/error.rs | 1 + compiler/rustc_middle/src/ty/print/pretty.rs | 6 ++- compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_middle/src/ty/util.rs | 19 +++------ .../rustc_next_trait_solver/src/coherence.rs | 4 +- .../src/solve/assembly/mod.rs | 4 +- .../src/solve/assembly/structural_traits.rs | 3 +- .../src/solve/normalizes_to/mod.rs | 3 ++ compiler/rustc_privacy/src/lib.rs | 6 ++- .../src/unstable/convert/stable/ty.rs | 1 + .../src/error_reporting/infer/region.rs | 1 + .../traits/fulfillment_errors.rs | 12 ++++-- .../src/solve/fulfill/derive_errors.rs | 6 +-- .../src/traits/normalize.rs | 1 + .../src/traits/project.rs | 1 + .../src/traits/query/normalize.rs | 2 + .../src/traits/select/candidate_assembly.rs | 2 + .../src/traits/select/mod.rs | 1 + .../rustc_trait_selection/src/traits/wf.rs | 3 ++ compiler/rustc_type_ir/src/flags.rs | 31 ++++++++------ compiler/rustc_type_ir/src/interner.rs | 5 +-- compiler/rustc_type_ir/src/outlives.rs | 2 +- compiler/rustc_type_ir/src/predicate.rs | 41 +++++++++++++++++-- compiler/rustc_type_ir/src/relate.rs | 5 ++- compiler/rustc_type_ir/src/ty_kind.rs | 24 +++++++++++ compiler/rustc_type_ir/src/visit.rs | 4 ++ 37 files changed, 175 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs index c057d99c6a41b..8989be90409e9 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs @@ -176,8 +176,8 @@ impl<'tcx> TypeVisitor> for CollectMemberConstraintsVisitor<'_, '_, | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.visit_closure_args(def_id, args), - ty::Alias(ty::AliasTy { kind, args, .. }) - if let Some(variances) = self.cx().opt_alias_variances(kind) => + ty::Alias(alias @ ty::AliasTy { args, .. }) + if let Some(variances) = self.cx().opt_alias_variances(alias) => { // Skip lifetime parameters that are not captured, since they do // not need member constraints registered for them; we'll erase diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index 1348f30b4c980..176660c1555b3 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -500,8 +500,8 @@ impl<'tcx> FallibleTypeFolder> for ToArgRegionsFolder<'_, 'tcx> { Ty::new_coroutine(tcx, def_id, self.fold_closure_args(def_id, args)?) } - ty::Alias(ty::AliasTy { kind, args, .. }) - if let Some(variances) = tcx.opt_alias_variances(kind) => + ty::Alias(alias @ ty::AliasTy { kind, args, .. }) + if let Some(variances) = tcx.opt_alias_variances(alias) => { let args = tcx.mk_args_from_iter(std::iter::zip(variances, args.iter()).map( |(&v, s)| { diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index f1bca03218e07..f8b32cc5464d4 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -45,7 +45,7 @@ impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> { | ty::UnsafeBinder(_) => self.pretty_print_type(ty), // Placeholders (all printed as `_` to uniformize them). - ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => { + ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Error(_) => { write!(self, "_")?; Ok(()) } @@ -69,6 +69,7 @@ impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> { ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { bug!("type_name: unexpected inherent projection") } + ty::Infer(_) | ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. }) => unreachable!(), ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"), } } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 52567667b0fe6..5fd4feea31010 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -210,7 +210,8 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) | ty::Bound(..) | ty::Placeholder(_) - | ty::Infer(_) => { + | ty::Infer(_) + | ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => { bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty); } // We could bail out here, but that will silence other useful errors. diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index bacc1f1549973..a3e647d85db11 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -180,6 +180,19 @@ pub(crate) fn orphan_check_impl( NonlocalImpl::DisallowOther, ), + ty::FnDef(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(..) + | ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. }) => { + let sp = tcx.def_span(impl_def_id); + span_bug!(sp, "weird self type for autotrait impl") + } + ty::Alias(ty::AliasTy { kind, .. }) => { let problematic_kind = match kind { // trait Id { type This: ?Sized; } @@ -203,6 +216,7 @@ pub(crate) fn orphan_check_impl( // ``` // FIXME(inherent_associated_types): The example code above currently leads to a cycle ty::Inherent { .. } => "associated type", + ty::Ambiguous { .. } => unreachable!("handled in arm above"), }; (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther) } @@ -223,18 +237,6 @@ pub(crate) fn orphan_check_impl( | ty::Tuple(..) | ty::UnsafeBinder(_) => (LocalImpl::Allow, NonlocalImpl::DisallowOther), - ty::FnDef(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Infer(..) => { - let sp = tcx.def_span(impl_def_id); - span_bug!(sp, "weird self type for autotrait impl") - } - ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow), }; diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index a45856937a8e0..39269876f1c84 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -327,7 +327,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // types, where we use Error as the Self type } - ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Bound(..) | ty::Infer(..) => { + ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) + | ty::Placeholder(..) + | ty::CoroutineWitness(..) + | ty::Bound(..) + | ty::Infer(..) => { bug!("unexpected type encountered in variance inference: {}", ty); } } diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index b4594bd60f3ba..a9e60cf64993c 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -56,7 +56,7 @@ where // either `'static` or a unique outlives region, and if one is // found, we just need to prove that that region is still live. // If one is not found, then we continue to walk through the alias. - ty::Alias(ty::AliasTy { kind, args, .. }) => { + ty::Alias(alias @ ty::AliasTy { kind, args, .. }) => { let tcx = self.tcx; let param_env = self.param_env; let outlives_bounds: Vec<_> = tcx @@ -95,7 +95,7 @@ where } else { // Skip lifetime parameters that are not captured, since they do // not need to be live. - let variances = tcx.opt_alias_variances(kind); + let variances = tcx.opt_alias_variances(alias); for (idx, s) in args.iter().enumerate() { if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5d6bd3fd4cac6..594cc72ece2a2 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -573,7 +573,7 @@ where && (alias_ty.has_infer_regions() || matches!(kind, ty::Opaque { .. })) { debug!("no declared bounds"); - let opt_variances = self.tcx.opt_alias_variances(kind); + let opt_variances = self.tcx.opt_alias_variances(alias_ty); self.args_must_outlive(alias_ty.args, origin, region, opt_variances); return; } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 3d2d617cfdb29..8075438d4bbab 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -210,6 +210,9 @@ impl<'tcx> InferCtxt<'tcx> { | ty::AliasTermKind::UnevaluatedConst { .. } => { return Err(TypeError::CyclicConst(source_term.expect_const())); } + ty::AliasTermKind::AmbiguousTy { .. } => { + unreachable!("We shouldn't have `AmbiguousTy` in the old solver") + } } } } else { diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index a1020962faedf..79816ba840a22 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -894,6 +894,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { help: None, }, + ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => todo!(), ty::Param(..) | ty::Alias(ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 7f1eeda4ad1d6..629c4dae24efa 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -176,11 +176,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.variances_of(def_id) } - fn opt_alias_variances( - self, - kind: impl Into>, - ) -> Option<&'tcx [ty::Variance]> { - self.opt_alias_variances(kind) + fn opt_alias_variances(self, alias: ty::AliasTy<'tcx>) -> Option<&'tcx [ty::Variance]> { + self.opt_alias_variances(alias) } fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 52f37ed4a9eac..0ce7e9819523b 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -213,6 +213,7 @@ impl<'tcx> Ty<'tcx> { ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => "type alias".into(), ty::Param(_) => "type parameter".into(), ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => "opaque type".into(), + ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => "ambiguous alias".into(), } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index daead99b977c1..ac9e50d57d08e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -819,6 +819,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } } ty::Foreign(def_id) => self.print_def_path(def_id, &[])?, + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args, .. }) => { + self.pretty_print_type(args.type_at(0))? + } ty::Alias( ref data @ ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, @@ -3155,7 +3158,7 @@ define_print! { } ty::AliasTerm<'tcx> { - match self.kind(p.tcx()) { + match self.kind(p.tcx()).reveal_ambiguous(self.args) { ty::AliasTermKind::InherentTy {..} | ty::AliasTermKind::InherentConst {..} => p.pretty_print_inherent_projection(*self)?, ty::AliasTermKind::ProjectionTy { def_id } => { if !(p.should_print_verbose() || with_reduced_queries()) @@ -3173,6 +3176,7 @@ define_print! { | ty::AliasTermKind::ProjectionConst { def_id } => { p.print_def_path(def_id, self.args)?; } + ty::AliasTermKind::AmbiguousTy { .. } => unreachable!() } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 14bce52fefe63..2e8c9c1872262 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -482,6 +482,7 @@ impl<'tcx> Ty<'tcx> { (ty::Opaque { .. }, DefKind::OpaqueTy) | (ty::Projection { .. } | ty::Inherent { .. }, DefKind::AssocTy) | (ty::Free { .. }, DefKind::TyAlias) + | (ty::Ambiguous { .. }, DefKind::OpaqueTy | DefKind::AssocTy | DefKind::TyAlias) ); Ty::new(tcx, Alias(alias_ty)) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 99da2da391151..bdbf1ae4881c0 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -914,25 +914,18 @@ impl<'tcx> TyCtxt<'tcx> { // Computes the variances for an alias (opaque or RPITIT) that represent // its (un)captured regions. - pub fn opt_alias_variances( - self, - kind: impl Into>, - ) -> Option<&'tcx [ty::Variance]> { - match kind.into() { - ty::AliasTermKind::ProjectionTy { def_id } => { + pub fn opt_alias_variances(self, alias: ty::AliasTy<'tcx>) -> Option<&'tcx [ty::Variance]> { + match alias.kind.reveal_ambiguous(alias.args) { + ty::Projection { def_id } => { if self.is_impl_trait_in_trait(def_id) { Some(self.variances_of(def_id)) } else { None } } - ty::AliasTermKind::OpaqueTy { def_id } => Some(self.variances_of(def_id)), - ty::AliasTermKind::InherentTy { .. } - | ty::AliasTermKind::InherentConst { .. } - | ty::AliasTermKind::FreeTy { .. } - | ty::AliasTermKind::FreeConst { .. } - | ty::AliasTermKind::UnevaluatedConst { .. } - | ty::AliasTermKind::ProjectionConst { .. } => None, + ty::Opaque { def_id } => Some(self.variances_of(def_id)), + ty::Inherent { .. } | ty::Free { .. } => None, + ty::Ambiguous => unreachable!(), } } } diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 589d055192029..b42f3925a8992 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -362,14 +362,14 @@ where // normalize to that, so we have to treat it as an uncovered ty param. // * Otherwise it may normalize to any non-type-generic type // be it local or non-local. - ty::Alias(ty::AliasTy { kind, .. }) => { + ty::Alias(ty::AliasTy { kind, args, .. }) => { if ty.has_type_flags( ty::TypeFlags::HAS_TY_PLACEHOLDER | ty::TypeFlags::HAS_TY_BOUND | ty::TypeFlags::HAS_TY_INFER, ) { match self.in_crate { - InCrate::Local { mode } => match kind { + InCrate::Local { mode } => match kind.reveal_ambiguous(args) { ty::Projection { .. } => { if let OrphanCheckMode::Compat = mode { ControlFlow::Continue(()) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 7f3627c6db54e..9546a7612a92f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -767,7 +767,9 @@ where | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Error(_) => return Ok(()), - ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => { + ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Bound(..) + | ty::Alias(AliasTy { kind: ty::Ambiguous { .. }, .. }) => { panic!("unexpected self type for `{goal:?}`") } 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 660f1ec706aa8..054e809900e43 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 @@ -50,7 +50,8 @@ where ty::Dynamic(..) | ty::Param(..) | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, + kind: + ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. } | ty::Ambiguous { .. }, .. }) | ty::Placeholder(..) 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 e9a4d7e5919ad..3b3620a27b5da 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 @@ -52,6 +52,9 @@ where ty::AliasTermKind::UnevaluatedConst { def_id } => { self.normalize_anon_const(goal, def_id).map_err(Into::into) } + ty::AliasTermKind::AmbiguousTy { .. } => { + unreachable!("`AmbiguousTy` should be eliminated when renormalizing binders") + } } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6a792e5a803b7..1c80da38df889 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -243,7 +243,7 @@ where match kind { ty::Inherent { .. } | ty::Projection { .. } => "associated type", ty::Free { .. } => "type alias", - ty::Opaque { .. } => unreachable!(), + ty::Opaque { .. } | ty::Ambiguous { .. } => unreachable!(), }, &LazyDefPathStr { def_id, tcx }, )); @@ -308,7 +308,9 @@ where | ty::Bound(..) | ty::Error(_) | ty::CoroutineWitness(..) => {} - ty::Placeholder(..) | ty::Infer(..) => { + ty::Placeholder(..) + | ty::Infer(..) + | ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => { bug!("unexpected type: {:?}", ty) } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index c4f1da14da23e..fbbf833a87aa4 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -20,6 +20,7 @@ impl<'tcx> Stable<'tcx> for ty::AliasTyKind<'tcx> { ty::Inherent { .. } => crate::ty::AliasKind::Inherent, ty::Opaque { .. } => crate::ty::AliasKind::Opaque, ty::Free { .. } => crate::ty::AliasKind::Free, + ty::Ambiguous { .. } => unreachable!(), } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 9d2eb42496e2f..3ed1135d20942 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -738,6 +738,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ty::Free { .. } => format!("the type alias `{bound_kind}`"), ty::Opaque { .. } => format!("the opaque type `{bound_kind}`"), + ty::Ambiguous { .. } => format!("the ambiguous alias `{bound_kind}`"), }, }; 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 4b67cada078a4..083a1d8ea91cd 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 @@ -1606,7 +1606,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(lhs) = lhs.to_alias_term(self.tcx) && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind(self.tcx) + | ty::AliasTermKind::ProjectionConst { .. } = + lhs.kind.reveal_ambiguous(lhs.args) && let Some((better_type_err, expected_term)) = derive_better_type_error(lhs, rhs) { @@ -1616,7 +1617,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } else if let Some(rhs) = rhs.to_alias_term(self.tcx) && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind(self.tcx) + | ty::AliasTermKind::ProjectionConst { .. } = + rhs.kind.reveal_ambiguous(rhs.args) && let Some((better_type_err, expected_term)) = derive_better_type_error(rhs, lhs) { @@ -1861,7 +1863,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::CoroutineClosure(..) => Some(21), ty::Pat(..) => Some(22), ty::UnsafeBinder(..) => Some(23), - ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, + ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) + | ty::Placeholder(..) + | ty::Bound(..) + | ty::Infer(..) + | ty::Error(_) => None, } } 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..46f920cd9629e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -393,7 +393,6 @@ impl<'tcx> BestObligation<'tcx> { &mut self, goal: &inspect::InspectGoal<'_, 'tcx>, ) -> ControlFlow> { - let tcx = goal.infcx().tcx; let pred_kind = goal.goal().predicate.kind(); match pred_kind.no_bound_vars() { @@ -402,7 +401,8 @@ impl<'tcx> BestObligation<'tcx> { } Some(ty::PredicateKind::NormalizesTo(pred)) if let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = pred.alias.kind(tcx) => + | ty::AliasTermKind::ProjectionConst { .. } = + pred.alias.kind.reveal_ambiguous(pred.alias.args) => { self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?; self.detect_non_well_formed_assoc_item(goal, pred.alias)?; @@ -469,7 +469,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } ty::PredicateKind::NormalizesTo(normalizes_to) if matches!( - normalizes_to.alias.kind(tcx), + normalizes_to.alias.kind.reveal_ambiguous(normalizes_to.alias.args), ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } ) => diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 84dbd53de83f2..31419fde4cb9a 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -441,6 +441,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ty::Projection { .. } => self.normalize_trait_projection(data.into()).expect_type(), ty::Inherent { .. } => self.normalize_inherent_projection(data.into()).expect_type(), ty::Free { .. } => self.normalize_free_alias(data.into()).expect_type(), + ty::Ambiguous { .. } => unreachable!(), } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 900d55cc556fc..f8715824e8eea 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -473,6 +473,7 @@ fn normalize_to_error<'a, 'tcx>( | ty::AliasTermKind::ProjectionConst { .. } => { selcx.infcx.next_const_var(cause.span).into() } + ty::AliasTermKind::AmbiguousTy { .. } => unreachable!(), }; let mut obligations = PredicateObligations::new(); obligations.push(Obligation { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e8c5d10c78ce3..6410e7ccd59a0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -259,6 +259,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { kind @ (ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }) => self .try_fold_free_or_assoc(ty::AliasTerm::new(self.cx(), kind.into(), data.args))? .expect_type(), + ty::Ambiguous { .. } => unreachable!(), }; self.cache.insert(ty, res); @@ -339,6 +340,7 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { tcx.normalize_canonicalized_inherent_projection(c_term) } kind @ (ty::AliasTermKind::OpaqueTy { .. } + | ty::AliasTermKind::AmbiguousTy { .. } | ty::AliasTermKind::UnevaluatedConst { .. }) => { unreachable!("did not expect {kind:?} due to match arm above") } 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 3b599db8ff1c2..1978d4dd5af8b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -863,6 +863,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => unreachable!(), + ty::CoroutineWitness(..) => { candidates.vec.push(AutoImplCandidate); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index eadc937639f20..e47a9e0311918 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2438,6 +2438,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { }) } } + ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => unreachable!(), }) } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fdf32d32e9058..8ba0fb18d1d36 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -815,6 +815,9 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { return; // Subtree handled by compute_inherent_projection. } + // Generally we skip predicates that contain escaping bound vars. See above. + ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => {} + ty::Adt(def, args) => { // WfNominalType let obligations = self.nominal_obligations(def.did(), args); diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 19c59df0604c3..5d384dd802aaf 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -82,6 +82,9 @@ bitflags::bitflags! { /// Does this have `ConstKind::Unevaluated`? const HAS_CT_PROJECTION = 1 << 14; + /// Does this have `Ambiguous` aliases? + const HAS_AMBIGUOUS_ALIAS = 1 << 15; + /// Does this have `Alias` or `ConstKind::Unevaluated`? /// /// Rephrased, could this term be normalized further? @@ -89,26 +92,27 @@ bitflags::bitflags! { | TypeFlags::HAS_TY_FREE_ALIAS.bits() | TypeFlags::HAS_TY_OPAQUE.bits() | TypeFlags::HAS_TY_INHERENT.bits() - | TypeFlags::HAS_CT_PROJECTION.bits(); + | TypeFlags::HAS_CT_PROJECTION.bits() + | TypeFlags::HAS_AMBIGUOUS_ALIAS.bits(); /// Is a type or const error reachable? - const HAS_NON_REGION_ERROR = 1 << 15; + const HAS_NON_REGION_ERROR = 1 << 16; /// Is a region error reachable? - const HAS_RE_ERROR = 1 << 16; + const HAS_RE_ERROR = 1 << 17; /// Is an error type/lifetime/const reachable? const HAS_ERROR = TypeFlags::HAS_NON_REGION_ERROR.bits() | TypeFlags::HAS_RE_ERROR.bits(); /// Does this have any region that "appears free" in the type? /// Basically anything but `ReBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 17; + const HAS_FREE_REGIONS = 1 << 18; /// Does this have any `ReBound` regions? - const HAS_RE_BOUND = 1 << 18; + const HAS_RE_BOUND = 1 << 19; /// Does this have any `Bound` types? - const HAS_TY_BOUND = 1 << 19; + const HAS_TY_BOUND = 1 << 20; /// Does this have any `ConstKind::Bound` consts? - const HAS_CT_BOUND = 1 << 20; + const HAS_CT_BOUND = 1 << 21; /// Does this have any bound variables? /// Used to check if a global bound is safe to evaluate. const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits() @@ -116,7 +120,7 @@ bitflags::bitflags! { | TypeFlags::HAS_CT_BOUND.bits(); /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 21; + const HAS_RE_ERASED = 1 << 22; /// Does this have any regions of any kind? const HAS_REGIONS = TypeFlags::HAS_FREE_REGIONS.bits() @@ -133,19 +137,19 @@ bitflags::bitflags! { | TypeFlags::HAS_CT_INFER.bits(); /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 22; + const HAS_TY_FRESH = 1 << 23; /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 23; + const HAS_CT_FRESH = 1 << 24; /// Does this have any binders with bound vars (e.g. that need to be anonymized)? - const HAS_BINDER_VARS = 1 << 24; + const HAS_BINDER_VARS = 1 << 25; /// Does this type have any coroutines in it? - const HAS_TY_CORO = 1 << 25; + const HAS_TY_CORO = 1 << 26; /// Does this have a `Bound(BoundVarIndexKind::Canonical, _)`? - const HAS_CANONICAL_BOUND = 1 << 26; + const HAS_CANONICAL_BOUND = 1 << 27; } } @@ -301,6 +305,7 @@ impl FlagComputation { ty::Free { .. } => TypeFlags::HAS_TY_FREE_ALIAS, ty::Opaque { .. } => TypeFlags::HAS_TY_OPAQUE, ty::Inherent { .. } => TypeFlags::HAS_TY_INHERENT, + ty::Ambiguous { .. } => TypeFlags::HAS_AMBIGUOUS_ALIAS, }); self.add_alias_ty(alias); diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 09def0212a153..197f7228c1bbf 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -225,10 +225,7 @@ pub trait Interner: type VariancesOf: Copy + Debug + SliceLike; fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf; - fn opt_alias_variances( - self, - kind: impl Into>, - ) -> Option; + fn opt_alias_variances(self, alias: ty::AliasTy) -> Option; fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder; fn type_of_opaque_hir_typeck( diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 2a1cbc3575d85..dcbddb78ecdcd 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -226,7 +226,7 @@ pub fn compute_alias_components_recursive( alias_ty: ty::AliasTy, out: &mut SmallVec<[Component; 4]>, ) { - let opt_variances = cx.opt_alias_variances(alias_ty.kind); + let opt_variances = cx.opt_alias_variances(alias_ty); let mut visitor = OutlivesCollector { cx, out, visited: Default::default() }; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 301cf7dbf1087..adf93c24158e3 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -593,6 +593,15 @@ pub enum AliasTermKind { /// Can always be normalized away. FreeTy { def_id: I::FreeTyAliasId }, + /// A wrapper that indicates the alias needs to be re-normalized. + /// + /// It's specifc to ambiguous aliases that contain escaping bound vars. + /// This is an optimization for binder renormalization and is only used in the + /// next solver. See `NormalizationFolder`. + /// + /// The original alias is stored in the first generic arg. + AmbiguousTy, + /// An unevaluated anonymous constants. UnevaluatedConst { def_id: I::UnevaluatedConstId }, /// An unevaluated const coming from an associated const. @@ -614,6 +623,7 @@ impl AliasTermKind { AliasTermKind::FreeTy { .. } => "type alias", AliasTermKind::FreeConst { .. } => "unevaluated constant", AliasTermKind::UnevaluatedConst { .. } => "unevaluated constant", + AliasTermKind::AmbiguousTy => "ambiguous alias type", } } @@ -622,7 +632,8 @@ impl AliasTermKind { AliasTermKind::ProjectionTy { .. } | AliasTermKind::InherentTy { .. } | AliasTermKind::OpaqueTy { .. } - | AliasTermKind::FreeTy { .. } => true, + | AliasTermKind::FreeTy { .. } + | AliasTermKind::AmbiguousTy => true, AliasTermKind::UnevaluatedConst { .. } | AliasTermKind::ProjectionConst { .. } @@ -638,12 +649,25 @@ impl AliasTermKind { AliasTermKind::InherentTy { def_id } => def_id.into(), AliasTermKind::OpaqueTy { def_id } => def_id.into(), AliasTermKind::FreeTy { def_id } => def_id.into(), + AliasTermKind::AmbiguousTy => todo!("this method is expected to be removed"), AliasTermKind::UnevaluatedConst { def_id } => def_id.into(), AliasTermKind::ProjectionConst { def_id } => def_id.into(), AliasTermKind::FreeConst { def_id } => def_id.into(), AliasTermKind::InherentConst { def_id } => def_id.into(), } } + + // Convert `AmbiguousTy` into its original kind. + pub fn reveal_ambiguous(self, args: I::GenericArgs) -> Self { + if let AliasTermKind::AmbiguousTy = self { + let ty::Alias(ty::AliasTy { kind, .. }) = args.type_at(0).kind() else { + unreachable!() + }; + kind.into() + } else { + self + } + } } impl From> for AliasTermKind { @@ -653,6 +677,7 @@ impl From> for AliasTermKind { ty::Opaque { def_id } => AliasTermKind::OpaqueTy { def_id }, ty::Free { def_id } => AliasTermKind::FreeTy { def_id }, ty::Inherent { def_id } => AliasTermKind::InherentTy { def_id }, + ty::Ambiguous => AliasTermKind::AmbiguousTy, } } } @@ -698,7 +723,11 @@ impl AliasTerm { kind: AliasTermKind, args: I::GenericArgs, ) -> AliasTerm { - interner.debug_assert_args_compatible(kind.def_id(), args); + // FIXME: skipping args compatibility check for `Ambiguous`. + // Should be fixed with the removal the `def_id` method . + if !matches!(kind, AliasTermKind::AmbiguousTy) { + interner.debug_assert_args_compatible(kind.def_id(), args); + } AliasTerm { kind, args, _use_alias_term_new_instead: () } } @@ -727,6 +756,7 @@ impl AliasTerm { AliasTermKind::InherentTy { def_id } => AliasTyKind::Inherent { def_id }, AliasTermKind::OpaqueTy { def_id } => AliasTyKind::Opaque { def_id }, AliasTermKind::FreeTy { def_id } => AliasTyKind::Free { def_id }, + AliasTermKind::AmbiguousTy => AliasTyKind::Ambiguous, kind @ (AliasTermKind::InherentConst { .. } | AliasTermKind::FreeConst { .. } | AliasTermKind::UnevaluatedConst { .. } @@ -746,7 +776,8 @@ impl AliasTerm { kind @ (AliasTermKind::ProjectionTy { .. } | AliasTermKind::InherentTy { .. } | AliasTermKind::OpaqueTy { .. } - | AliasTermKind::FreeTy { .. }) => { + | AliasTermKind::FreeTy { .. } + | AliasTermKind::AmbiguousTy) => { panic!("Cannot turn `{}` into `UnevaluatedConst`", kind.descr()) } }; @@ -777,6 +808,7 @@ impl AliasTerm { AliasTermKind::InherentTy { def_id } => ty::Inherent { def_id }, AliasTermKind::OpaqueTy { def_id } => ty::Opaque { def_id }, AliasTermKind::FreeTy { def_id } => ty::Free { def_id }, + AliasTermKind::AmbiguousTy => ty::Ambiguous, }; Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, alias_ty_kind, self.args)) @@ -803,7 +835,7 @@ impl AliasTerm { } fn projection_def_id(self) -> Option { - match self.kind { + match self.kind.reveal_ambiguous(self.args) { AliasTermKind::ProjectionTy { def_id } => Some(def_id.into()), AliasTermKind::ProjectionConst { def_id } => Some(def_id.into()), AliasTermKind::InherentTy { .. } @@ -812,6 +844,7 @@ impl AliasTerm { | AliasTermKind::UnevaluatedConst { .. } | AliasTermKind::FreeConst { .. } | AliasTermKind::InherentConst { .. } => None, + AliasTermKind::AmbiguousTy => unreachable!(), } } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 51de99e92fcad..5ee2b19e49757 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -220,7 +220,7 @@ impl Relate for ty::AliasTy { ))) } else { let cx = relation.cx(); - let args = if let Some(variances) = cx.opt_alias_variances(a.kind) { + let args = if let Some(variances) = cx.opt_alias_variances(a) { relate_args_with_variances(relation, variances, a.args, b.args)? } else { relate_args_invariantly(relation, a.args, b.args)? @@ -239,7 +239,7 @@ impl Relate for ty::AliasTerm { if a.def_id() != b.def_id() { Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.def_id(), b.def_id()))) } else { - let args = match a.kind(relation.cx()) { + let args = match a.kind(relation.cx()).reveal_ambiguous(a.args) { ty::AliasTermKind::OpaqueTy { .. } => relate_args_with_variances( relation, relation.cx().variances_of(a.def_id()), @@ -255,6 +255,7 @@ impl Relate for ty::AliasTerm { | ty::AliasTermKind::ProjectionConst { .. } => { relate_args_invariantly(relation, a.args, b.args)? } + ty::AliasTermKind::AmbiguousTy { .. } => unreachable!(), }; Ok(a.with_args(relation.cx(), args)) } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 6f3cea27cafdb..0cb003d5188e0 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -62,6 +62,15 @@ pub enum AliasTyKind { /// Currently only used if the type alias references opaque types. /// Can always be normalized away. Free { def_id: I::FreeTyAliasId }, + + /// A wrapper that indicates the alias needs to be re-normalized. + /// + /// It's specifc to ambiguous aliases that contain escaping bound vars. + /// This is an optimization for binder renormalization and is only used in the + /// next solver. See `NormalizationFolder`. + /// + /// The original alias is stored in the first generic arg. + Ambiguous, } impl AliasTyKind { @@ -75,6 +84,7 @@ impl AliasTyKind { AliasTyKind::Inherent { .. } => "inherent associated type", AliasTyKind::Opaque { .. } => "opaque type", AliasTyKind::Free { .. } => "type alias", + AliasTyKind::Ambiguous { .. } => "ambiguous alias", } } @@ -84,6 +94,20 @@ impl AliasTyKind { AliasTyKind::Inherent { def_id } => def_id.into(), AliasTyKind::Opaque { def_id } => def_id.into(), AliasTyKind::Free { def_id } => def_id.into(), + // FIXME: in the meantime, We can `reveal_ambiguous` and call this method? + AliasTyKind::Ambiguous => todo!("this method is expected to be removed"), + } + } + + // Convert `Ambiguous` into its original kind. + pub fn reveal_ambiguous(self, args: I::GenericArgs) -> Self { + if let AliasTyKind::Ambiguous = self { + let ty::Alias(ty::AliasTy { kind, .. }) = args.type_at(0).kind() else { + unreachable!() + }; + kind + } else { + self } } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 492c37481298b..1b091eece4514 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -265,6 +265,10 @@ pub trait TypeVisitableExt: TypeVisitable { self.has_type_flags(TypeFlags::HAS_ALIAS) } + fn has_ambiguous_aliases(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_AMBIGUOUS_ALIAS) + } + fn has_opaque_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) } From 3ad3a863e7a6f1a98bb8d4af70d70ad15bd29052 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Thu, 7 May 2026 17:47:10 +0800 Subject: [PATCH 02/38] folders to create and consume ambiguous --- .../rustc_next_trait_solver/src/normalize.rs | 160 ++++++++++++++++-- 1 file changed, 145 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 7506591d6fb5d..5b9ff95fc9a5d 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -1,6 +1,6 @@ use rustc_type_ir::data_structures::ensure_sufficient_stack; use rustc_type_ir::inherent::*; -use rustc_type_ir::solve::{Goal, NoSolution}; +use rustc_type_ir::solve::{Goal, NoSolutionOrRerunNonErased}; use rustc_type_ir::{ self as ty, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, Interner, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -31,6 +31,12 @@ enum HasEscapingBoundVars { No, } +#[derive(PartialEq, Eq)] +pub enum NormalizationScope { + All, + AmbiguousAlias, +} + /// Finds the max universe present in infer vars. struct MaxUniverse<'a, Infcx, I> where @@ -97,11 +103,19 @@ where } } +#[derive(PartialEq, Eq)] +enum NeedRenormalization { + Yes, + No, +} + impl<'a, Infcx, I, F> NormalizationFolder<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Term) -> Result<(I::Term, Option>), NoSolution>, + F: FnMut( + I::Term, + ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, { pub fn new( infcx: &'a Infcx, @@ -120,7 +134,7 @@ where &mut self, alias_term: I::Term, has_escaping: HasEscapingBoundVars, - ) -> Result { + ) -> Result<(I::Term, NeedRenormalization), NoSolutionOrRerunNonErased> { let current_universe = self.infcx.universe(); self.infcx.create_next_universe(); @@ -139,12 +153,12 @@ where normalized.visit_with(&mut visitor); let max_universe = visitor.max_universe(); if current_universe.cannot_name(max_universe) { - return Ok(alias_term); + return Ok((alias_term, NeedRenormalization::Yes)); } } self.stalled_goals.extend(ambig_goal); - Ok(normalized) + Ok((normalized, NeedRenormalization::No)) } } @@ -152,9 +166,11 @@ impl<'a, Infcx, I, F> FallibleTypeFolder for NormalizationFolder<'a, Infcx, I where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Term) -> Result<(I::Term, Option>), NoSolution>, + F: FnMut( + I::Term, + ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, { - type Error = NoSolution; + type Error = NoSolutionOrRerunNonErased; fn cx(&self) -> I { self.infcx.cx() @@ -180,27 +196,41 @@ where // With eager normalization, we should normalize the args of alias before // normalizing the alias itself. let ty = ty.try_super_fold_with(self)?; - let ty::Alias(..) = ty.kind() else { return Ok(ty) }; + let ty::Alias(alias_ty) = ty.kind() else { return Ok(ty) }; if ty.has_escaping_bound_vars() { let (ty, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty); - let result = ensure_sufficient_stack(|| { + let (normalized_term, need_renormalization) = ensure_sufficient_stack(|| { self.normalize_alias_term(ty.into(), HasEscapingBoundVars::Yes) - })? - .expect_ty(); - Ok(PlaceholderReplacer::replace_placeholders( + })?; + let normalized_ty = PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, mapped_types, mapped_consts, &self.universes, - result, - )) + normalized_term.expect_ty(), + ); + if need_renormalization == NeedRenormalization::Yes { + Ok(I::Ty::new_alias( + self.cx(), + ty::AliasTy::new_from_args( + self.cx(), + ty::AliasTyKind::Ambiguous, + self.cx().mk_args(&[normalized_ty.into()]), + ), + )) + } else { + Ok(normalized_ty) + } } else { + let alias = + if let ty::Ambiguous = alias_ty.kind { alias_ty.args.type_at(0) } else { ty }; Ok(ensure_sufficient_stack(|| { - self.normalize_alias_term(ty.into(), HasEscapingBoundVars::No) + self.normalize_alias_term(alias.into(), HasEscapingBoundVars::No) })? + .0 .expect_ty()) } } @@ -223,6 +253,7 @@ where let result = ensure_sufficient_stack(|| { self.normalize_alias_term(ct.into(), HasEscapingBoundVars::Yes) })? + .0 .expect_const(); Ok(PlaceholderReplacer::replace_placeholders( infcx, @@ -236,7 +267,106 @@ where Ok(ensure_sufficient_stack(|| { self.normalize_alias_term(ct.into(), HasEscapingBoundVars::No) })? + .0 .expect_const()) } } } + +// Only handle ambiguous alias in the outmost instantiated binder. +pub struct BinderRenormalizer<'a, Infcx, I, F> +where + Infcx: InferCtxtLike, + I: Interner, +{ + infcx: &'a Infcx, + stalled_goals: Vec>, + normalize: F, +} + +impl<'a, Infcx, I, F> BinderRenormalizer<'a, Infcx, I, F> +where + Infcx: InferCtxtLike, + I: Interner, + F: FnMut( + I::Term, + ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, +{ + pub fn new(infcx: &'a Infcx, stalled_goals: Vec>, normalize: F) -> Self { + Self { infcx, stalled_goals, normalize } + } + + pub fn stalled_goals(self) -> Vec> { + self.stalled_goals + } + + fn normalize_alias_term( + &mut self, + alias_term: I::Term, + ) -> Result { + let (normalized, ambig_goal) = (self.normalize)(alias_term)?; + + self.stalled_goals.extend(ambig_goal); + Ok(normalized) + } +} + +impl<'a, Infcx, I, F> FallibleTypeFolder for BinderRenormalizer<'a, Infcx, I, F> +where + Infcx: InferCtxtLike, + I: Interner, + F: FnMut( + I::Term, + ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, +{ + type Error = NoSolutionOrRerunNonErased; + + fn cx(&self) -> I { + self.infcx.cx() + } + + fn try_fold_binder>( + &mut self, + t: Binder, + ) -> Result, Self::Error> { + // We don't look into nested binders since they're not instantiated. + // Thus we assume we won't meet escaping bound vars as well. + Ok(t) + } + + #[instrument(level = "trace", skip(self), ret)] + fn try_fold_ty(&mut self, ty: I::Ty) -> Result { + debug_assert!(!ty.has_escaping_bound_vars()); + if !ty.has_ambiguous_aliases() { + return Ok(ty); + } + + // With eager normalization, we should normalize the args of alias before + // normalizing the alias itself. + let ty = ty.try_super_fold_with(self)?; + let ty::Alias(ty::AliasTy { kind: ty::AliasTyKind::Ambiguous, args, .. }) = ty.kind() + else { + return Ok(ty); + }; + + let original_alias = args.type_at(0); + Ok(ensure_sufficient_stack(|| self.normalize_alias_term(original_alias.into()))? + .expect_ty()) + } + + #[instrument(level = "trace", skip(self), ret)] + fn try_fold_const(&mut self, ct: I::Const) -> Result { + debug_assert!(!ct.has_escaping_bound_vars()); + if !ct.has_ambiguous_aliases() { + return Ok(ct); + } + + // With eager normalization, we should normalize the args of alias before + // normalizing the alias itself. + let ct = ct.try_super_fold_with(self)?; + let ty::ConstKind::Unevaluated(..) = ct.kind() else { return Ok(ct) }; + // FIXME: add an new `Ambiguous` kind to `UnevaluatedConst` as well. + // As a field or a new kind on `ConstKind`? + Ok(ct) + } +} From a5bfa857aa3ef77629c1d364f3967eac2fd412ed Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 13 May 2026 11:47:33 +0800 Subject: [PATCH 03/38] add new wrapper def --- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_type_ir/src/lib.rs | 2 +- compiler/rustc_type_ir/src/unnormalized.rs | 35 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 74f9e75fb48c0..ce63e699b4243 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -109,7 +109,7 @@ pub use self::sty::{ BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, FnSigKind, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst, PlaceholderRegion, PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, - TypingModeEqWrapper, Unnormalized, UpvarArgs, + TypingModeEqWrapper, Unnormalized, UnnormalizedAmbiguous, UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2e8c9c1872262..6f97e64b13b71 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -43,6 +43,7 @@ pub type FnSigKind<'tcx> = ir::FnSigKind>; pub type Binder<'tcx, T> = ir::Binder, T>; pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; pub type Unnormalized<'tcx, T> = ir::Unnormalized, T>; +pub type UnnormalizedAmbiguous<'tcx, T> = ir::UnnormalizedAmbiguous, T>; pub type TypingMode<'tcx, S = MayBeErased> = ir::TypingMode, S>; pub type TypingModeEqWrapper<'tcx> = ir::TypingModeEqWrapper>; pub type Placeholder<'tcx, T> = ir::Placeholder, T>; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index d9906795dfba6..7ca1565f68f07 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -82,7 +82,7 @@ pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintT use rustc_type_ir_macros::GenericTypeVisitable; pub use ty_info::*; pub use ty_kind::*; -pub use unnormalized::Unnormalized; +pub use unnormalized::*; pub use upcast::*; pub use visit::*; diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index 0981a8a7e0e18..62e11bd1c9bab 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -147,3 +147,38 @@ impl Unnormalized>> { Unnormalized::new(inner) } } + +/// Like `Unnormalized`, but for value that contains unnormalized `Ambiguous` alias. +#[derive_where(Clone, Copy, PartialOrd, PartialEq, Debug; T)] +pub struct UnnormalizedAmbiguous { + value: T, + #[derive_where(skip(Debug))] + _tcx: PhantomData I>, +} + +impl UnnormalizedAmbiguous { + /// Should only be used in binder instantitation. + pub fn new(value: T) -> Self { + Self { value, _tcx: PhantomData } + } + + /// FIXME: This is going to be eventually removed. + /// If you meet this in codebase, try using one of the ambiguous renormalization + /// routines to consume the wrapper. Or use `skip_normalization` when normalization + /// is really unnecessary. + pub fn skip_norm_wip(self) -> T { + self.value + } + + /// Intentionally skip normalization. + /// You probably should perform normalization in most cases. + pub fn skip_normalization(self) -> T { + self.value + } +} + +impl From> for Unnormalized { + fn from(value: UnnormalizedAmbiguous) -> Unnormalized { + Unnormalized::new(value.skip_normalization()) + } +} From d493c2a76d7b5cabf8c5670617c974b19cd342ac Mon Sep 17 00:00:00 2001 From: Adwin White Date: Fri, 8 May 2026 15:03:31 +0800 Subject: [PATCH 04/38] add method to normalize ambiguous aliases outside of next solver --- .../src/solve/normalize.rs | 73 ++++++++++++------- .../src/traits/engine.rs | 10 +++ .../src/traits/normalize.rs | 24 +++++- 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 7c21dc161a1ec..707ae2d6a26e2 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,6 +1,6 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::infer::at::At; -use rustc_infer::traits::solve::Goal; +use rustc_infer::traits::solve::{Goal, NoSolutionOrRerunNonErased}; use rustc_infer::traits::{ FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; @@ -9,7 +9,9 @@ use rustc_middle::ty::{ self, Binder, Flags, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UniverseIndex, Unnormalized, }; -use rustc_next_trait_solver::normalize::NormalizationFolder; +use rustc_next_trait_solver::normalize::{ + BinderRenormalizer, NormalizationFolder, NormalizationScope, +}; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; use super::{FulfillmentCtxt, NextSolverError}; @@ -17,11 +19,15 @@ use crate::solve::{Certainty, SolverDelegate}; use crate::traits::{BoundVarReplacer, ScrubbedTraitError}; /// see `normalize_with_universes`. -pub fn normalize<'tcx, T>(at: At<'_, 'tcx>, value: Unnormalized<'tcx, T>) -> Normalized<'tcx, T> +pub fn normalize<'tcx, T>( + at: At<'_, 'tcx>, + value: Unnormalized<'tcx, T>, + scope: NormalizationScope, +) -> Normalized<'tcx, T> where T: TypeFoldable>, { - normalize_with_universes(at, value, vec![]) + normalize_with_universes(at, value, vec![], scope) } /// Like `deeply_normalize`, but we handle ambiguity and inference variables in this routine. @@ -35,6 +41,7 @@ fn normalize_with_universes<'tcx, T>( at: At<'_, 'tcx>, value: Unnormalized<'tcx, T>, universes: Vec>, + scope: NormalizationScope, ) -> Normalized<'tcx, T> where T: TypeFoldable>, @@ -43,27 +50,42 @@ where let value = value.skip_normalization(); let value = infcx.resolve_vars_if_possible(value); let original_value = value.clone(); - let mut folder = - NormalizationFolder::new(infcx, universes.clone(), Default::default(), |alias_term| { - let delegate = <&SolverDelegate<'tcx>>::from(infcx); - let infer_term = delegate.next_term_var_of_kind(alias_term, at.cause.span); - let predicate = ty::PredicateKind::AliasRelate( - alias_term.into(), - infer_term.into(), - ty::AliasRelationDirection::Equate, + let normalize_term = |alias_term| -> Result<_, NoSolutionOrRerunNonErased> { + let delegate = <&SolverDelegate<'tcx>>::from(infcx); + let infer_term = delegate.next_term_var_of_kind(alias_term, at.cause.span); + let predicate = ty::PredicateKind::AliasRelate( + alias_term.into(), + infer_term.into(), + ty::AliasRelationDirection::Equate, + ); + let goal = Goal::new(infcx.tcx, at.param_env, predicate); + let result = delegate.evaluate_root_goal(goal, at.cause.span, None)?; + let normalized = infcx.resolve_vars_if_possible(infer_term); + let stalled_goal = match result.certainty { + Certainty::Yes => None, + Certainty::Maybe { .. } => Some(infcx.resolve_vars_if_possible(result.goal)), + }; + Ok((normalized, stalled_goal)) + }; + let (normalized, stalled_goals) = match scope { + NormalizationScope::All => { + let mut folder = NormalizationFolder::new( + infcx, + universes.clone(), + Default::default(), + normalize_term, ); - let goal = Goal::new(infcx.tcx, at.param_env, predicate); - let result = delegate.evaluate_root_goal(goal, at.cause.span, None)?; - let normalized = infcx.resolve_vars_if_possible(infer_term); - let stalled_goal = match result.certainty { - Certainty::Yes => None, - Certainty::Maybe { .. } => Some(infcx.resolve_vars_if_possible(result.goal)), - }; - Ok((normalized, stalled_goal)) - }); - if let Ok(value) = value.try_fold_with(&mut folder) { - let obligations = folder - .stalled_goals() + let normalized = value.try_fold_with(&mut folder); + (normalized, folder.stalled_goals()) + } + NormalizationScope::AmbiguousAlias => { + let mut folder = BinderRenormalizer::new(infcx, Default::default(), normalize_term); + let normalized = value.try_fold_with(&mut folder); + (normalized, folder.stalled_goals()) + } + }; + if let Ok(value) = normalized { + let obligations = stalled_goals .into_iter() .map(|goal| { Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate) @@ -210,7 +232,8 @@ where T: TypeFoldable>, E: FromSolverError<'tcx, NextSolverError<'tcx>>, { - let Normalized { value, obligations } = normalize_with_universes(at, value, universes); + let Normalized { value, obligations } = + normalize_with_universes(at, value, universes, NormalizationScope::All); let mut fulfill_cx = FulfillmentCtxt::new(at.infcx); for pred in obligations { diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 6cddd79544906..c972a31daa6e1 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -119,6 +119,16 @@ where self.register_infer_ok_obligations(infer_ok) } + pub fn renormalize_ambiguous_aliases>>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: ty::UnnormalizedAmbiguous<'tcx, T>, + ) -> T { + let infer_ok = self.infcx.at(cause, param_env).renormalize_ambiguous_aliases(value); + self.register_infer_ok_obligations(infer_ok) + } + pub fn eq>( &self, cause: &ObligationCause<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 31419fde4cb9a..f54814255b364 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{ self, AliasTerm, Term, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingMode, Unnormalized, }; +use rustc_next_trait_solver::normalize::NormalizationScope; use tracing::{debug, instrument}; use super::{BoundVarReplacer, PlaceholderReplacer, SelectionContext, project}; @@ -33,7 +34,8 @@ impl<'tcx> At<'_, 'tcx> { value: Unnormalized<'tcx, T>, ) -> InferOk<'tcx, T> { if self.infcx.next_trait_solver() { - let Normalized { value, obligations } = crate::solve::normalize(*self, value); + let Normalized { value, obligations } = + crate::solve::normalize(*self, value, NormalizationScope::All); InferOk { value, obligations } } else { let value = value.skip_normalization(); @@ -44,6 +46,26 @@ impl<'tcx> At<'_, 'tcx> { } } + /// Normalize aliases of `Ambiguous` kind in a value. + /// + /// We should use this after instantiating binders to improve perf. + fn renormalize_ambiguous_aliases>>( + &self, + value: ty::UnnormalizedAmbiguous<'tcx, T>, + ) -> InferOk<'tcx, T> { + if self.infcx.next_trait_solver() { + let Normalized { value, obligations } = crate::solve::normalize( + *self, + Unnormalized::new(value.skip_normalization()), + NormalizationScope::AmbiguousAlias, + ); + InferOk { value, obligations } + } else { + // We won't have ambiguous aliases in old solver so no-op. + InferOk { value: value.skip_normalization(), obligations: Default::default() } + } + } + /// Deeply normalizes `value`, replacing all aliases which can by normalized in /// the current environment. In the new solver this errors in case normalization /// fails or is ambiguous. From 29edde4f5aeaa70e62d84e74152614f9c0e52d9a Mon Sep 17 00:00:00 2001 From: Adwin White Date: Thu, 30 Apr 2026 19:57:26 +0800 Subject: [PATCH 05/38] add normalization methods to eval_ctxt --- .../src/solve/eval_ctxt/mod.rs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) 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 54d306466cf5b..fe2404ca69662 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 @@ -28,6 +28,7 @@ use crate::canonical::{ }; use crate::coherence; use crate::delegate::SolverDelegate; +use crate::normalize::{BinderRenormalizer, NormalizationFolder, NormalizationScope}; use crate::placeholder::BoundVarReplacer; use crate::resolve::eager_resolve_vars; use crate::solve::search_graph::SearchGraph; @@ -1731,6 +1732,80 @@ where ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } } + + /// Normalizes aliases in a value as much as we can. + /// + /// Ambiguous goals are added to eval_ctxt. + pub fn normalize>( + &mut self, + param_env: I::ParamEnv, + value: ty::Unnormalized, + ) -> Result { + self.normalize_inner(param_env, value, NormalizationScope::All) + } + + /// Only normalizes aliases of `AmbiguousTy` kind. + /// + /// Ambiguous goals are added to eval_ctxt. + /// + /// This should be used after instantiating binders to improve perf, assuming that + /// other normalizable aliases have been normalized before. + pub fn normalize_ambiguous_only>( + &mut self, + param_env: I::ParamEnv, + value: ty::UnnormalizedAmbiguous, + ) -> Result { + self.normalize_inner(param_env, value.into(), NormalizationScope::AmbiguousAlias) + } + + fn normalize_inner>( + &mut self, + param_env: I::ParamEnv, + value: ty::Unnormalized, + scope: NormalizationScope, + ) -> Result { + let value = value.skip_normalization(); + let value = self.delegate.resolve_vars_if_possible(value); + // To drop the mutable borrow of self early. + let (normalized, stalled_goals) = { + let infcx = self.delegate.deref(); + let normalize_term = |alias_term| { + let delegate = self.delegate; + let infer_term = self.next_term_infer_of_kind(alias_term); + let predicate = ty::PredicateKind::AliasRelate( + alias_term.into(), + infer_term.into(), + ty::AliasRelationDirection::Equate, + ); + let goal = Goal::new(self.delegate.cx(), param_env, predicate); + let result = self.evaluate_goal(GoalSource::Misc, goal, None)?; + let normalized = delegate.resolve_vars_if_possible(infer_term); + let stalled_goal = match result.certainty { + Certainty::Yes => None, + Certainty::Maybe { .. } => Some(delegate.resolve_vars_if_possible(result.goal)), + }; + Ok((normalized, stalled_goal)) + }; + match scope { + NormalizationScope::All => { + let mut folder = + NormalizationFolder::new(infcx, vec![], Default::default(), normalize_term); + let value = value.try_fold_with(&mut folder)?; + (value, folder.stalled_goals()) + } + NormalizationScope::AmbiguousAlias => { + let mut folder = + BinderRenormalizer::new(infcx, Default::default(), normalize_term); + let value = value.try_fold_with(&mut folder)?; + (value, folder.stalled_goals()) + } + } + }; + + // FIXME: what goal source should we use? + self.add_goals(GoalSource::Misc, stalled_goals); + Ok(normalized) + } } /// Eagerly replace aliases with inference variables, emitting `AliasRelate` From e911fbd73cd576bdda6514f179aa3a143fc9948b Mon Sep 17 00:00:00 2001 From: Adwin White Date: Fri, 8 May 2026 15:47:59 +0800 Subject: [PATCH 06/38] make instantitation renormalize --- .../rustc_borrowck/src/diagnostics/mod.rs | 17 +-- .../src/type_check/input_output.rs | 11 +- compiler/rustc_borrowck/src/type_check/mod.rs | 24 ++-- .../src/type_check/relate_tys.rs | 2 + compiler/rustc_codegen_ssa/src/base.rs | 13 +- .../src/check/compare_eii.rs | 28 ++-- .../src/check/compare_impl_item.rs | 32 +++-- compiler/rustc_hir_typeck/src/callee.rs | 26 ++-- compiler/rustc_hir_typeck/src/closure.rs | 20 ++- compiler/rustc_hir_typeck/src/expr.rs | 35 ++--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 23 +++- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_hir_typeck/src/method/mod.rs | 19 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 55 ++++---- .../rustc_hir_typeck/src/method/suggest.rs | 29 ++-- compiler/rustc_infer/src/infer/context.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 56 ++++++-- .../src/infer/relate/higher_ranked.rs | 43 +++++- .../src/infer/relate/type_relating.rs | 32 +++-- .../src/opaque_hidden_inferred_bound.rs | 2 +- .../src/solve/assembly/structural_traits.rs | 11 +- .../src/solve/effect_goals.rs | 9 +- .../src/solve/eval_ctxt/mod.rs | 14 +- .../src/solve/normalizes_to/mod.rs | 11 +- .../src/solve/trait_goals.rs | 30 ++-- .../src/error_reporting/traits/ambiguity.rs | 15 +- .../traits/fulfillment_errors.rs | 26 ++-- .../src/error_reporting/traits/suggestions.rs | 31 +++-- .../src/solve/fulfill/derive_errors.rs | 4 +- .../src/traits/auto_trait.rs | 2 +- .../src/traits/effects.rs | 2 +- .../src/traits/project.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 93 +++++++------ .../src/traits/select/confirmation.rs | 8 +- .../src/traits/select/mod.rs | 130 +++++++++--------- compiler/rustc_type_ir/src/infer_ctxt.rs | 4 +- .../rustc_type_ir/src/region_constraint.rs | 11 +- .../src/relate/solver_relating.rs | 12 +- 40 files changed, 548 insertions(+), 354 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 248396ba9849b..18c8e393635e3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1460,14 +1460,15 @@ 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_no_ambiguous_aliases( + fn_call_span, + BoundRegionConversionTime::FnCall, + tcx.fn_sig(method_did) + .instantiate(tcx, method_args) + .skip_norm_wip() + .input(0), + ) && 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 fe40173b905d6..5a8a626759de8 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( - self.body.span, - BoundRegionConversionTime::FnCall, - user_provided_sig, - ); + let mut user_provided_sig = + self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + self.body.span, + BoundRegionConversionTime::FnCall, + user_provided_sig, + ); // 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 13983f349d6a5..8429a2953ba15 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1076,11 +1076,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { && let target_sig = target_fn_tys.with(target_hdr) && let Some(target_sig) = target_sig.no_bound_vars() { - let src_sig = self.infcx.instantiate_binder_with_fresh_vars( - span, - BoundRegionConversionTime::HigherRankedType, - src_sig, - ); + let src_sig = + self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + span, + BoundRegionConversionTime::HigherRankedType, + src_sig, + ); let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig)); self.prove_predicate( ty::ClauseKind::WellFormed(src_ty.into()), @@ -1676,11 +1677,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *ty.kind() else { unreachable!(); }; - let expected_ty = self.infcx.instantiate_binder_with_fresh_vars( - self.body().source_info(location).span, - BoundRegionConversionTime::HigherRankedType, - binder_ty.into(), - ); + let expected_ty = + self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + self.body().source_info(location).span, + BoundRegionConversionTime::HigherRankedType, + binder_ty.into(), + ); self.sub_types( operand_ty, expected_ty, @@ -1916,7 +1918,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else { unreachable!(); }; - let found_ty = self.infcx.instantiate_binder_with_fresh_vars( + let found_ty = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( self.body.source_info(location).span, BoundRegionConversionTime::HigherRankedType, binder_ty.into(), diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index f18884df0b44d..5d8eb35ff368b 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -172,6 +172,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { where T: ty::TypeFoldable> + Copy, { + debug_assert!(!binder.has_ambiguous_aliases()); let value = if let Some(inner) = binder.no_bound_vars() { inner } else { @@ -215,6 +216,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { where T: ty::TypeFoldable> + Copy, { + debug_assert!(!binder.has_ambiguous_aliases()); if let Some(inner) = binder.no_bound_vars() { return inner; } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index b0ce3833446d3..323701ceeadd6 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -128,12 +128,13 @@ pub fn validate_trivial_unsize<'tcx>( tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let universe = infcx.universe(); let ocx = ObligationCtxt::new(&infcx); - infcx.enter_forall(hr_target_principal, |target_principal| { - let source_principal = infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - hr_source_principal, - ); + infcx.enter_forall_no_ambiguous_aliases(hr_target_principal, |target_principal| { + let source_principal = infcx + .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + hr_source_principal, + ); 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..c5139ee70a40a 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -72,21 +72,19 @@ pub(crate) fn compare_eii_function_types<'tcx>( let declaration_sig = tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig); debug!(?declaration_sig); - let unnormalized_external_impl_sig = infcx.instantiate_binder_with_fresh_vars( - external_impl_span, - infer::BoundRegionConversionTime::HigherRankedType, - tcx.fn_sig(external_impl) - .instantiate( - tcx, - infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id()), + // We need to check wf of the unnormalized sig. + let unnormalized_external_impl_sig = tcx + .fn_sig(external_impl) + .instantiate(tcx, infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id())) + .map(|sig| { + infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + external_impl_span, + infer::BoundRegionConversionTime::HigherRankedType, + sig, ) - .skip_norm_wip(), - ); - let external_impl_sig = ocx.normalize( - &norm_cause, - param_env, - Unnormalized::new_wip(unnormalized_external_impl_sig), - ); + }); + let external_impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_external_impl_sig); + debug!(?external_impl_sig); // Next, add all inputs and output as well-formed tys. Importantly, @@ -125,7 +123,7 @@ pub(crate) fn compare_eii_function_types<'tcx>( } if !(declaration_sig, external_impl_sig).references_error() { - for ty in unnormalized_external_impl_sig.inputs_and_output { + for ty in unnormalized_external_impl_sig.skip_normalization().inputs_and_output { ocx.register_obligation(traits::Obligation::new( infcx.tcx, cause.clone(), 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..2151011fe0efb 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -326,15 +326,18 @@ fn compare_method_predicate_entailment<'tcx>( let mut wf_tys = FxIndexSet::default(); - let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars( - impl_m_span, - BoundRegionConversionTime::HigherRankedType, - tcx.fn_sig(impl_m.def_id).instantiate_identity().skip_norm_wip(), - ); + // We need to check wf of unnormalized sig. + let unnormalized_impl_sig = tcx.fn_sig(impl_m.def_id).instantiate_identity().map(|sig| { + infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + impl_m_span, + BoundRegionConversionTime::HigherRankedType, + sig, + ) + }); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id); - let impl_sig = - ocx.normalize(&norm_cause, param_env, Unnormalized::new_wip(unnormalized_impl_sig)); + let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig); + debug!(?impl_sig); let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args).skip_norm_wip(); @@ -375,7 +378,7 @@ fn compare_method_predicate_entailment<'tcx>( } if !(impl_sig, trait_sig).references_error() { - for ty in unnormalized_impl_sig.inputs_and_output { + for ty in unnormalized_impl_sig.skip_normalization().inputs_and_output { ocx.register_obligation(traits::Obligation::new( infcx.tcx, cause.clone(), @@ -534,15 +537,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // Normalize the impl signature with fresh variables for lifetime inference. let misc_cause = ObligationCause::misc(return_span, impl_m_def_id); - let impl_sig = ocx.normalize( - &misc_cause, - param_env, - Unnormalized::new_wip(infcx.instantiate_binder_with_fresh_vars( + let impl_sig = tcx.fn_sig(impl_m.def_id).instantiate_identity().map(|sig| { + infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( return_span, BoundRegionConversionTime::HigherRankedType, - tcx.fn_sig(impl_m.def_id).instantiate_identity().skip_norm_wip(), - )), - ); + sig, + ) + }); + let impl_sig = ocx.normalize(&misc_cause, param_env, impl_sig); 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 e15c9fe661641..3a589e4a31477 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,11 +232,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Closure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { let def_id = def_id.expect_local(); let closure_sig = args.as_closure().sig(); - let closure_sig = self.instantiate_binder_with_fresh_vars( - call_expr.span, - BoundRegionConversionTime::FnCall, - closure_sig, - ); + let closure_sig = self + .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + call_expr.span, + BoundRegionConversionTime::FnCall, + closure_sig, + ); let adjustments = self.adjust_steps(autoderef); self.record_deferred_call_resolution( def_id, @@ -259,11 +260,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::CoroutineClosure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { let def_id = def_id.expect_local(); let closure_args = args.as_coroutine_closure(); - let coroutine_closure_sig = self.instantiate_binder_with_fresh_vars( - call_expr.span, - BoundRegionConversionTime::FnCall, - closure_args.coroutine_closure_sig(), - ); + let coroutine_closure_sig = self + .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + call_expr.span, + BoundRegionConversionTime::FnCall, + closure_args.coroutine_closure_sig(), + ); 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 @@ -589,7 +591,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.into()); 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..39b8ef6c1ebe1 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -20,6 +20,7 @@ use rustc_span::def_id::LocalDefId; use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::traits::ArgKind; use rustc_trait_selection::traits; +use rustc_trait_selection::traits::NormalizeExt; use tracing::{debug, instrument, trace}; use super::{CoroutineTypes, Expectation, FnCtxt, check_fn}; @@ -823,11 +824,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796 self.commit_if_ok(|_| { let mut all_obligations = PredicateObligations::new(); - let supplied_sig = self.instantiate_binder_with_fresh_vars( - self.tcx.def_span(expr_def_id), - BoundRegionConversionTime::FnCall, - supplied_sig, - ); + let supplied_sig = self + .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( + self.tcx.def_span(expr_def_id), + BoundRegionConversionTime::FnCall, + supplied_sig, + |value| { + // FIXME: a proper cause? + let cause = self.misc(DUMMY_SP); + let InferOk { value, obligations } = + self.at(&cause, self.param_env).renormalize_ambiguous_aliases(value); + all_obligations.extend(obligations); + value + }, + ); // 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 f1d9100a1d5f6..3c07214aa0bd4 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -647,11 +647,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = call_expr_and_args .and_then(|(_, args)| args.get(i)) .map_or(expr.span, |arg| arg.span); - let input = self.instantiate_binder_with_fresh_vars( - span, - infer::BoundRegionConversionTime::FnCall, - fn_sig.input(i), - ); + let input = self + .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + span, + infer::BoundRegionConversionTime::FnCall, + fn_sig.input(i), + ); self.require_type_is_sized_deferred( input, span, @@ -664,7 +665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Also, as we just want to check sizedness, instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. - let output = self.instantiate_binder_with_fresh_vars( + let output = self.instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( expr.span, infer::BoundRegionConversionTime::FnCall, fn_sig.output(), @@ -1571,11 +1572,12 @@ 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_renormalize_ambiguous_aliases( + inner_expr.span, + infer::BoundRegionConversionTime::HigherRankedType, + binder.into(), + ), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { let guar = self @@ -1608,11 +1610,12 @@ 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_renormalize_ambiguous_aliases( + inner_expr.span, + infer::BoundRegionConversionTime::HigherRankedType, + binder.into(), + ), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { let guar = self diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index db5994bca3d3d..5d5712326cd87 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -20,7 +20,7 @@ use rustc_hir_analysis::hir_ty_lowering::{ GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; -use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferResult}; use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, @@ -435,6 +435,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } + pub(crate) fn instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + &self, + span: Span, + lbrct: BoundRegionConversionTime, + value: ty::Binder<'tcx, T>, + ) -> T + where + T: TypeFoldable> + Copy, + { + self.instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( + span, + lbrct, + value, + |value| { + self.register_infer_ok_obligations( + self.at(&self.misc(span), self.param_env).renormalize_ambiguous_aliases(value), + ) + }, + ) + } + pub(crate) fn require_type_meets( &self, ty: Ty<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 415630dab38b3..6d91eb18398d7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -3034,11 +3034,13 @@ 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_renormalize_ambiguous_aliases( + call_name.span, + BoundRegionConversionTime::FnCall, + fn_sig, + ); } None } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 5fea7454e57ea..a9b7305efdbd9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -394,7 +394,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { item_segment: &rustc_hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> { - let trait_ref = self.instantiate_binder_with_fresh_vars( + let trait_ref = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( span, // FIXME(mgca): `item_def_id` can be an AssocConst; rename this variant. infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id), diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 0c83c1948d6f2..65ce0427a6cd4 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -792,7 +792,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { where T: TypeFoldable> + Copy, { - self.fcx.instantiate_binder_with_fresh_vars( + self.fcx.instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( self.span, BoundRegionConversionTime::FnCall, value, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 49126ff0e964c..361e0d61ddf93 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -15,7 +15,7 @@ use rustc_infer::infer::{BoundRegionConversionTime, InferOk}; use rustc_infer::traits::PredicateObligations; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt, Unnormalized, + self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol}; @@ -421,15 +421,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // N.B., instantiate late-bound regions before normalizing the // function signature so that normalization does not need to deal // with bound regions. - let fn_sig = tcx.fn_sig(def_id).instantiate(self.tcx, args).skip_norm_wip(); - let fn_sig = self.instantiate_binder_with_fresh_vars( - obligation.cause.span, - BoundRegionConversionTime::FnCall, - fn_sig, - ); - + let fn_sig = tcx.fn_sig(def_id).instantiate(self.tcx, args).map(|sig| { + self.instantiate_binder_with_fresh_vars( + obligation.cause.span, + BoundRegionConversionTime::FnCall, + sig, + ) + .skip_normalization() + }); let InferOk { value: fn_sig, obligations: o } = - self.at(&obligation.cause, self.param_env).normalize(Unnormalized::new_wip(fn_sig)); + self.at(&obligation.cause, self.param_env).normalize(fn_sig); obligations.extend(o); // Register obligations for the parameters. This will include the diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 4258896deec70..ad9b727f72145 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1073,13 +1073,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { match method.kind { ty::AssocKind::Fn { .. } => self.probe(|_| { let args = self.fresh_args_for_item(self.span, method.def_id); - let fty = - self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args).skip_norm_wip(); - let fty = self.instantiate_binder_with_fresh_vars( - self.span, - BoundRegionConversionTime::FnCall, - fty, - ); + let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args).map(|sig| { + self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + self.span, + BoundRegionConversionTime::FnCall, + sig, + ) + }); + let fty = self.normalize(self.span, fty); self.can_eq(self.param_env, fty.output(), expected) }), _ => false, @@ -1901,11 +1902,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref, _) => self.probe(|_| { - let trait_ref = self.instantiate_binder_with_fresh_vars( - self.span, - BoundRegionConversionTime::FnCall, - trait_ref, - ); + let trait_ref = self + .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + self.span, + BoundRegionConversionTime::FnCall, + trait_ref, + ); 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 @@ -2035,13 +2037,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - let trait_ref = self.instantiate_binder_with_fresh_vars( - self.span, - BoundRegionConversionTime::FnCall, - poly_trait_ref, - ); - let trait_ref = - ocx.normalize(cause, self.param_env, Unnormalized::new_wip(trait_ref)); + let trait_ref = self + .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( + self.span, + BoundRegionConversionTime::FnCall, + poly_trait_ref, + |value| ocx.renormalize_ambiguous_aliases(cause, self.param_env, value), + ); (xform_self_ty, xform_ret_ty) = self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); xform_self_ty = @@ -2100,11 +2102,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { trait_predicate = Some(trait_ref.upcast(self.tcx)); } ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => { - let trait_ref = self.instantiate_binder_with_fresh_vars( - self.span, - BoundRegionConversionTime::FnCall, - poly_trait_ref, - ); + // If we normalize the whole trait ref, this candidate can fail. + // Unsure if that's desirable. See + // `tests/ui/traits/trait-upcasting/mono-impossible.rs`. + let trait_ref = self + .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( + self.span, + BoundRegionConversionTime::FnCall, + poly_trait_ref, + |value| value.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 7bebe72971a9e..8344cc9911b23 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2286,12 +2286,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if def_kind == DefKind::AssocFn { let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id); let fn_sig = - tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args).skip_norm_wip(); - let fn_sig = self.instantiate_binder_with_fresh_vars( - span, - BoundRegionConversionTime::FnCall, - fn_sig, - ); + tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args).map(|sig| { + self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + span, + BoundRegionConversionTime::FnCall, + sig, + ) + }); + let fn_sig = self.normalize(span, fn_sig); if similar_candidate.is_method() { if let Some(args) = args && fn_sig.inputs()[1..].len() == args.len() @@ -2373,12 +2375,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .fn_sig(inherent_method.def_id) .instantiate(self.tcx, args) - .skip_norm_wip(); - let fn_sig = self.instantiate_binder_with_fresh_vars( - item_name.span, - BoundRegionConversionTime::FnCall, - fn_sig, - ); + .map(|sig| { + self.instantiate_binder_with_fresh_vars( + item_name.span, + BoundRegionConversionTime::FnCall, + sig, + ) + .skip_normalization() + }); + let fn_sig = self.normalize(item_name.span, fn_sig); 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 fc0c4bb0d5f5e..0a13969fd8c37 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -201,7 +201,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn instantiate_binder_with_infer> + Copy>( &self, value: ty::Binder<'tcx, T>, - ) -> T { + ) -> ty::UnnormalizedAmbiguous<'tcx, T> { self.instantiate_binder_with_fresh_vars( DUMMY_SP, BoundRegionConversionTime::HigherRankedType, @@ -212,7 +212,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::UnnormalizedAmbiguous<'tcx, T>) -> U, ) -> U { self.enter_forall(value, f) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c0029719c6e12..cd2006d327432 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -850,13 +850,16 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { - if a_is_expected { - Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) - } else { - Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a)) - } - }) + self.enter_forall_no_ambiguous_aliases( + predicate, + |ty::SubtypePredicate { a_is_expected, a, b }| { + if a_is_expected { + Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) + } else { + Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a)) + } + }, + ) } /// Number of type variables created so far. @@ -1376,6 +1379,34 @@ impl<'tcx> InferCtxt<'tcx> { } } + pub fn instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( + &self, + span: Span, + lbrct: BoundRegionConversionTime, + value: ty::Binder<'tcx, T>, + mut renormalize_ambig: F, + ) -> T + where + T: TypeFoldable> + Copy, + F: FnMut(ty::UnnormalizedAmbiguous<'tcx, T>) -> T, + { + let instantiated = self.instantiate_binder_with_fresh_vars(span, lbrct, value); + renormalize_ambig(instantiated) + } + + pub fn instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + &self, + span: Span, + lbrct: BoundRegionConversionTime, + value: ty::Binder<'tcx, T>, + ) -> T + where + T: TypeFoldable> + Copy, + { + debug_assert!(!value.has_ambiguous_aliases()); + self.instantiate_binder_with_fresh_vars(span, lbrct, value).skip_normalization() + } + // Instantiates the bound variables in a given binder with fresh inference // variables in the current universe. // @@ -1383,17 +1414,22 @@ impl<'tcx> InferCtxt<'tcx> { // 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. + // + // You shouldn't use this method directly. Have a look at its wrappers. + // FIXME: I really want to make this method private. But it's needed for one use case: + // a full normalization after instantiating binder where the value can contain ambiguous + // aliases. Maybe add another wrapper for that use case? pub fn instantiate_binder_with_fresh_vars( &self, span: Span, lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, - ) -> T + ) -> ty::UnnormalizedAmbiguous<'tcx, T> where T: TypeFoldable> + Copy, { if let Some(inner) = value.no_bound_vars() { - return inner; + return ty::UnnormalizedAmbiguous::new(inner); } let bound_vars = value.bound_vars(); @@ -1426,7 +1462,7 @@ impl<'tcx> InferCtxt<'tcx> { } } let delegate = ToFreshVars { args }; - self.tcx.replace_bound_vars_uncached(value, delegate) + ty::UnnormalizedAmbiguous::new(self.tcx.replace_bound_vars_uncached(value, delegate)) } /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 324725a079bbe..e92479a76d4c9 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -20,8 +20,29 @@ impl<'tcx> InferCtxt<'tcx> { /// `fn enter_forall` should be preferred over this method. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - #[instrument(level = "debug", skip(self), ret)] + /// + /// This is expected to be used in the old solver only so no ambiguous aliases allowed. pub fn enter_forall_and_leak_universe(&self, binder: ty::Binder<'tcx, T>) -> T + where + T: TypeFoldable>, + { + debug_assert!(!binder.has_ambiguous_aliases()); + self.enter_forall_and_leak_universe_inner(binder) + } + + /// Same as `enter_forall_and_leak_universe`, but we allow ambiguous aliases here. + pub fn enter_forall_and_leak_universe_for_diagnostics( + &self, + binder: ty::Binder<'tcx, T>, + ) -> T + where + T: TypeFoldable>, + { + self.enter_forall_and_leak_universe_inner(binder) + } + + #[instrument(level = "debug", skip(self), ret)] + fn enter_forall_and_leak_universe_inner(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable>, { @@ -63,7 +84,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::UnnormalizedAmbiguous<'tcx, T>) -> U, + ) -> U where T: TypeFoldable>, { @@ -71,6 +96,20 @@ 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_inner(forall); + debug!(?value); + f(ty::UnnormalizedAmbiguous::new(value)) + } + + #[instrument(level = "debug", skip(self, f))] + pub fn enter_forall_no_ambiguous_aliases( + &self, + forall: ty::Binder<'tcx, T>, + f: impl FnOnce(T) -> U, + ) -> U + where + T: TypeFoldable>, + { let value = self.enter_forall_and_leak_universe(forall); debug!(?value); f(value) diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 595392fcfb524..f0751631beea9 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -299,14 +299,22 @@ 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 a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); + infcx.enter_forall_no_ambiguous_aliases(b, |b| { + let a = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + span, + HigherRankedType, + a, + ); self.relate(a, b) })?; } ty::Contravariant => { - infcx.enter_forall(a, |a| { - let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); + infcx.enter_forall_no_ambiguous_aliases(a, |a| { + let b = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + span, + HigherRankedType, + b, + ); self.relate(a, b) })?; } @@ -322,14 +330,22 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`. // Check if `exists<..> A == for<..> B` ty::Invariant => { - infcx.enter_forall(b, |b| { - let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); + infcx.enter_forall_no_ambiguous_aliases(b, |b| { + let a = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + span, + HigherRankedType, + a, + ); 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); + infcx.enter_forall_no_ambiguous_aliases(a, |a| { + let b = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + span, + HigherRankedType, + b, + ); 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 6b19aa17c6d6c..d3bee1970b25c 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { .iter_identity_copied() .map(Unnormalized::skip_norm_wip) { - infcx.enter_forall(pred.kind(), |predicate| { + infcx.enter_forall_no_ambiguous_aliases(pred.kind(), |predicate| { let ty::ClauseKind::Projection(proj) = predicate else { return; }; 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 054e809900e43..14e1ca5618a06 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 @@ -885,7 +885,8 @@ 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(param_env, trait_ref).map_err(|_| Ambiguous)?; 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 @@ -972,7 +973,8 @@ where .ecx .probe(|_| ProbeKind::ProjectionCompatibility) .enter_without_propagated_nested_goals(|ecx| { - let source_projection = ecx.instantiate_binder_with_infer(source_projection); + let source_projection = + ecx.instantiate_binder_with_infer(self.param_env, source_projection)?; ecx.eq(self.param_env, source_projection.projection_term, target_projection)?; ecx.try_evaluate_added_goals() }) @@ -1013,7 +1015,10 @@ where return Err(Ambiguous); } - let replacement = self.ecx.instantiate_binder_with_infer(*replacement); + let replacement = self + .ecx + .instantiate_binder_with_infer(self.param_env, *replacement) + .map_err(|_| Ambiguous)?; 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 0a260f97e5164..db6b3d110c1ea 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -66,7 +66,8 @@ where ) -> QueryResultOrRerunNonErased { 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(goal.param_env, host_clause)?; ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; then(ecx) @@ -271,7 +272,8 @@ where ) }), ); - }); + Ok(()) + })?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -295,7 +297,8 @@ 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(goal.param_env, inputs_and_output)?; // 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 fe2404ca69662..7f6290db9ff71 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 @@ -880,6 +880,7 @@ where } }) }) + .map_err(Into::into) } // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning @@ -1322,10 +1323,12 @@ where } pub(super) fn instantiate_binder_with_infer + Copy>( - &self, + &mut self, + param_env: I::ParamEnv, value: ty::Binder, - ) -> T { - self.delegate.instantiate_binder_with_infer(value) + ) -> Result { + let instantiated = self.delegate.instantiate_binder_with_infer(value); + self.normalize_ambiguous_only(param_env, instantiated) } /// `enter_forall`, but takes `&mut self` and passes it back through the @@ -1339,9 +1342,10 @@ where &mut self, value: ty::Binder, param_env: I::ParamEnv, - f: impl FnOnce(&mut Self, T) -> U, - ) -> U { + f: impl FnOnce(&mut Self, T) -> Result, + ) -> Result { self.delegate.enter_forall(value, |value| { + let value = self.normalize_ambiguous_only(param_env, value)?; let u = self.delegate.universe(); let assumptions = if self.cx().assumptions_on_binders() { self.region_assumptions_for_placeholders_in_universe(value.clone(), u, param_env) 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 3b3620a27b5da..b94b86eac6d5e 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 @@ -192,7 +192,8 @@ where ) -> QueryResultOrRerunNonErased { 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(goal.param_env, projection_pred)?; ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); @@ -493,7 +494,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(goal.param_env, tupled_inputs_and_output)?; // 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...) @@ -544,7 +546,10 @@ 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( + goal.param_env, + tupled_inputs_and_output_and_coroutine, + )?; // 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 f3ace5a70c69c..f81393dbfa099 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,8 @@ 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(goal.param_env, trait_clause)?; ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; then(ecx) @@ -381,7 +382,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(goal.param_env, tupled_inputs_and_output)?; // 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...) @@ -423,7 +425,10 @@ 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( + goal.param_env, + tupled_inputs_and_output_and_coroutine, + )?; // 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...) @@ -1076,8 +1081,10 @@ where target_projection, param_env, |ecx, target_projection| { - let source_projection = - ecx.instantiate_binder_with_infer(source_projection); + let source_projection = ecx.instantiate_binder_with_infer( + param_env, + source_projection, + )?; ecx.eq(param_env, source_projection, target_projection)?; ecx.try_evaluate_added_goals() }, @@ -1100,7 +1107,7 @@ where param_env, |ecx, target_principal| { let source_principal = - ecx.instantiate_binder_with_infer(source_principal); + ecx.instantiate_binder_with_infer(param_env, source_principal)?; ecx.eq(param_env, source_principal, target_principal)?; ecx.try_evaluate_added_goals() }, @@ -1131,8 +1138,8 @@ where target_projection, param_env, |ecx, target_projection| { - let source_projection = - ecx.instantiate_binder_with_infer(source_projection); + let source_projection = ecx + .instantiate_binder_with_infer(param_env, source_projection)?; ecx.eq(param_env, source_projection, target_projection)?; ecx.try_evaluate_added_goals() }, @@ -1365,13 +1372,14 @@ where constituent_tys(ecx, goal.predicate.self_ty())?, goal.param_env, |ecx, tys| { - tys.into_iter() + Ok(tys + .into_iter() .map(|ty| { goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty)) }) - .collect::>() + .collect::>()) }, - ); + )?; ecx.add_goals(GoalSource::ImplWhereBound, goals); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) 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..205a6abecb4de 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -40,7 +40,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( let impl_may_apply = |impl_def_id| { let ocx = ObligationCtxt::new(infcx); - infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + infcx.enter_forall_no_ambiguous_aliases(obligation.predicate, |placeholder_obligation| { let obligation_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, @@ -98,18 +98,19 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| { let ocx = ObligationCtxt::new(infcx); - infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + infcx.enter_forall_no_ambiguous_aliases(obligation.predicate, |placeholder_obligation| { let obligation_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, Unnormalized::new_wip(placeholder_obligation.trait_ref), ); - let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - poly_trait_predicate, - ); + let param_env_predicate = infcx + .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + poly_trait_predicate, + ); let param_env_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, 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 083a1d8ea91cd..457ad0c28c05e 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 @@ -833,8 +833,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { diag.downgrade_to_delayed_bug(); } - if let Ok(Some(ImplSource::UserDefined(impl_data))) = - self.enter_forall(trait_ref, |trait_ref_for_select| { + if let Ok(Some(ImplSource::UserDefined(impl_data))) = self + .enter_forall_no_ambiguous_aliases(trait_ref, |trait_ref_for_select| { SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref_for_select)) }) { @@ -958,8 +958,8 @@ 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| { - self.enter_forall(expected_args, |expected_args| { + if self.enter_forall_no_ambiguous_aliases(found_args, |found_args| { + self.enter_forall_no_ambiguous_aliases(expected_args, |expected_args| { !self.can_eq(obligation.param_env, expected_args, found_args) }) }) { @@ -1402,7 +1402,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut pred = obligation.predicate.as_trait_clause(); while let Some((next_code, next_pred)) = code.parent_with_predicate() { if let Some(pred) = pred { - self.enter_forall(pred, |pred| { + self.enter_forall_no_ambiguous_aliases(pred, |pred| { let ty = self.tcx.short_string(pred.self_ty(), diag.long_ty_path()); let trait_path = self .tcx @@ -1430,7 +1430,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; } - let trait_assumption = self.instantiate_binder_with_fresh_vars( + let trait_assumption = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( DUMMY_SP, infer::BoundRegionConversionTime::HigherRankedType, assumption, @@ -1445,7 +1445,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { goal: ty::HostEffectPredicate<'tcx>, assumption: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, ) -> bool { - let assumption = self.instantiate_binder_with_fresh_vars( + let assumption = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( DUMMY_SP, infer::BoundRegionConversionTime::HigherRankedType, assumption, @@ -1470,7 +1470,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { goal: ty::ProjectionPredicate<'tcx>, assumption: ty::PolyProjectionPredicate<'tcx>, ) -> bool { - let assumption = self.instantiate_binder_with_fresh_vars( + let assumption = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( DUMMY_SP, infer::BoundRegionConversionTime::HigherRankedType, assumption, @@ -1501,19 +1501,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let param_env = error.param_env; if let Some(error) = error.predicate.as_trait_clause() { - self.enter_forall(error, |error| { + self.enter_forall_no_ambiguous_aliases(error, |error| { 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| { + self.enter_forall_no_ambiguous_aliases(error, |error| { 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| { + self.enter_forall_no_ambiguous_aliases(error, |error| { 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)) @@ -1545,7 +1545,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { let ocx = ObligationCtxt::new(self); - let data = self.instantiate_binder_with_fresh_vars( + let data = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( obligation.cause.span, infer::BoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), @@ -2078,7 +2078,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if self.probe(|_| { let ocx = ObligationCtxt::new(self); - self.enter_forall(trait_pred, |obligation_trait_ref| { + self.enter_forall_no_ambiguous_aliases(trait_pred, |obligation_trait_ref| { 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 26139926dae41..bde878a756fe3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1014,7 +1014,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; } - let self_ty = self.instantiate_binder_with_fresh_vars( + let self_ty = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( DUMMY_SP, BoundRegionConversionTime::FnCall, trait_pred.self_ty(), @@ -1346,7 +1346,7 @@ 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_no_ambiguous_aliases(self_ty, |ty: Ty<'_>| { let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_id) else { return false; }; @@ -1558,7 +1558,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; }; - let output = self.instantiate_binder_with_fresh_vars( + let output = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( DUMMY_SP, BoundRegionConversionTime::FnCall, output, @@ -1567,7 +1567,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .skip_binder() .iter() .map(|ty| { - self.instantiate_binder_with_fresh_vars( + self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( DUMMY_SP, BoundRegionConversionTime::FnCall, inputs.rebind(*ty), @@ -4845,12 +4845,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some(failed_pred) = failed_pred.as_trait_clause() && where_pred.def_id() == failed_pred.def_id() { - self.enter_forall(where_pred, |where_pred| { - let failed_pred = self.instantiate_binder_with_fresh_vars( - expr.span, - BoundRegionConversionTime::FnCall, - failed_pred, - ); + self.enter_forall_no_ambiguous_aliases(where_pred, |where_pred| { + let failed_pred = self + .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + expr.span, + BoundRegionConversionTime::FnCall, + failed_pred, + ); let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); @@ -5588,7 +5589,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { self.probe(|_| { let ocx = ObligationCtxt::new(self); - self.enter_forall(pred, |pred| { + self.enter_forall_no_ambiguous_aliases(pred, |pred| { let pred = ocx.normalize( &ObligationCause::dummy(), param_env, @@ -6061,13 +6062,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_no_ambiguous_aliases(*sig_tys, |sig_tys| sig_tys.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_no_ambiguous_aliases(*sig_tys, |sig_tys| sig_tys.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/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 46f920cd9629e..9cc30730e0997 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -59,14 +59,14 @@ 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( + let (a, b) = infcx.enter_forall_and_leak_universe_for_diagnostics( obligation.predicate.kind().rebind((pred.a, pred.b)), ); 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( + let (a, b) = infcx.enter_forall_and_leak_universe_for_diagnostics( obligation.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(b, a); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 646945990a1d5..44e331f6bb2fa 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -739,7 +739,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); - selcx.infcx.enter_forall(binder, |pred| { + selcx.infcx.enter_forall_no_ambiguous_aliases(binder, |pred| { selcx.infcx.register_region_outlives_constraint(pred, ty::VisibleForLeakCheck::Yes,&dummy_cause); }); } diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 8681a92f57ecb..b3097006d0d9a 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -89,7 +89,7 @@ fn match_candidate<'tcx>( return Err(NoSolution); } - let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars( + let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, candidate, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index f8715824e8eea..9a5ea15540515 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1910,7 +1910,7 @@ 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_no_ambiguous_aliases( cause.span, BoundRegionConversionTime::HigherRankedType, poly_cache_entry, 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 1978d4dd5af8b..a161154692fd7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -924,57 +924,60 @@ 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 self_ty = placeholder_trait_predicate.self_ty(); - let principal_trait_ref = match self_ty.kind() { - ty::Dynamic(data, ..) => { - if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { - debug!( - "assemble_candidates_from_object_ty: matched builtin bound, \ - pushing candidate" - ); - candidates.vec.push(BuiltinObjectCandidate); - return; - } + self.infcx.enter_forall_no_ambiguous_aliases( + poly_trait_predicate, + |placeholder_trait_predicate| { + let self_ty = placeholder_trait_predicate.self_ty(); + let principal_trait_ref = match self_ty.kind() { + ty::Dynamic(data, ..) => { + if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { + debug!( + "assemble_candidates_from_object_ty: matched builtin bound, \ + pushing candidate" + ); + candidates.vec.push(BuiltinObjectCandidate); + return; + } - if let Some(principal) = data.principal() { - principal.with_self_ty(self.tcx(), self_ty) - } else { - // Only auto trait bounds exist. + if let Some(principal) = data.principal() { + principal.with_self_ty(self.tcx(), self_ty) + } else { + // Only auto trait bounds exist. + return; + } + } + ty::Infer(ty::TyVar(_)) => { + debug!("assemble_candidates_from_object_ty: ambiguous"); + candidates.ambiguous = true; // could wind up being an object type return; } - } - ty::Infer(ty::TyVar(_)) => { - debug!("assemble_candidates_from_object_ty: ambiguous"); - candidates.ambiguous = true; // could wind up being an object type - return; - } - _ => return, - }; - - debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); + _ => return, + }; - // Count only those upcast versions that match the trait-ref - // we are looking for. Specifically, do not only check for the - // correct trait, but also the correct type parameters. - // For example, we may be trying to upcast `Foo` to `Bar`, - // but `Foo` is declared as `trait Foo: Bar`. - let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) - .enumerate() - .filter(|&(_, upcast_trait_ref)| { - self.infcx.probe(|_| { - self.match_normalize_trait_ref( - obligation, - placeholder_trait_predicate.trait_ref, - upcast_trait_ref, - ) - .is_ok() + debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); + + // Count only those upcast versions that match the trait-ref + // we are looking for. Specifically, do not only check for the + // correct trait, but also the correct type parameters. + // For example, we may be trying to upcast `Foo` to `Bar`, + // but `Foo` is declared as `trait Foo: Bar`. + let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) + .enumerate() + .filter(|&(_, upcast_trait_ref)| { + self.infcx.probe(|_| { + self.match_normalize_trait_ref( + obligation, + placeholder_trait_predicate.trait_ref, + upcast_trait_ref, + ) + .is_ok() + }) }) - }) - .map(|(idx, _)| ObjectCandidate(idx)); + .map(|(idx, _)| ObjectCandidate(idx)); - candidates.vec.extend(candidate_supertraits); - }) + candidates.vec.extend(candidate_supertraits); + }, + ) }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 11ce6235eb7ff..cd13912969e0c 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_no_ambiguous_aliases( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, candidate, @@ -499,7 +499,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let object_trait_ref = data.principal().unwrap_or_else(|| { span_bug!(obligation.cause.span, "object candidate with no principal") }); - let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( + let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, object_trait_ref, @@ -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_no_ambiguous_aliases( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, unnormalized_upcast_trait_ref, @@ -962,7 +962,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: TraitObligation<'tcx>, found_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result, SelectionError<'tcx>> { - let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( + let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, found_trait_ref, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e47a9e0311918..d7f49c1cfe437 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -624,8 +624,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.evaluate_trait_predicate_recursively(previous_stack, obligation) } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => { - self.infcx.enter_forall(bound_predicate.rebind(data), |data| { + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => self + .infcx + .enter_forall_no_ambiguous_aliases(bound_predicate.rebind(data), |data| { match effects::evaluate_host_effect_obligation( self, &obligation.with(self.tcx(), data), @@ -636,8 +637,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(effects::EvaluationFailure::Ambiguous) => Ok(EvaluatedToAmbig), Err(effects::EvaluationFailure::NoSolution) => Ok(EvaluatedToErr), } - }) - } + }), ty::PredicateKind::Subtype(p) => { let p = bound_predicate.rebind(p); @@ -1721,7 +1721,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_no_ambiguous_aliases( obligation.cause.span, HigherRankedType, trait_bound, @@ -1778,7 +1778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug_assert_eq!(obligation.predicate.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_no_ambiguous_aliases( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, env_predicate, @@ -2623,24 +2623,28 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx - .enter_forall(hr_target_principal, |target_principal| { - let source_principal = - self.infcx.instantiate_binder_with_fresh_vars( - obligation.cause.span, - HigherRankedType, - hr_source_principal, - ); - self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( - DefineOpaqueTypes::Yes, - ToTrace::to_trace( - &obligation.cause, - hr_target_principal, - hr_source_principal, - ), - target_principal, - source_principal, - ) - }) + .enter_forall_no_ambiguous_aliases( + hr_target_principal, + |target_principal| { + let source_principal = self + .infcx + .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + obligation.cause.span, + HigherRankedType, + hr_source_principal, + ); + self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + hr_target_principal, + hr_source_principal, + ), + target_principal, + source_principal, + ) + }, + ) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); @@ -2659,27 +2663,23 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // here instead of equating and processing obligations. hr_source_projection.item_def_id() == hr_target_projection.item_def_id() && self.infcx.probe(|_| { - self.infcx - .enter_forall(hr_target_projection, |target_projection| { - let source_projection = - self.infcx.instantiate_binder_with_fresh_vars( - obligation.cause.span, - HigherRankedType, + self.infcx.enter_forall_no_ambiguous_aliases(hr_target_projection, + |target_projection| { + let source_projection = + self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases(obligation.cause.span, HigherRankedType, hr_source_projection); + self.infcx + .at(&obligation.cause, obligation.param_env) + .eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + hr_target_projection, hr_source_projection, - ); - self.infcx - .at(&obligation.cause, obligation.param_env) - .eq_trace( - DefineOpaqueTypes::Yes, - ToTrace::to_trace( - &obligation.cause, - hr_target_projection, - hr_source_projection, - ), - target_projection, - source_projection, - ) - }) + ), + target_projection, + source_projection, + ) + },) .is_ok() }) }); @@ -2692,24 +2692,28 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } nested.extend( self.infcx - .enter_forall(hr_target_projection, |target_projection| { - let source_projection = - self.infcx.instantiate_binder_with_fresh_vars( - obligation.cause.span, - HigherRankedType, - hr_source_projection, - ); - self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( - DefineOpaqueTypes::Yes, - ToTrace::to_trace( - &obligation.cause, - hr_target_projection, - hr_source_projection, - ), - target_projection, - source_projection, - ) - }) + .enter_forall_no_ambiguous_aliases( + hr_target_projection, + |target_projection| { + let source_projection = self + .infcx + .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + obligation.cause.span, + HigherRankedType, + hr_source_projection, + ); + self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + hr_target_projection, + hr_source_projection, + ), + target_projection, + source_projection, + ) + }, + ) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); @@ -2754,7 +2758,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result, ()> { let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); - let trait_ref = self.infcx.instantiate_binder_with_fresh_vars( + let trait_ref = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( obligation.cause.span, HigherRankedType, poly_trait_ref, diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 7957bacda5677..c00e2e7922915 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -391,12 +391,12 @@ pub trait InferCtxtLike: Sized { fn instantiate_binder_with_infer + Copy>( &self, value: ty::Binder, - ) -> T; + ) -> ty::UnnormalizedAmbiguous; fn enter_forall, U>( &self, value: ty::Binder, - f: impl FnOnce(T) -> U, + f: impl FnOnce(ty::UnnormalizedAmbiguous) -> U, ) -> U; fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index ab9553da42f89..d784dbd767599 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -1096,13 +1096,14 @@ fn alias_outlives_candidates_from_assumptions let prev_universe = infcx.universe(); // FIXME(-Zassumptions-on-binders): Handle the assumptions on this binder - infcx.enter_forall(bound_outlives, |(alias, r)| { + infcx.enter_forall(bound_outlives, |bound_outlives| { + let (alias, r) = bound_outlives.skip_norm_wip(); let u = infcx.universe(); infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); for bound_type_outlives in assumptions.type_outlives.iter() { let OutlivesPredicate(alias2, r2) = - infcx.instantiate_binder_with_infer(*bound_type_outlives); + infcx.instantiate_binder_with_infer(*bound_type_outlives).skip_norm_wip(); let mut relation = HigherRankedAliasMatcher { infcx, @@ -1187,16 +1188,18 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> TypeRelation T: Relate, { self.infcx.enter_forall(a, |a| { + let a = a.skip_norm_wip(); let u = self.infcx.universe(); self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); - 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) })?; self.infcx.enter_forall(b, |b| { + let b = b.skip_norm_wip(); let u = self.infcx.universe(); self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); - 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) })?; diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index a643d22c17643..022d9cf17ac4b 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -312,13 +312,15 @@ 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 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 b = self.infcx.instantiate_binder_with_infer(b); + let a = a.skip_norm_wip(); + let b = self.infcx.instantiate_binder_with_infer(b).skip_norm_wip(); self.relate(a, b) })?; } @@ -335,13 +337,15 @@ 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 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 b = self.infcx.instantiate_binder_with_infer(b); + let a = a.skip_norm_wip(); + let b = self.infcx.instantiate_binder_with_infer(b).skip_norm_wip(); self.relate(a, b) })?; } From fdf44a2e8479d9c5cc78132d3181745c05b64bfa Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 13 May 2026 17:13:16 +0800 Subject: [PATCH 07/38] renormalize inside solver relating --- .../src/relate/solver_relating.rs | 117 ++++++++++++++++-- 1 file changed, 108 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 022d9cf17ac4b..ddcdadc4b742c 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -5,7 +5,7 @@ use crate::data_structures::DelayedSet; use crate::relate::combine::combine_ty_args; pub use crate::relate::*; use crate::solve::{Goal, VisibleForLeakCheck}; -use crate::{self as ty, InferCtxtLike, Interner}; +use crate::{self as ty, InferCtxtLike, Interner, TypeFolder, TypeSuperFoldable, TypeVisitableExt}; pub trait RelateExt: InferCtxtLike { fn relate>( @@ -129,6 +129,17 @@ where cache: Default::default(), } } + + fn normalize_ambiguous_aliases>( + &mut self, + value: ty::UnnormalizedAmbiguous, + ) -> T { + let value = value.skip_normalization(); + let mut replacer = ReplaceAmbiguousAliasWithInfer::new(self.infcx, self.param_env); + let value = value.fold_with(&mut replacer); + self.register_goals(replacer.goals()); + value + } } impl TypeRelation for SolverRelating<'_, Infcx, I> @@ -312,15 +323,17 @@ 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(); + let b = self.normalize_ambiguous_aliases(b); + let a = self.infcx.instantiate_binder_with_infer(a); + let a = self.normalize_ambiguous_aliases(a); 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(); + let a = self.normalize_ambiguous_aliases(a); + let b = self.infcx.instantiate_binder_with_infer(b); + let b = self.normalize_ambiguous_aliases(b); self.relate(a, b) })?; } @@ -337,15 +350,17 @@ 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(); + let b = self.normalize_ambiguous_aliases(b); + let a = self.infcx.instantiate_binder_with_infer(a); + let a = self.normalize_ambiguous_aliases(a); 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(); + let a = self.normalize_ambiguous_aliases(a); + let b = self.infcx.instantiate_binder_with_infer(b); + let b = self.normalize_ambiguous_aliases(b); self.relate(a, b) })?; } @@ -411,3 +426,87 @@ where })]); } } + +// FIXME: this is a temporary solution for renomalizing ambiguous aliases +// inside solver relating. We may pursue actual normalization in the future. +pub struct ReplaceAmbiguousAliasWithInfer<'a, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + infcx: &'a Infcx, + param_env: I::ParamEnv, + goals: Vec>, +} + +impl<'a, Infcx, I> ReplaceAmbiguousAliasWithInfer<'a, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + pub fn new(infcx: &'a Infcx, param_env: I::ParamEnv) -> Self { + Self { infcx, param_env, goals: Vec::new() } + } + + pub fn goals(self) -> Vec> { + self.goals + } +} + +impl<'a, Infcx, I> TypeFolder for ReplaceAmbiguousAliasWithInfer<'a, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn cx(&self) -> I { + self.infcx.cx() + } + + fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + // Ambiguous aliases in nested binders will be handled when they're instantiated. + t + } + + #[instrument(level = "trace", skip(self), ret)] + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + debug_assert!(!ty.has_escaping_bound_vars()); + if !ty.has_ambiguous_aliases() { + return ty; + } + + // With eager normalization, we should normalize the args of alias before + // normalizing the alias itself. + let ty = ty.super_fold_with(self); + let ty::Alias(ty::AliasTy { kind: ty::AliasTyKind::Ambiguous, args, .. }) = ty.kind() + else { + return ty; + }; + + let original_alias = args.type_at(0); + + let infer_ty = self.infcx.next_ty_infer(); + let normalizes_to = ty::PredicateKind::AliasRelate( + original_alias.into(), + infer_ty.into(), + ty::AliasRelationDirection::Equate, + ); + self.goals.push(Goal::new(self.cx(), self.param_env, normalizes_to)); + infer_ty + } + + #[instrument(level = "trace", skip(self), ret)] + fn fold_const(&mut self, ct: I::Const) -> I::Const { + debug_assert!(!ct.has_escaping_bound_vars()); + if !ct.has_ambiguous_aliases() { + return ct; + } + + // With eager normalization, we should normalize the args of alias before + // normalizing the alias itself. + let ct = ct.super_fold_with(self); + let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct }; + // FIXME: add an new `Ambiguous` kind to `UnevaluatedConst` as well. + // As a field or a new kind on `ConstKind`? + ct + } +} From aaea957f616c73c7e5eec21d95db4883854d44a1 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 13 May 2026 18:57:10 +0800 Subject: [PATCH 08/38] make folders generic over error --- .../rustc_next_trait_solver/src/normalize.rs | 54 +++++++++---------- .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/solve/normalize.rs | 4 +- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 5b9ff95fc9a5d..b6d63c3086227 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -1,6 +1,9 @@ +use std::fmt::Debug; +use std::marker::PhantomData; + use rustc_type_ir::data_structures::ensure_sufficient_stack; use rustc_type_ir::inherent::*; -use rustc_type_ir::solve::{Goal, NoSolutionOrRerunNonErased}; +use rustc_type_ir::solve::Goal; use rustc_type_ir::{ self as ty, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, Interner, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -14,7 +17,7 @@ use crate::placeholder::{BoundVarReplacer, PlaceholderReplacer}; /// /// Note that for ambiguous alias which contains escaping bound vars, /// we just return the original alias and don't collect the ambiguous goal. -pub struct NormalizationFolder<'a, Infcx, I, F> +pub struct NormalizationFolder<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, I: Interner, @@ -23,6 +26,7 @@ where universes: Vec>, stalled_goals: Vec>, normalize: F, + _error: PhantomData, } #[derive(PartialEq, Eq)] @@ -109,13 +113,12 @@ enum NeedRenormalization { No, } -impl<'a, Infcx, I, F> NormalizationFolder<'a, Infcx, I, F> +impl<'a, Infcx, I, F, E> NormalizationFolder<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, I: Interner, - F: FnMut( - I::Term, - ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, + F: FnMut(I::Term) -> Result<(I::Term, Option>), E>, + E: Debug, { pub fn new( infcx: &'a Infcx, @@ -123,7 +126,7 @@ where stalled_goals: Vec>, normalize: F, ) -> Self { - Self { infcx, universes, stalled_goals, normalize } + Self { infcx, universes, stalled_goals, normalize, _error: PhantomData } } pub fn stalled_goals(self) -> Vec> { @@ -134,7 +137,7 @@ where &mut self, alias_term: I::Term, has_escaping: HasEscapingBoundVars, - ) -> Result<(I::Term, NeedRenormalization), NoSolutionOrRerunNonErased> { + ) -> Result<(I::Term, NeedRenormalization), E> { let current_universe = self.infcx.universe(); self.infcx.create_next_universe(); @@ -162,15 +165,14 @@ where } } -impl<'a, Infcx, I, F> FallibleTypeFolder for NormalizationFolder<'a, Infcx, I, F> +impl<'a, Infcx, I, F, E> FallibleTypeFolder for NormalizationFolder<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, I: Interner, - F: FnMut( - I::Term, - ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, + F: FnMut(I::Term) -> Result<(I::Term, Option>), E>, + E: Debug, { - type Error = NoSolutionOrRerunNonErased; + type Error = E; fn cx(&self) -> I { self.infcx.cx() @@ -274,7 +276,7 @@ where } // Only handle ambiguous alias in the outmost instantiated binder. -pub struct BinderRenormalizer<'a, Infcx, I, F> +pub struct BinderRenormalizer<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, I: Interner, @@ -282,28 +284,25 @@ where infcx: &'a Infcx, stalled_goals: Vec>, normalize: F, + _error: PhantomData, } -impl<'a, Infcx, I, F> BinderRenormalizer<'a, Infcx, I, F> +impl<'a, Infcx, I, F, E> BinderRenormalizer<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, I: Interner, - F: FnMut( - I::Term, - ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, + F: FnMut(I::Term) -> Result<(I::Term, Option>), E>, + E: Debug, { pub fn new(infcx: &'a Infcx, stalled_goals: Vec>, normalize: F) -> Self { - Self { infcx, stalled_goals, normalize } + Self { infcx, stalled_goals, normalize, _error: PhantomData } } pub fn stalled_goals(self) -> Vec> { self.stalled_goals } - fn normalize_alias_term( - &mut self, - alias_term: I::Term, - ) -> Result { + fn normalize_alias_term(&mut self, alias_term: I::Term) -> Result { let (normalized, ambig_goal) = (self.normalize)(alias_term)?; self.stalled_goals.extend(ambig_goal); @@ -311,15 +310,14 @@ where } } -impl<'a, Infcx, I, F> FallibleTypeFolder for BinderRenormalizer<'a, Infcx, I, F> +impl<'a, Infcx, I, F, E> FallibleTypeFolder for BinderRenormalizer<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, I: Interner, - F: FnMut( - I::Term, - ) -> Result<(I::Term, Option>), NoSolutionOrRerunNonErased>, + F: FnMut(I::Term) -> Result<(I::Term, Option>), E>, + E: Debug, { - type Error = NoSolutionOrRerunNonErased; + type Error = E; fn cx(&self) -> I { self.infcx.cx() 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 7f6290db9ff71..bf3394aa8cae1 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 @@ -1773,7 +1773,7 @@ where // To drop the mutable borrow of self early. let (normalized, stalled_goals) = { let infcx = self.delegate.deref(); - let normalize_term = |alias_term| { + let normalize_term = |alias_term| -> Result<_, NoSolutionOrRerunNonErased> { let delegate = self.delegate; let infer_term = self.next_term_infer_of_kind(alias_term); let predicate = ty::PredicateKind::AliasRelate( diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 707ae2d6a26e2..5c3f32eb34d78 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,6 +1,6 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::infer::at::At; -use rustc_infer::traits::solve::{Goal, NoSolutionOrRerunNonErased}; +use rustc_infer::traits::solve::{Goal, NoSolution}; use rustc_infer::traits::{ FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; @@ -50,7 +50,7 @@ where let value = value.skip_normalization(); let value = infcx.resolve_vars_if_possible(value); let original_value = value.clone(); - let normalize_term = |alias_term| -> Result<_, NoSolutionOrRerunNonErased> { + let normalize_term = |alias_term| -> Result<_, NoSolution> { let delegate = <&SolverDelegate<'tcx>>::from(infcx); let infer_term = delegate.next_term_var_of_kind(alias_term, at.cause.span); let predicate = ty::PredicateKind::AliasRelate( From 2e93e442b875d651931903816d7faed605ccf8b0 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 13 May 2026 19:23:06 +0800 Subject: [PATCH 09/38] revert and fix `opt_alias_variances` --- .../opaque_types/member_constraints.rs | 4 ++-- .../src/region_infer/opaque_types/mod.rs | 4 ++-- .../src/infer/outlives/for_liveness.rs | 4 ++-- .../src/infer/outlives/obligations.rs | 2 +- .../src/ty/context/impl_interner.rs | 7 +++++-- compiler/rustc_middle/src/ty/util.rs | 20 +++++++++++++------ compiler/rustc_type_ir/src/interner.rs | 5 ++++- compiler/rustc_type_ir/src/outlives.rs | 2 +- compiler/rustc_type_ir/src/relate.rs | 2 +- 9 files changed, 32 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs index 8989be90409e9..c057d99c6a41b 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs @@ -176,8 +176,8 @@ impl<'tcx> TypeVisitor> for CollectMemberConstraintsVisitor<'_, '_, | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.visit_closure_args(def_id, args), - ty::Alias(alias @ ty::AliasTy { args, .. }) - if let Some(variances) = self.cx().opt_alias_variances(alias) => + ty::Alias(ty::AliasTy { kind, args, .. }) + if let Some(variances) = self.cx().opt_alias_variances(kind) => { // Skip lifetime parameters that are not captured, since they do // not need member constraints registered for them; we'll erase diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index 176660c1555b3..1348f30b4c980 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -500,8 +500,8 @@ impl<'tcx> FallibleTypeFolder> for ToArgRegionsFolder<'_, 'tcx> { Ty::new_coroutine(tcx, def_id, self.fold_closure_args(def_id, args)?) } - ty::Alias(alias @ ty::AliasTy { kind, args, .. }) - if let Some(variances) = tcx.opt_alias_variances(alias) => + ty::Alias(ty::AliasTy { kind, args, .. }) + if let Some(variances) = tcx.opt_alias_variances(kind) => { let args = tcx.mk_args_from_iter(std::iter::zip(variances, args.iter()).map( |(&v, s)| { diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index a9e60cf64993c..b4594bd60f3ba 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -56,7 +56,7 @@ where // either `'static` or a unique outlives region, and if one is // found, we just need to prove that that region is still live. // If one is not found, then we continue to walk through the alias. - ty::Alias(alias @ ty::AliasTy { kind, args, .. }) => { + ty::Alias(ty::AliasTy { kind, args, .. }) => { let tcx = self.tcx; let param_env = self.param_env; let outlives_bounds: Vec<_> = tcx @@ -95,7 +95,7 @@ where } else { // Skip lifetime parameters that are not captured, since they do // not need to be live. - let variances = tcx.opt_alias_variances(alias); + let variances = tcx.opt_alias_variances(kind); for (idx, s) in args.iter().enumerate() { if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 594cc72ece2a2..5d6bd3fd4cac6 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -573,7 +573,7 @@ where && (alias_ty.has_infer_regions() || matches!(kind, ty::Opaque { .. })) { debug!("no declared bounds"); - let opt_variances = self.tcx.opt_alias_variances(alias_ty); + let opt_variances = self.tcx.opt_alias_variances(kind); self.args_must_outlive(alias_ty.args, origin, region, opt_variances); return; } diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 629c4dae24efa..7f1eeda4ad1d6 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -176,8 +176,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.variances_of(def_id) } - fn opt_alias_variances(self, alias: ty::AliasTy<'tcx>) -> Option<&'tcx [ty::Variance]> { - self.opt_alias_variances(alias) + fn opt_alias_variances( + self, + kind: impl Into>, + ) -> Option<&'tcx [ty::Variance]> { + self.opt_alias_variances(kind) } fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index bdbf1ae4881c0..c68c6d57c866f 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -914,18 +914,26 @@ impl<'tcx> TyCtxt<'tcx> { // Computes the variances for an alias (opaque or RPITIT) that represent // its (un)captured regions. - pub fn opt_alias_variances(self, alias: ty::AliasTy<'tcx>) -> Option<&'tcx [ty::Variance]> { - match alias.kind.reveal_ambiguous(alias.args) { - ty::Projection { def_id } => { + pub fn opt_alias_variances( + self, + kind: impl Into>, + ) -> Option<&'tcx [ty::Variance]> { + match kind.into() { + ty::AliasTermKind::ProjectionTy { def_id } => { if self.is_impl_trait_in_trait(def_id) { Some(self.variances_of(def_id)) } else { None } } - ty::Opaque { def_id } => Some(self.variances_of(def_id)), - ty::Inherent { .. } | ty::Free { .. } => None, - ty::Ambiguous => unreachable!(), + ty::AliasTermKind::OpaqueTy { def_id } => Some(self.variances_of(def_id)), + ty::AliasTermKind::AmbiguousTy => Some(&[ty::Variance::Covariant]), + ty::AliasTermKind::InherentTy { .. } + | ty::AliasTermKind::InherentConst { .. } + | ty::AliasTermKind::FreeTy { .. } + | ty::AliasTermKind::FreeConst { .. } + | ty::AliasTermKind::UnevaluatedConst { .. } + | ty::AliasTermKind::ProjectionConst { .. } => None, } } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 197f7228c1bbf..09def0212a153 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -225,7 +225,10 @@ pub trait Interner: type VariancesOf: Copy + Debug + SliceLike; fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf; - fn opt_alias_variances(self, alias: ty::AliasTy) -> Option; + fn opt_alias_variances( + self, + kind: impl Into>, + ) -> Option; fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder; fn type_of_opaque_hir_typeck( diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index dcbddb78ecdcd..2a1cbc3575d85 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -226,7 +226,7 @@ pub fn compute_alias_components_recursive( alias_ty: ty::AliasTy, out: &mut SmallVec<[Component; 4]>, ) { - let opt_variances = cx.opt_alias_variances(alias_ty); + let opt_variances = cx.opt_alias_variances(alias_ty.kind); let mut visitor = OutlivesCollector { cx, out, visited: Default::default() }; diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 5ee2b19e49757..0ddbb203652b6 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -220,7 +220,7 @@ impl Relate for ty::AliasTy { ))) } else { let cx = relation.cx(); - let args = if let Some(variances) = cx.opt_alias_variances(a) { + let args = if let Some(variances) = cx.opt_alias_variances(a.kind) { relate_args_with_variances(relation, variances, a.args, b.args)? } else { relate_args_invariantly(relation, a.args, b.args)? From cca7517b918d1dd0605a011a88b9c2884548f3b7 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 13 May 2026 19:24:56 +0800 Subject: [PATCH 10/38] address some reviews --- compiler/rustc_hir_typeck/src/closure.rs | 3 +-- compiler/rustc_lint/src/types/improper_ctypes.rs | 3 +-- compiler/rustc_trait_selection/src/traits/wf.rs | 4 +++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 39b8ef6c1ebe1..1f2026e34436f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -830,8 +830,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BoundRegionConversionTime::FnCall, supplied_sig, |value| { - // FIXME: a proper cause? - let cause = self.misc(DUMMY_SP); + let cause = self.misc(self.tcx.def_span(expr_def_id)); let InferOk { value, obligations } = self.at(&cause, self.param_env).renormalize_ambiguous_aliases(value); all_obligations.extend(obligations); diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 79816ba840a22..7b7b8bec4f43b 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -894,10 +894,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { help: None, }, - ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => todo!(), ty::Param(..) | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. } | ty::Ambiguous, .. }) | ty::Infer(..) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 8ba0fb18d1d36..e3d77b6da262d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -815,7 +815,9 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { return; // Subtree handled by compute_inherent_projection. } - // Generally we skip predicates that contain escaping bound vars. See above. + // Ambiguous aliases only wrap another higher-ranked alias whose + // normalization is currently ambiguous, we will handle that alias + // when recursing into args. ty::Alias(ty::AliasTy { kind: ty::Ambiguous { .. }, .. }) => {} ty::Adt(def, args) => { From 5f0356fd9eaf164d138558bb38e1d8c6e4c12de5 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 13 May 2026 19:34:25 +0800 Subject: [PATCH 11/38] fix rustdoc and clippy --- src/librustdoc/clean/mod.rs | 1 + src/tools/clippy/clippy_lints/src/dereference.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d50e4dd80557a..8f20f2e5234a8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2346,6 +2346,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Placeholder(..) => panic!("Placeholder"), ty::CoroutineWitness(..) => panic!("CoroutineWitness"), ty::Infer(..) => panic!("Infer"), + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. }) => panic!("Ambiguous alias"), ty::Error(_) => FatalError.raise(), } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 7a5150da6593a..07091d34ed310 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -904,7 +904,7 @@ impl TyCoercionStability { | ty::Error(_) | ty::Bound(..) | ty::Alias(ty::AliasTy { - kind: ty::Opaque { .. }, + kind: ty::Opaque { .. } | ty::Ambiguous, .. }) | ty::Placeholder(_) From bda52cf1481345d7d74f55be2229565b83a43c27 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 13 May 2026 20:36:38 +0800 Subject: [PATCH 12/38] create a wrapper for fully normalization after instantiation --- compiler/rustc_hir_typeck/src/callee.rs | 8 ++--- compiler/rustc_hir_typeck/src/method/mod.rs | 23 ++++++------- .../rustc_hir_typeck/src/method/suggest.rs | 21 +++++------- compiler/rustc_infer/src/infer/context.rs | 4 +-- compiler/rustc_infer/src/infer/mod.rs | 32 ++++++++++++------- .../src/solve/eval_ctxt/mod.rs | 7 ++-- .../src/traits/normalize.rs | 4 +-- .../src/relate/solver_relating.rs | 2 +- compiler/rustc_type_ir/src/unnormalized.rs | 16 ++-------- 9 files changed, 56 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 3a589e4a31477..87c88f9510523 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -546,7 +546,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (fn_sig, def_id) = match *callee_ty.kind() { ty::FnDef(def_id, args) => { self.enforce_context_effects(Some(call_expr.hir_id), call_expr.span, def_id, args); - let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args).skip_norm_wip(); + let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args); // Unit testing: function items annotated with // `#[rustc_evaluate_where_clauses]` trigger special output @@ -576,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // FIXME(const_trait_impl): these arms should error because we can't enforce them - ty::FnPtr(sig_tys, hdr) => (sig_tys.with(hdr), None), + ty::FnPtr(sig_tys, hdr) => (ty::Unnormalized::new_wip(sig_tys.with(hdr)), None), _ => unreachable!(), }; @@ -586,12 +586,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // renormalize the associated types at this point, since they // previously appeared within a `Binder<>` and hence would not // have been normalized before. - let fn_sig = self.instantiate_binder_with_fresh_vars( + let fn_sig = self.instantiate_binder_with_fresh_vars_then_fully_normalize( call_expr.span, BoundRegionConversionTime::FnCall, fn_sig, + |sig| self.normalize(call_expr.span, sig), ); - let fn_sig = self.normalize(call_expr.span, fn_sig.into()); self.check_argument_types( call_expr.span, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 361e0d61ddf93..719e20de94947 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -421,17 +421,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // N.B., instantiate late-bound regions before normalizing the // function signature so that normalization does not need to deal // with bound regions. - let fn_sig = tcx.fn_sig(def_id).instantiate(self.tcx, args).map(|sig| { - self.instantiate_binder_with_fresh_vars( - obligation.cause.span, - BoundRegionConversionTime::FnCall, - sig, - ) - .skip_normalization() - }); - let InferOk { value: fn_sig, obligations: o } = - self.at(&obligation.cause, self.param_env).normalize(fn_sig); - obligations.extend(o); + let fn_sig = tcx.fn_sig(def_id).instantiate(self.tcx, args); + let fn_sig = self.instantiate_binder_with_fresh_vars_then_fully_normalize( + obligation.cause.span, + BoundRegionConversionTime::FnCall, + fn_sig, + |sig| { + let InferOk { value: sig, obligations: o } = + self.at(&obligation.cause, self.param_env).normalize(sig); + obligations.extend(o); + sig + }, + ); // Register obligations for the parameters. This will include the // `Self` parameter, which in turn has a bound of the main trait, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8344cc9911b23..d15ee7767e47c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2371,19 +2371,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inherent_method.container_id(self.tcx), adt_args, ); - let fn_sig = self - .tcx - .fn_sig(inherent_method.def_id) - .instantiate(self.tcx, args) - .map(|sig| { - self.instantiate_binder_with_fresh_vars( - item_name.span, - BoundRegionConversionTime::FnCall, - sig, - ) - .skip_normalization() - }); - let fn_sig = self.normalize(item_name.span, fn_sig); + let fn_sig = + self.tcx.fn_sig(inherent_method.def_id).instantiate(self.tcx, args); + let fn_sig = self.instantiate_binder_with_fresh_vars_then_fully_normalize( + item_name.span, + BoundRegionConversionTime::FnCall, + fn_sig, + |sig| self.normalize(item_name.span, sig), + ); 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 0a13969fd8c37..9710b2cb567aa 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -202,11 +202,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { &self, value: ty::Binder<'tcx, T>, ) -> ty::UnnormalizedAmbiguous<'tcx, T> { - self.instantiate_binder_with_fresh_vars( + ty::UnnormalizedAmbiguous::new(self.instantiate_binder_with_fresh_vars( DUMMY_SP, BoundRegionConversionTime::HigherRankedType, value, - ) + )) } fn enter_forall>, U>( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index cd2006d327432..a39eb89f921dc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1391,7 +1391,7 @@ impl<'tcx> InferCtxt<'tcx> { F: FnMut(ty::UnnormalizedAmbiguous<'tcx, T>) -> T, { let instantiated = self.instantiate_binder_with_fresh_vars(span, lbrct, value); - renormalize_ambig(instantiated) + renormalize_ambig(ty::UnnormalizedAmbiguous::new(instantiated)) } pub fn instantiate_binder_with_fresh_vars_no_ambiguous_aliases( @@ -1404,7 +1404,22 @@ impl<'tcx> InferCtxt<'tcx> { T: TypeFoldable> + Copy, { debug_assert!(!value.has_ambiguous_aliases()); - self.instantiate_binder_with_fresh_vars(span, lbrct, value).skip_normalization() + self.instantiate_binder_with_fresh_vars(span, lbrct, value) + } + + pub fn instantiate_binder_with_fresh_vars_then_fully_normalize( + &self, + span: Span, + lbrct: BoundRegionConversionTime, + value: ty::Unnormalized<'tcx, ty::Binder<'tcx, T>>, + mut normalize: F, + ) -> T + where + T: TypeFoldable> + Copy, + F: FnMut(ty::Unnormalized<'tcx, T>) -> T, + { + let instantiated = value.map(|v| self.instantiate_binder_with_fresh_vars(span, lbrct, v)); + normalize(instantiated) } // Instantiates the bound variables in a given binder with fresh inference @@ -1414,22 +1429,17 @@ impl<'tcx> InferCtxt<'tcx> { // 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. - // - // You shouldn't use this method directly. Have a look at its wrappers. - // FIXME: I really want to make this method private. But it's needed for one use case: - // a full normalization after instantiating binder where the value can contain ambiguous - // aliases. Maybe add another wrapper for that use case? - pub fn instantiate_binder_with_fresh_vars( + fn instantiate_binder_with_fresh_vars( &self, span: Span, lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, - ) -> ty::UnnormalizedAmbiguous<'tcx, T> + ) -> T where T: TypeFoldable> + Copy, { if let Some(inner) = value.no_bound_vars() { - return ty::UnnormalizedAmbiguous::new(inner); + return inner; } let bound_vars = value.bound_vars(); @@ -1462,7 +1472,7 @@ impl<'tcx> InferCtxt<'tcx> { } } let delegate = ToFreshVars { args }; - ty::UnnormalizedAmbiguous::new(self.tcx.replace_bound_vars_uncached(value, delegate)) + self.tcx.replace_bound_vars_uncached(value, delegate) } /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. 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 bf3394aa8cae1..33651635d9940 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 @@ -1745,7 +1745,7 @@ where param_env: I::ParamEnv, value: ty::Unnormalized, ) -> Result { - self.normalize_inner(param_env, value, NormalizationScope::All) + self.normalize_inner(param_env, value.skip_normalization(), NormalizationScope::All) } /// Only normalizes aliases of `AmbiguousTy` kind. @@ -1759,16 +1759,15 @@ where param_env: I::ParamEnv, value: ty::UnnormalizedAmbiguous, ) -> Result { - self.normalize_inner(param_env, value.into(), NormalizationScope::AmbiguousAlias) + self.normalize_inner(param_env, value.do_normalize(), NormalizationScope::AmbiguousAlias) } fn normalize_inner>( &mut self, param_env: I::ParamEnv, - value: ty::Unnormalized, + value: T, scope: NormalizationScope, ) -> Result { - let value = value.skip_normalization(); let value = self.delegate.resolve_vars_if_possible(value); // To drop the mutable borrow of self early. let (normalized, stalled_goals) = { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index f54814255b364..6037043349bea 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -56,13 +56,13 @@ impl<'tcx> At<'_, 'tcx> { if self.infcx.next_trait_solver() { let Normalized { value, obligations } = crate::solve::normalize( *self, - Unnormalized::new(value.skip_normalization()), + Unnormalized::new(value.do_normalize()), NormalizationScope::AmbiguousAlias, ); InferOk { value, obligations } } else { // We won't have ambiguous aliases in old solver so no-op. - InferOk { value: value.skip_normalization(), obligations: Default::default() } + InferOk { value: value.do_normalize(), obligations: Default::default() } } } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index ddcdadc4b742c..3f30f2e8c4637 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -134,7 +134,7 @@ where &mut self, value: ty::UnnormalizedAmbiguous, ) -> T { - let value = value.skip_normalization(); + let value = value.do_normalize(); let mut replacer = ReplaceAmbiguousAliasWithInfer::new(self.infcx, self.param_env); let value = value.fold_with(&mut replacer); self.register_goals(replacer.goals()); diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index 62e11bd1c9bab..89ca4f2592cc6 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -162,23 +162,13 @@ impl UnnormalizedAmbiguous { Self { value, _tcx: PhantomData } } - /// FIXME: This is going to be eventually removed. - /// If you meet this in codebase, try using one of the ambiguous renormalization - /// routines to consume the wrapper. Or use `skip_normalization` when normalization - /// is really unnecessary. + /// FIXME: This is going to be removed in this PR. pub fn skip_norm_wip(self) -> T { self.value } - /// Intentionally skip normalization. - /// You probably should perform normalization in most cases. - pub fn skip_normalization(self) -> T { + /// Only use this if it will then normalize away all ambiguous aliases. + pub fn do_normalize(self) -> T { self.value } } - -impl From> for Unnormalized { - fn from(value: UnnormalizedAmbiguous) -> Unnormalized { - Unnormalized::new(value.skip_normalization()) - } -} From a99a408b859c1b28479a3832d58ded0033209132 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 13 May 2026 15:13:11 +0200 Subject: [PATCH 13/38] review --- compiler/rustc_const_eval/src/util/type_name.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index f8b32cc5464d4..e215c49b6fffc 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -63,14 +63,12 @@ impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> { | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), - ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => { - bug!("type_name: unexpected free alias") - } - ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { - bug!("type_name: unexpected inherent projection") - } - ty::Infer(_) | ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. }) => unreachable!(), - ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"), + ty::Infer(_) + | ty::Alias(ty::AliasTy { + kind: ty::Free { .. } | ty::Inherent { .. } | ty::Ambiguous, + .. + }) + | ty::CoroutineWitness(..) => bug!("type_name: unexpected type: {ty:?}"), } } From 8c8b1314bd9c1716a330ad163b829cdb60f8e4cd Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 00:16:43 +0200 Subject: [PATCH 14/38] update --- compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/method/mod.rs | 11 ++-- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 4 +- compiler/rustc_infer/src/infer/context.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 17 +++--- .../src/infer/relate/higher_ranked.rs | 17 +----- compiler/rustc_middle/src/ty/context.rs | 58 +++++++++++++++++++ .../src/ty/context/impl_interner.rs | 16 +++++ compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_middle/src/ty/sty.rs | 19 +++--- .../rustc_next_trait_solver/src/coherence.rs | 7 ++- .../rustc_next_trait_solver/src/normalize.rs | 43 +++++++++----- .../traits/fulfillment_errors.rs | 6 +- .../src/solve/fulfill/derive_errors.rs | 19 +++--- .../src/solve/normalize.rs | 8 +++ compiler/rustc_type_ir/src/interner.rs | 12 ++++ compiler/rustc_type_ir/src/predicate.rs | 40 ++++--------- .../rustc_type_ir/src/region_constraint.rs | 12 ++-- compiler/rustc_type_ir/src/relate.rs | 11 ++-- compiler/rustc_type_ir/src/relate/combine.rs | 4 ++ compiler/rustc_type_ir/src/ty_kind.rs | 15 +---- compiler/rustc_type_ir/src/unnormalized.rs | 15 +++-- 23 files changed, 207 insertions(+), 139 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 87c88f9510523..6416bdabff81f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -586,12 +586,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // renormalize the associated types at this point, since they // previously appeared within a `Binder<>` and hence would not // have been normalized before. - let fn_sig = self.instantiate_binder_with_fresh_vars_then_fully_normalize( + let fn_sig = self.instantiate_unnormalized_binder_with_fresh_vars( call_expr.span, BoundRegionConversionTime::FnCall, fn_sig, - |sig| self.normalize(call_expr.span, 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/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 719e20de94947..1b25e3c3600a0 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -422,17 +422,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // function signature so that normalization does not need to deal // with bound regions. let fn_sig = tcx.fn_sig(def_id).instantiate(self.tcx, args); - let fn_sig = self.instantiate_binder_with_fresh_vars_then_fully_normalize( + let fn_sig = self.instantiate_unnormalized_binder_with_fresh_vars( obligation.cause.span, BoundRegionConversionTime::FnCall, fn_sig, - |sig| { - let InferOk { value: sig, obligations: o } = - self.at(&obligation.cause, self.param_env).normalize(sig); - obligations.extend(o); - sig - }, ); + let InferOk { value: fn_sig, obligations: o } = + self.at(&obligation.cause, self.param_env).normalize(fn_sig); + obligations.extend(o); // Register obligations for the parameters. This will include the // `Self` parameter, which in turn has a bound of the main trait, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ad9b727f72145..9defb8fc1e92b 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2110,7 +2110,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.span, BoundRegionConversionTime::FnCall, poly_trait_ref, - |value| value.skip_norm_wip(), + |value| value.no_ambiguous_aliases(), ); (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 d15ee7767e47c..c70b7cb820f26 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2373,12 +2373,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let fn_sig = self.tcx.fn_sig(inherent_method.def_id).instantiate(self.tcx, args); - let fn_sig = self.instantiate_binder_with_fresh_vars_then_fully_normalize( + let fn_sig = self.instantiate_unnormalized_binder_with_fresh_vars( item_name.span, BoundRegionConversionTime::FnCall, fn_sig, - |sig| self.normalize(item_name.span, sig), ); + let fn_sig = self.normalize(item_name.span, fn_sig); 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 9710b2cb567aa..1b79d31a95e97 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -202,7 +202,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { &self, value: ty::Binder<'tcx, T>, ) -> ty::UnnormalizedAmbiguous<'tcx, T> { - ty::UnnormalizedAmbiguous::new(self.instantiate_binder_with_fresh_vars( + ty::UnnormalizedAmbiguous::new(self.instantiate_binder_with_fresh_vars_raw( DUMMY_SP, BoundRegionConversionTime::HigherRankedType, value, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a39eb89f921dc..5a0ca1232fe6f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1390,7 +1390,7 @@ impl<'tcx> InferCtxt<'tcx> { T: TypeFoldable> + Copy, F: FnMut(ty::UnnormalizedAmbiguous<'tcx, T>) -> T, { - let instantiated = self.instantiate_binder_with_fresh_vars(span, lbrct, value); + let instantiated = self.instantiate_binder_with_fresh_vars_raw(span, lbrct, value); renormalize_ambig(ty::UnnormalizedAmbiguous::new(instantiated)) } @@ -1403,23 +1403,20 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable> + Copy, { - debug_assert!(!value.has_ambiguous_aliases()); - self.instantiate_binder_with_fresh_vars(span, lbrct, value) + assert!(!value.has_ambiguous_aliases()); + self.instantiate_binder_with_fresh_vars_raw(span, lbrct, value) } - pub fn instantiate_binder_with_fresh_vars_then_fully_normalize( + pub fn instantiate_unnormalized_binder_with_fresh_vars( &self, span: Span, lbrct: BoundRegionConversionTime, value: ty::Unnormalized<'tcx, ty::Binder<'tcx, T>>, - mut normalize: F, - ) -> T + ) -> ty::Unnormalized<'tcx, T> where T: TypeFoldable> + Copy, - F: FnMut(ty::Unnormalized<'tcx, T>) -> T, { - let instantiated = value.map(|v| self.instantiate_binder_with_fresh_vars(span, lbrct, v)); - normalize(instantiated) + value.map(|v| self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases(span, lbrct, v)) } // Instantiates the bound variables in a given binder with fresh inference @@ -1429,7 +1426,7 @@ impl<'tcx> InferCtxt<'tcx> { // 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. - fn instantiate_binder_with_fresh_vars( + fn instantiate_binder_with_fresh_vars_raw( &self, span: Span, lbrct: BoundRegionConversionTime, diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index e92479a76d4c9..95cba34aa5654 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -27,22 +27,11 @@ impl<'tcx> InferCtxt<'tcx> { T: TypeFoldable>, { debug_assert!(!binder.has_ambiguous_aliases()); - self.enter_forall_and_leak_universe_inner(binder) - } - - /// Same as `enter_forall_and_leak_universe`, but we allow ambiguous aliases here. - pub fn enter_forall_and_leak_universe_for_diagnostics( - &self, - binder: ty::Binder<'tcx, T>, - ) -> T - where - T: TypeFoldable>, - { - self.enter_forall_and_leak_universe_inner(binder) + self.enter_forall_and_leak_universe_raw(binder) } #[instrument(level = "debug", skip(self), ret)] - fn enter_forall_and_leak_universe_inner(&self, binder: ty::Binder<'tcx, T>) -> T + fn enter_forall_and_leak_universe_raw(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable>, { @@ -96,7 +85,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_inner(forall); + let value = self.enter_forall_and_leak_universe_raw(forall); debug!(?value); f(ty::UnnormalizedAmbiguous::new(value)) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e756277b92d76..1ff24bfb1fe0c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2134,6 +2134,64 @@ impl<'tcx> TyCtxt<'tcx> { true } + pub fn debug_assert_alias_ty_args_compatible( + self, + alias_ty: ty::AliasTyKind<'tcx>, + args: &'tcx [ty::GenericArg<'tcx>], + ) { + if cfg!(debug_assertions) { + match alias_ty { + ty::AliasTyKind::Projection { def_id } + | ty::AliasTyKind::Inherent { def_id } + | ty::AliasTyKind::Opaque { def_id } + | ty::AliasTyKind::Free { def_id } => { + self.debug_assert_args_compatible(def_id, args) + } + ty::AliasTyKind::Ambiguous => { + assert_eq!(args.len(), 1); + match args[0].expect_ty().kind() { + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args: _, .. }) => { + unreachable!() + } + ty::Alias(_) => {} + _ => unreachable!(), + } + } + } + } + } + + pub fn debug_assert_alias_term_args_compatible( + self, + alias_term: ty::AliasTermKind<'tcx>, + args: &'tcx [ty::GenericArg<'tcx>], + ) { + if cfg!(debug_assertions) { + match alias_term { + rustc_type_ir::AliasTermKind::ProjectionTy { def_id } + | rustc_type_ir::AliasTermKind::InherentTy { def_id } + | rustc_type_ir::AliasTermKind::OpaqueTy { def_id } + | rustc_type_ir::AliasTermKind::FreeTy { def_id } + | rustc_type_ir::AliasTermKind::UnevaluatedConst { def_id } + | rustc_type_ir::AliasTermKind::ProjectionConst { def_id } + | rustc_type_ir::AliasTermKind::FreeConst { def_id } + | rustc_type_ir::AliasTermKind::InherentConst { def_id } => { + self.debug_assert_args_compatible(def_id, args) + } + ty::AliasTermKind::AmbiguousTy => { + assert_eq!(args.len(), 1); + match args[0].expect_ty().kind() { + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args: _, .. }) => { + unreachable!() + } + ty::Alias(_) => {} + _ => unreachable!(), + } + } + } + } + } + /// With `cfg(debug_assertions)`, assert that args are compatible with their generics, /// and print out the args if not. pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) { diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 7f1eeda4ad1d6..b41cc716ef866 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -277,6 +277,22 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.debug_assert_args_compatible(def_id, args); } + fn debug_assert_alias_ty_args_compatible( + self, + alias_ty: ty::AliasTyKind<'tcx>, + args: ty::GenericArgsRef<'tcx>, + ) { + self.debug_assert_alias_ty_args_compatible(alias_ty, args); + } + + fn debug_assert_alias_term_args_compatible( + self, + alias_ty: ty::AliasTermKind<'tcx>, + args: ty::GenericArgsRef<'tcx>, + ) { + self.debug_assert_alias_term_args_compatible(alias_ty, args); + } + /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` /// are compatible with the `DefId`. Since we're missing a `Self` type, stick on /// a dummy self type and forward to `debug_assert_args_compatible`. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ac9e50d57d08e..89a9979f02b1c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3158,7 +3158,7 @@ define_print! { } ty::AliasTerm<'tcx> { - match self.kind(p.tcx()).reveal_ambiguous(self.args) { + match self.kind(p.tcx()) { ty::AliasTermKind::InherentTy {..} | ty::AliasTermKind::InherentConst {..} => p.pretty_print_inherent_projection(*self)?, ty::AliasTermKind::ProjectionTy { def_id } => { if !(p.should_print_verbose() || with_reduced_queries()) @@ -3176,7 +3176,7 @@ define_print! { | ty::AliasTermKind::ProjectionConst { def_id } => { p.print_def_path(def_id, self.args)?; } - ty::AliasTermKind::AmbiguousTy { .. } => unreachable!() + ty::AliasTermKind::AmbiguousTy { .. } => self.args.type_at(0).print(p)?, } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 6f97e64b13b71..eef3034072be8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -3,8 +3,8 @@ #![allow(rustc::usage_of_ty_tykind)] use std::borrow::Cow; -use std::debug_assert_matches; use std::ops::{ControlFlow, Range}; +use std::{assert_matches, debug_assert_matches}; use hir::def::{CtorKind, DefKind}; use rustc_abi::{FIRST_VARIANT, FieldIdx, NumScalableVectors, ScalableElt, VariantIdx}; @@ -478,13 +478,16 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_alias(tcx: TyCtxt<'tcx>, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> { - debug_assert_matches!( - (alias_ty.kind, tcx.def_kind(alias_ty.kind.def_id())), - (ty::Opaque { .. }, DefKind::OpaqueTy) - | (ty::Projection { .. } | ty::Inherent { .. }, DefKind::AssocTy) - | (ty::Free { .. }, DefKind::TyAlias) - | (ty::Ambiguous { .. }, DefKind::OpaqueTy | DefKind::AssocTy | DefKind::TyAlias) - ); + if cfg!(debug_assertions) { + match alias_ty.kind { + ty::Opaque { def_id } => assert_matches!(tcx.def_kind(def_id), DefKind::OpaqueTy), + ty::Projection { def_id } | ty::Inherent { def_id } => { + assert_matches!(tcx.def_kind(def_id), DefKind::AssocTy) + } + ty::Free { def_id } => assert_matches!(tcx.def_kind(def_id), DefKind::TyAlias), + ty::Ambiguous => {} + } + } Ty::new(tcx, Alias(alias_ty)) } diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index b42f3925a8992..ec1066623ff77 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -362,14 +362,14 @@ where // normalize to that, so we have to treat it as an uncovered ty param. // * Otherwise it may normalize to any non-type-generic type // be it local or non-local. - ty::Alias(ty::AliasTy { kind, args, .. }) => { + ty::Alias(ty::AliasTy { kind, .. }) => { if ty.has_type_flags( ty::TypeFlags::HAS_TY_PLACEHOLDER | ty::TypeFlags::HAS_TY_BOUND | ty::TypeFlags::HAS_TY_INFER, ) { match self.in_crate { - InCrate::Local { mode } => match kind.reveal_ambiguous(args) { + InCrate::Local { mode } => match kind { ty::Projection { .. } => { if let OrphanCheckMode::Compat = mode { ControlFlow::Continue(()) @@ -377,7 +377,8 @@ where self.found_uncovered_ty_param(ty) } } - _ => self.found_uncovered_ty_param(ty), + ty::Inherent { .. } | ty::Opaque { .. } | ty::Free { .. } => self.found_uncovered_ty_param(ty), + ty::AliasTyKind::Ambiguous => unreachable!(), }, InCrate::Remote => { // The inference variable might be unified with a local diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index b6d63c3086227..1e2b2d771b8a3 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -195,10 +195,15 @@ where return Ok(ty); } - // With eager normalization, we should normalize the args of alias before - // normalizing the alias itself. - let ty = ty.try_super_fold_with(self)?; - let ty::Alias(alias_ty) = ty.kind() else { return Ok(ty) }; + let ty = match ty.kind() { + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args, .. }) => { + // FIXME: long term we shouldn't ever normalize types containing ambiguous aliases, + // but for now we just try to renormalize the contained alias. + return Ok(args.type_at(0).try_fold_with(self)?); + } + ty::Alias(..) => ty.try_super_fold_with(self)?, + _ => return Ok(ty.try_super_fold_with(self)?), + }; if ty.has_escaping_bound_vars() { let (ty, mapped_regions, mapped_types, mapped_consts) = @@ -227,10 +232,8 @@ where Ok(normalized_ty) } } else { - let alias = - if let ty::Ambiguous = alias_ty.kind { alias_ty.args.type_at(0) } else { ty }; Ok(ensure_sufficient_stack(|| { - self.normalize_alias_term(alias.into(), HasEscapingBoundVars::No) + self.normalize_alias_term(ty.into(), HasEscapingBoundVars::No) })? .0 .expect_ty()) @@ -273,6 +276,10 @@ where .expect_const()) } } + + fn try_fold_predicate(&mut self, p: I::Predicate) -> Result { + if p.allow_normalization() { p.try_super_fold_with(self) } else { Ok(p) } + } } // Only handle ambiguous alias in the outmost instantiated binder. @@ -327,14 +334,11 @@ where &mut self, t: Binder, ) -> Result, Self::Error> { - // We don't look into nested binders since they're not instantiated. - // Thus we assume we won't meet escaping bound vars as well. - Ok(t) + if t.has_ambiguous_aliases() { t.try_super_fold_with(self) } else { Ok(t) } } #[instrument(level = "trace", skip(self), ret)] fn try_fold_ty(&mut self, ty: I::Ty) -> Result { - debug_assert!(!ty.has_escaping_bound_vars()); if !ty.has_ambiguous_aliases() { return Ok(ty); } @@ -348,8 +352,12 @@ where }; let original_alias = args.type_at(0); - Ok(ensure_sufficient_stack(|| self.normalize_alias_term(original_alias.into()))? - .expect_ty()) + if original_alias.has_escaping_bound_vars() { + Ok(original_alias) + } else { + Ok(ensure_sufficient_stack(|| self.normalize_alias_term(original_alias.into()))? + .expect_ty()) + } } #[instrument(level = "trace", skip(self), ret)] @@ -367,4 +375,13 @@ where // As a field or a new kind on `ConstKind`? Ok(ct) } + + fn try_fold_predicate(&mut self, p: I::Predicate) -> Result { + if p.allow_normalization() { + p.try_super_fold_with(self) + } else { + assert!(!p.has_ambiguous_aliases()); + Ok(p) + } + } } 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 457ad0c28c05e..998e2c93fe7b4 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 @@ -1606,8 +1606,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(lhs) = lhs.to_alias_term(self.tcx) && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = - lhs.kind.reveal_ambiguous(lhs.args) + | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind && let Some((better_type_err, expected_term)) = derive_better_type_error(lhs, rhs) { @@ -1617,8 +1616,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } else if let Some(rhs) = rhs.to_alias_term(self.tcx) && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = - rhs.kind.reveal_ambiguous(rhs.args) + | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind && let Some((better_type_err, expected_term)) = derive_better_type_error(rhs, lhs) { 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 9cc30730e0997..139562ccd79c1 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -9,7 +9,7 @@ use rustc_infer::traits::{ }; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_next_trait_solver::solve::{GoalEvaluation, MaybeInfo, SolverDelegateEvalExt as _}; use tracing::{instrument, trace}; @@ -58,17 +58,13 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( ty::PredicateKind::AliasRelate(_, _, _) => { FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) } - ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.enter_forall_and_leak_universe_for_diagnostics( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); + ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => { + assert!(!(a, b).has_escaping_bound_vars()); 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_for_diagnostics( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); + ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => { + assert!(!(a, b).has_escaping_bound_vars()); let expected_found = ExpectedFound::new(b, a); FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) } @@ -401,8 +397,7 @@ impl<'tcx> BestObligation<'tcx> { } Some(ty::PredicateKind::NormalizesTo(pred)) if let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = - pred.alias.kind.reveal_ambiguous(pred.alias.args) => + | ty::AliasTermKind::ProjectionConst { .. } = pred.alias.kind => { self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?; self.detect_non_well_formed_assoc_item(goal, pred.alias)?; @@ -469,7 +464,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } ty::PredicateKind::NormalizesTo(normalizes_to) if matches!( - normalizes_to.alias.kind.reveal_ambiguous(normalizes_to.alias.args), + normalizes_to.alias.kind, ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } ) => diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 5c3f32eb34d78..776648d2eaff4 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -174,6 +174,10 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { self.term_to_infer(ct.into()).expect_const() } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.allow_normalization() { p.super_fold_with(self) } else { p } + } } /// Deeply normalize all aliases in `value`. This does not handle inference and expects @@ -308,4 +312,8 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, Err(_) => ct.super_fold_with(self), } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.allow_normalization() { p.super_fold_with(self) } else { p } + } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 09def0212a153..50294abf8f4f7 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -264,6 +264,18 @@ pub trait Interner: fn debug_assert_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs); + fn debug_assert_alias_ty_args_compatible( + self, + alias_ty: ty::AliasTyKind, + args: Self::GenericArgs, + ); + + fn debug_assert_alias_term_args_compatible( + self, + alias_ty: ty::AliasTermKind, + args: Self::GenericArgs, + ); + /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` /// are compatible with the `DefId`. fn debug_assert_existential_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs); diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index adf93c24158e3..2added8a8b98e 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -656,18 +656,6 @@ impl AliasTermKind { AliasTermKind::InherentConst { def_id } => def_id.into(), } } - - // Convert `AmbiguousTy` into its original kind. - pub fn reveal_ambiguous(self, args: I::GenericArgs) -> Self { - if let AliasTermKind::AmbiguousTy = self { - let ty::Alias(ty::AliasTy { kind, .. }) = args.type_at(0).kind() else { - unreachable!() - }; - kind.into() - } else { - self - } - } } impl From> for AliasTermKind { @@ -723,11 +711,7 @@ impl AliasTerm { kind: AliasTermKind, args: I::GenericArgs, ) -> AliasTerm { - // FIXME: skipping args compatibility check for `Ambiguous`. - // Should be fixed with the removal the `def_id` method . - if !matches!(kind, AliasTermKind::AmbiguousTy) { - interner.debug_assert_args_compatible(kind.def_id(), args); - } + interner.debug_assert_alias_term_args_compatible(kind, args); AliasTerm { kind, args, _use_alias_term_new_instead: () } } @@ -834,26 +818,22 @@ impl AliasTerm { ) } - fn projection_def_id(self) -> Option { - match self.kind.reveal_ambiguous(self.args) { - AliasTermKind::ProjectionTy { def_id } => Some(def_id.into()), - AliasTermKind::ProjectionConst { def_id } => Some(def_id.into()), + fn projection_def_id(self) -> I::TraitAssocTermId { + match self.kind { + AliasTermKind::ProjectionTy { def_id } => def_id.into(), + AliasTermKind::ProjectionConst { def_id } => def_id.into(), AliasTermKind::InherentTy { .. } | AliasTermKind::OpaqueTy { .. } | AliasTermKind::FreeTy { .. } | AliasTermKind::UnevaluatedConst { .. } | AliasTermKind::FreeConst { .. } - | AliasTermKind::InherentConst { .. } => None, - AliasTermKind::AmbiguousTy => unreachable!(), + | AliasTermKind::InherentConst { .. } + | AliasTermKind::AmbiguousTy => unreachable!(), } } - fn expect_projection_def_id(self) -> I::TraitAssocTermId { - self.projection_def_id().expect("expected a projection") - } - pub fn trait_def_id(self, interner: I) -> I::TraitId { - interner.projection_parent(self.expect_projection_def_id()) + interner.projection_parent(self.projection_def_id()) } /// Extracts the underlying trait reference and own args from this projection. @@ -861,7 +841,7 @@ impl AliasTerm { /// then this function would return a `T: StreamingIterator` trait reference and /// `['a]` as the own args. pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef, I::GenericArgsSlice) { - interner.trait_ref_and_own_args_for_alias(self.expect_projection_def_id(), self.args) + interner.trait_ref_and_own_args_for_alias(self.projection_def_id(), self.args) } /// Extracts the underlying trait reference from this projection. @@ -960,7 +940,7 @@ impl ProjectionPredicate { } pub fn def_id(self) -> I::TraitAssocTermId { - self.projection_term.expect_projection_def_id() + self.projection_term.projection_def_id() } } diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index d784dbd767599..ea08067ef66aa 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -1097,13 +1097,13 @@ fn alias_outlives_candidates_from_assumptions // FIXME(-Zassumptions-on-binders): Handle the assumptions on this binder infcx.enter_forall(bound_outlives, |bound_outlives| { - let (alias, r) = bound_outlives.skip_norm_wip(); + let (alias, r) = bound_outlives.no_ambiguous_aliases(); let u = infcx.universe(); infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); for bound_type_outlives in assumptions.type_outlives.iter() { let OutlivesPredicate(alias2, r2) = - infcx.instantiate_binder_with_infer(*bound_type_outlives).skip_norm_wip(); + infcx.instantiate_binder_with_infer(*bound_type_outlives).no_ambiguous_aliases(); let mut relation = HigherRankedAliasMatcher { infcx, @@ -1188,18 +1188,18 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> TypeRelation T: Relate, { self.infcx.enter_forall(a, |a| { - let a = a.skip_norm_wip(); + let a = a.no_ambiguous_aliases(); let u = self.infcx.universe(); self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); - let b = self.infcx.instantiate_binder_with_infer(b).skip_norm_wip(); + let b = self.infcx.instantiate_binder_with_infer(b).no_ambiguous_aliases(); self.relate(a, b) })?; self.infcx.enter_forall(b, |b| { - let b = b.skip_norm_wip(); + let b = b.no_ambiguous_aliases(); let u = self.infcx.universe(); self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); - let a = self.infcx.instantiate_binder_with_infer(a).skip_norm_wip(); + let a = self.infcx.instantiate_binder_with_infer(a).no_ambiguous_aliases(); self.relate(a, b) })?; diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 0ddbb203652b6..d85594eda3e85 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -213,7 +213,7 @@ impl Relate for ty::AliasTy { a: ty::AliasTy, b: ty::AliasTy, ) -> RelateResult> { - if a.kind.def_id() != b.kind.def_id() { + if a.kind != b.kind { Err(TypeError::ProjectionMismatched(ExpectedFound::new( a.kind.def_id(), b.kind.def_id(), @@ -236,10 +236,10 @@ impl Relate for ty::AliasTerm { a: ty::AliasTerm, b: ty::AliasTerm, ) -> RelateResult> { - if a.def_id() != b.def_id() { + if a.kind != b.kind { Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.def_id(), b.def_id()))) } else { - let args = match a.kind(relation.cx()).reveal_ambiguous(a.args) { + let args = match a.kind(relation.cx()) { ty::AliasTermKind::OpaqueTy { .. } => relate_args_with_variances( relation, relation.cx().variances_of(a.def_id()), @@ -255,7 +255,10 @@ impl Relate for ty::AliasTerm { | ty::AliasTermKind::ProjectionConst { .. } => { relate_args_invariantly(relation, a.args, b.args)? } - ty::AliasTermKind::AmbiguousTy { .. } => unreachable!(), + ty::AliasTermKind::AmbiguousTy { .. } => { + let nested = relation.tys(a.args.type_at(0), b.args.type_at(0))?; + relation.cx().mk_args(&[nested.into()]) + } }; Ok(a.with_args(relation.cx(), args)) } diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 77dfed9c3313a..b9d33433c5ed7 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -115,6 +115,10 @@ where panic!("We do not expect to encounter `Fresh` variables in the new solver") } + (ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. }), _) + | (_, ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. })) => { + unreachable!("ambiguous alias in combine: {a:?} {b:?}") + } (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => { match relation.structurally_relate_aliases() { StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 0cb003d5188e0..28b2a934d7dec 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -94,22 +94,9 @@ impl AliasTyKind { AliasTyKind::Inherent { def_id } => def_id.into(), AliasTyKind::Opaque { def_id } => def_id.into(), AliasTyKind::Free { def_id } => def_id.into(), - // FIXME: in the meantime, We can `reveal_ambiguous` and call this method? AliasTyKind::Ambiguous => todo!("this method is expected to be removed"), } } - - // Convert `Ambiguous` into its original kind. - pub fn reveal_ambiguous(self, args: I::GenericArgs) -> Self { - if let AliasTyKind::Ambiguous = self { - let ty::Alias(ty::AliasTy { kind, .. }) = args.type_at(0).kind() else { - unreachable!() - }; - kind - } else { - self - } - } } /// Defines the kinds of types used by the type system. @@ -492,7 +479,7 @@ impl Eq for AliasTy {} impl AliasTy { pub fn new_from_args(interner: I, kind: AliasTyKind, args: I::GenericArgs) -> AliasTy { - interner.debug_assert_args_compatible(kind.def_id(), args); + interner.debug_assert_alias_ty_args_compatible(kind, args); AliasTy { kind, args, _use_alias_ty_new_instead: () } } diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index 89ca4f2592cc6..e219fe2566e98 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -7,7 +7,7 @@ use crate::inherent::*; use crate::upcast::Upcast; use crate::{ Binder, BoundConstness, ClauseKind, HostEffectPredicate, Interner, PredicatePolarity, - TraitPredicate, TraitRef, + TraitPredicate, TraitRef, TypeVisitable, TypeVisitableExt, }; /// A wrapper for values that need normalization. @@ -148,7 +148,8 @@ impl Unnormalized>> { } } -/// Like `Unnormalized`, but for value that contains unnormalized `Ambiguous` alias. +/// Like `Unnormalized`, but for otherwise normalized values that contain +/// unnormalized `Ambiguous` aliases. #[derive_where(Clone, Copy, PartialOrd, PartialEq, Debug; T)] pub struct UnnormalizedAmbiguous { value: T, @@ -162,13 +163,15 @@ impl UnnormalizedAmbiguous { Self { value, _tcx: PhantomData } } - /// FIXME: This is going to be removed in this PR. - pub fn skip_norm_wip(self) -> T { + /// Only use this if it will then normalize away all ambiguous aliases. + pub fn do_normalize(self) -> T { self.value } +} - /// Only use this if it will then normalize away all ambiguous aliases. - pub fn do_normalize(self) -> T { +impl> UnnormalizedAmbiguous { + pub fn no_ambiguous_aliases(self) -> T { + assert!(!self.value.has_ambiguous_aliases()); self.value } } From 6efa24737db639669278e9fa48c36bb58cccb6b2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 00:22:16 +0200 Subject: [PATCH 15/38] rarw --- compiler/rustc_infer/src/infer/relate/higher_ranked.rs | 10 ++++++++++ compiler/rustc_trait_selection/src/traits/coherence.rs | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 95cba34aa5654..48fe2403495a3 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -30,6 +30,16 @@ impl<'tcx> InferCtxt<'tcx> { self.enter_forall_and_leak_universe_raw(binder) } + pub fn enter_forall_with_ambiguous_aliases_and_leak_universe( + &self, + binder: ty::Binder<'tcx, T>, + ) -> ty::UnnormalizedAmbiguous<'tcx, T> + where + T: TypeFoldable>, + { + ty::UnnormalizedAmbiguous::new(self.enter_forall_and_leak_universe_raw(binder)) + } + #[instrument(level = "debug", skip(self), ret)] fn enter_forall_and_leak_universe_raw(&self, binder: ty::Binder<'tcx, T>) -> T where diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 49cc2833cd978..adee0cfe24888 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_with_ambiguous_aliases_and_leak_universe(predicate.kind()); + // TODO: should have some "replace ambiguous aliases with infer" thingy on the infcx let trait_ref = match predicate_kind { ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref, ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) From 13d454453abcffef791aa3787da575d3ac86b7cd Mon Sep 17 00:00:00 2001 From: Adwin White Date: Thu, 14 May 2026 14:50:14 +0800 Subject: [PATCH 16/38] normalize some ambiguous aliases to infer --- compiler/rustc_hir_typeck/src/method/probe.rs | 9 ++++++++- compiler/rustc_trait_selection/src/traits/coherence.rs | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 9defb8fc1e92b..e0992e2edea55 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1080,7 +1080,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { sig, ) }); - let fty = self.normalize(self.span, fty); + // We shouldn't register predicates to fcx in `probe()` as they're not rollbacked. + // Although it probably doesn't matter much for diagnostics. + let ocx = ObligationCtxt::new(&self.infcx); + let fty = ocx.normalize(&ObligationCause::dummy(), self.param_env, fty); + if !ocx.try_evaluate_obligations().is_empty() { + return false; + } + self.can_eq(self.param_env, fty.output(), expected) }), _ => false, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index adee0cfe24888..5be402c6da33e 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -748,8 +748,11 @@ 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_with_ambiguous_aliases_and_leak_universe(predicate.kind()); - // TODO: should have some "replace ambiguous aliases with infer" thingy on the infcx + let predicate_kind = + goal.infcx().enter_forall_with_ambiguous_aliases_and_leak_universe(predicate.kind()); + let ocx = ObligationCtxt::new(infcx); + let predicate_kind = + ocx.renormalize_ambiguous_aliases(&ObligationCause::dummy(), param_env, predicate_kind); let trait_ref = match predicate_kind { ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref, ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) From e68a8291c3803cbbbd0ace35c08004f748971258 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 00:22:19 +0200 Subject: [PATCH 17/38] bless tests --- ...ence-overlap-unnormalizable-projection-1.stderr | 2 +- .../occurs-check/associated-type.next.stderr | 4 ++-- .../occurs-check/associated-type.old.stderr | 4 ++-- ...guous-on-failed-eval-with-vars-fail.next.stderr | 9 ++++++--- .../structually-relate-aliases.stderr | 2 +- tests/ui/traits/next-solver/async.fail.stderr | 4 ++-- tests/ui/traits/next-solver/async.rs | 2 +- .../lazy-nested-obligations-2.next.stderr | 14 ++++++++++---- tests/ui/traits/next-solver/more-object-bound.rs | 2 +- .../ui/traits/next-solver/more-object-bound.stderr | 12 ++++++++++-- 10 files changed, 36 insertions(+), 19 deletions(-) diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr index c92854b92f9d3..22673cef64079 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr @@ -12,7 +12,7 @@ LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box< as WithAssoc<'a>>::Assoc>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 38fb75483f3b3..ef5a090de4891 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,5 +1,5 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [Alias(AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: Projection { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. })], kind: AmbiguousTy, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [Alias(AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: Projection { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. })], kind: AmbiguousTy, .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 1dac3ecea2687..4e4ec2e9b17e1 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,5 +1,5 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [Alias(AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: Projection { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. })], kind: AmbiguousTy, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [Alias(AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: Projection { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. })], kind: AmbiguousTy, .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index f609dcab752af..e14b7a110e436 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -14,7 +14,7 @@ help: consider giving this pattern a type, where the value of const parameter `N LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = free(); | +++++++++++++ -error[E0271]: type mismatch resolving `10 == 2` +error[E0271]: type mismatch resolving `FREE::<10> == 2` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:35:45 | LL | let (mut arr, mut arr_with_weird_len) = free(); @@ -36,11 +36,14 @@ help: consider giving this pattern a type, where the value of const parameter `N LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = proj(); | +++++++++++++ -error[E0271]: type mismatch resolving `10 == 2` +error[E0271]: type mismatch resolving `::PROJ::<10> == 2` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:52:45 | LL | let (mut arr, mut arr_with_weird_len) = proj(); - | ^^^^^^ types differ + | ^^^^^^ expected `2`, found `10` + | + = note: expected constant `2` + found constant `10` error: aborting due to 4 previous errors diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 4649aac47cdbf..ec00873299f6e 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,4 +1,4 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a))], kind: ProjectionTy { def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [Alias(AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a))], kind: Projection { def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }, .. })], kind: AmbiguousTy, .. } error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied --> $DIR/structually-relate-aliases.rs:13:36 | diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr index a76a10d20ee8b..bc89842d16a14 100644 --- a/tests/ui/traits/next-solver/async.fail.stderr +++ b/tests/ui/traits/next-solver/async.fail.stderr @@ -1,8 +1,8 @@ -error[E0271]: type mismatch resolving `() == i32` +error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` --> $DIR/async.rs:12:17 | LL | needs_async(async {}); - | ----------- ^^^^^^^^ types differ + | ----------- ^^^^^^^^ expected `i32`, found `()` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/next-solver/async.rs b/tests/ui/traits/next-solver/async.rs index 34c0ed02eeb12..79985b6bb9962 100644 --- a/tests/ui/traits/next-solver/async.rs +++ b/tests/ui/traits/next-solver/async.rs @@ -10,7 +10,7 @@ fn needs_async(_: impl Future) {} #[cfg(fail)] fn main() { needs_async(async {}); - //[fail]~^ ERROR type mismatch resolving `() == i32` + //[fail]~^ ERROR: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` } #[cfg(pass)] diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr index 462544b405218..cc11aa018161a 100644 --- a/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr @@ -1,14 +1,20 @@ -error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}` +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` --> $DIR/lazy-nested-obligations-2.rs:20:21 | LL | let _: V = V(f); - | ^^^^ types differ + | ^^^^ expected fn item, found fn pointer + | + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` -error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}` +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` --> $DIR/lazy-nested-obligations-2.rs:27:22 | LL | let _: E3 = E3::Var(f); - | ^^^^^^^^^^ types differ + | ^^^^^^^^^^ expected fn item, found fn pointer + | + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs index 1dad1903a649d..7a7615be71fcf 100644 --- a/tests/ui/traits/next-solver/more-object-bound.rs +++ b/tests/ui/traits/next-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait::B> {} fn transmute(x: A) -> B { foo::>(x) - //~^ ERROR type mismatch resolving `A == B` + //~^ ERROR: type mismatch resolving ` as SuperTrait>::A == B` } fn foo(x: T::A) -> B diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index 7d279ed64282b..ccbf19ae4d96c 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -1,9 +1,17 @@ -error[E0271]: type mismatch resolving `A == B` +error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` --> $DIR/more-object-bound.rs:12:17 | +LL | fn transmute(x: A) -> B { + | - - expected type parameter + | | + | found type parameter LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters = note: required because it appears within the type `dyn Trait` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 From 0f6dab697eb3e2cfd7b7c04f1bb52f599df9b18f Mon Sep 17 00:00:00 2001 From: Adwin White Date: Thu, 14 May 2026 16:23:18 +0800 Subject: [PATCH 18/38] add some comments --- compiler/rustc_infer/src/infer/mod.rs | 17 ++++++++++------- .../src/infer/relate/higher_ranked.rs | 3 +++ .../rustc_next_trait_solver/src/normalize.rs | 13 +++++++++++-- .../src/solve/eval_ctxt/mod.rs | 11 ++++++++--- compiler/rustc_type_ir/src/predicate.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 2 +- compiler/rustc_type_ir/src/unnormalized.rs | 2 +- 7 files changed, 35 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 5a0ca1232fe6f..9c7f74e2061cf 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1379,6 +1379,16 @@ 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. + /// + /// If you're in the old solver or your binder doesn't have `Ambiguous` aliases, use + /// `instantiate_binder_with_fresh_vars_no_ambiguous_aliases` instead. pub fn instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( &self, span: Span, @@ -1419,13 +1429,6 @@ impl<'tcx> InferCtxt<'tcx> { value.map(|v| self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases(span, lbrct, v)) } - // 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. fn instantiate_binder_with_fresh_vars_raw( &self, span: Span, diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 48fe2403495a3..a5605ebdb6397 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -82,6 +82,9 @@ impl<'tcx> InferCtxt<'tcx> { /// This method should be preferred over `fn enter_forall_and_leak_universe`. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + /// + /// Check `renormalize_ambiguous_aliases` methods for handling the + /// `UnnormalizedAmbiguous` wrapper. #[instrument(level = "debug", skip(self, f))] pub fn enter_forall( &self, diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 1e2b2d771b8a3..df1824bf36b1f 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -16,7 +16,11 @@ use crate::placeholder::{BoundVarReplacer, PlaceholderReplacer}; /// This folder normalizes value and collects ambiguous goals. /// /// Note that for ambiguous alias which contains escaping bound vars, -/// we just return the original alias and don't collect the ambiguous goal. +/// we just return the original alias wrapped in `Ambiguous` alias and +/// don't collect the ambiguous goal. +/// +/// `Ambiguous` aliases are expected to be normalized away by +/// `BinderRenormalizer`. Though this folder can handle them as well. pub struct NormalizationFolder<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, @@ -282,7 +286,9 @@ where } } -// Only handle ambiguous alias in the outmost instantiated binder. +/// As a perf optimization, we only need to normalize aliases of `Ambiguous` +/// kind after instantiating binders, assuming other kinds of aliases have +/// been normalized before. pub struct BinderRenormalizer<'a, Infcx, I, F, E> where Infcx: InferCtxtLike, @@ -334,6 +340,9 @@ where &mut self, t: Binder, ) -> Result, Self::Error> { + // It's possible that we have ambiguous aliases which only reference + // outer instantiated bound vars in the nested inner binder. + // We should normalize those as well. if t.has_ambiguous_aliases() { t.try_super_fold_with(self) } else { Ok(t) } } 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 33651635d9940..896d5e66973da 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 @@ -1322,13 +1322,15 @@ where Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?) } + /// Same as the infcx one except we renormalize possible ambiguous aliases + /// in the instantiated binder. pub(super) fn instantiate_binder_with_infer + Copy>( &mut self, param_env: I::ParamEnv, value: ty::Binder, ) -> Result { let instantiated = self.delegate.instantiate_binder_with_infer(value); - self.normalize_ambiguous_only(param_env, instantiated) + self.renormalize_ambiguous_aliases(param_env, instantiated) } /// `enter_forall`, but takes `&mut self` and passes it back through the @@ -1337,6 +1339,9 @@ where /// The `param_env` is used to *compute* the assumptions of the binder, not *as* the /// assumptions associated with the binder. /// + /// We renormalize possible ambiguous aliases in the instantiated binder + /// before doing anything else. + /// /// FIXME(inherent_associated_types): fix this? pub(super) fn enter_forall_with_assumptions, U>( &mut self, @@ -1345,7 +1350,7 @@ where f: impl FnOnce(&mut Self, T) -> Result, ) -> Result { self.delegate.enter_forall(value, |value| { - let value = self.normalize_ambiguous_only(param_env, value)?; + let value = self.renormalize_ambiguous_aliases(param_env, value)?; let u = self.delegate.universe(); let assumptions = if self.cx().assumptions_on_binders() { self.region_assumptions_for_placeholders_in_universe(value.clone(), u, param_env) @@ -1754,7 +1759,7 @@ where /// /// This should be used after instantiating binders to improve perf, assuming that /// other normalizable aliases have been normalized before. - pub fn normalize_ambiguous_only>( + pub fn renormalize_ambiguous_aliases>( &mut self, param_env: I::ParamEnv, value: ty::UnnormalizedAmbiguous, diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 2added8a8b98e..cde2fd2cdb5c1 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -595,7 +595,7 @@ pub enum AliasTermKind { /// A wrapper that indicates the alias needs to be re-normalized. /// - /// It's specifc to ambiguous aliases that contain escaping bound vars. + /// It's specific to ambiguous aliases that contain escaping bound vars. /// This is an optimization for binder renormalization and is only used in the /// next solver. See `NormalizationFolder`. /// diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 28b2a934d7dec..1f6dee6b631c5 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -65,7 +65,7 @@ pub enum AliasTyKind { /// A wrapper that indicates the alias needs to be re-normalized. /// - /// It's specifc to ambiguous aliases that contain escaping bound vars. + /// It's specific to ambiguous aliases that contain escaping bound vars. /// This is an optimization for binder renormalization and is only used in the /// next solver. See `NormalizationFolder`. /// diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index e219fe2566e98..a33870e75ecd9 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -158,7 +158,7 @@ pub struct UnnormalizedAmbiguous { } impl UnnormalizedAmbiguous { - /// Should only be used in binder instantitation. + /// Should only be used in binder instantiation. pub fn new(value: T) -> Self { Self { value, _tcx: PhantomData } } From f2f6adfbce93ba6348244f360a98c04ee741bed3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 00:17:09 +0200 Subject: [PATCH 19/38] debugging jank --- compiler/rustc_middle/src/ty/context.rs | 27 +++++++++++++++++++ .../src/solve/alias_relate.rs | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1ff24bfb1fe0c..59f14e697cde5 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2064,6 +2064,22 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { + // TODO + match binder.skip_binder() { + ty::PredicateKind::AliasRelate(lhs, rhs, ..) => { + assert!( + lhs.to_alias_term(self) + .filter(|a| !matches!(a.kind, ty::AliasTermKind::AmbiguousTy)) + .is_some() + || rhs + .to_alias_term(self) + .filter(|a| !matches!(a.kind, ty::AliasTermKind::AmbiguousTy)) + .is_some(), + "{binder:?}" + ) + } + _ => {} + } self.interners.intern_predicate(binder) } @@ -2250,6 +2266,17 @@ impl<'tcx> TyCtxt<'tcx> { #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> { + // TODO + match st { + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args, .. }) => { + match args.type_at(0).kind() { + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. }) => unreachable!(), + ty::Alias(_) => {} + _ => unreachable!(), + } + } + _ => {} + } self.interners.intern_ty(st) } diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index 47d33985f9d36..2abbabaabf774 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -44,7 +44,8 @@ where lhs.to_alias_term(self.cx()).is_some() || rhs.to_alias_term(self.cx()).is_some() || lhs.is_error() - || rhs.is_error() + || rhs.is_error(), + "{lhs:?} {rhs:?}", ); // Structurally normalize the lhs. From 8e5bae3507da17b374de2f37cc96389912ebcfae Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 13:43:00 +0200 Subject: [PATCH 20/38] the coolest bean --- .../rustc_next_trait_solver/src/normalize.rs | 2 +- compiler/rustc_type_ir/src/relate/combine.rs | 5 +---- .../rustc_type_ir/src/relate/solver_relating.rs | 16 ++++++++++++++++ compiler/rustc_type_ir/src/unnormalized.rs | 5 +++++ .../ambiguous-on-failed-eval-with-vars-fail.rs | 4 ++-- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index df1824bf36b1f..b4c38c016e805 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -362,7 +362,7 @@ where let original_alias = args.type_at(0); if original_alias.has_escaping_bound_vars() { - Ok(original_alias) + Ok(ty) } else { Ok(ensure_sufficient_stack(|| self.normalize_alias_term(original_alias.into()))? .expect_ty()) diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index b9d33433c5ed7..832fc5d635335 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -115,10 +115,7 @@ where panic!("We do not expect to encounter `Fresh` variables in the new solver") } - (ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. }), _) - | (_, ty::Alias(ty::AliasTy { kind: ty::Ambiguous, .. })) => { - unreachable!("ambiguous alias in combine: {a:?} {b:?}") - } + (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => { match relation.structurally_relate_aliases() { StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 3f30f2e8c4637..e264588d48a58 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -305,6 +305,20 @@ where return Ok(a); } + match self.structurally_relate_aliases { + StructurallyRelateAliases::Yes => { + assert_eq!(a.bound_vars(), b.bound_vars()); + a.rebind((a.skip_binder(), b.skip_binder())); + self.infcx.enter_forall( a.rebind((a.skip_binder(), b.skip_binder())), |val| { + let (a, b) = val.keep_ambiguous_aliases_for_structurally_relate(); + self.relate(a, b) + })?; + return Ok(a); + + }, + StructurallyRelateAliases::No => {} + } + match self.ambient_variance { // Checks whether `for<..> sub <: for<..> sup` holds. // @@ -393,12 +407,14 @@ where &mut self, obligations: impl IntoIterator>, ) { + std::assert_matches!(self.structurally_relate_aliases, StructurallyRelateAliases::No); self.goals.extend( obligations.into_iter().map(|pred| Goal::new(self.infcx.cx(), self.param_env, pred)), ); } fn register_goals(&mut self, obligations: impl IntoIterator>) { + std::assert_matches!(self.structurally_relate_aliases, StructurallyRelateAliases::No); self.goals.extend(obligations); } diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index a33870e75ecd9..356043cf5d299 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -163,6 +163,11 @@ impl UnnormalizedAmbiguous { Self { value, _tcx: PhantomData } } + /// This should only be used when structurally relating types. + pub fn keep_ambiguous_aliases_for_structurally_relate(self) -> T { + self.value + } + /// Only use this if it will then normalize away all ambiguous aliases. pub fn do_normalize(self) -> T { self.value diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index 72952940b1c12..12e92d5530032 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -33,7 +33,7 @@ fn test_free() { fn test_free_mismatch() { let (mut arr, mut arr_with_weird_len) = free(); - //[next]~^ ERROR type mismatch resolving `10 == 2` + //[next]~^ ERROR type mismatch resolving `FREE::<10> == 2` arr_with_weird_len = [(); 2]; arr = [(); 10]; } @@ -50,7 +50,7 @@ fn test_proj() { fn test_proj_mismatch() { let (mut arr, mut arr_with_weird_len) = proj(); - //[next]~^ ERROR type mismatch resolving `10 == 2` + //[next]~^ ERROR type mismatch resolving `::PROJ::<10> == 2` arr_with_weird_len = [(); 2]; arr = [(); 10]; } From 4cc36611277e3271607c0eb2c49bffb05400b1ca Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 20:07:56 +0200 Subject: [PATCH 21/38] fix normalization --- compiler/rustc_next_trait_solver/src/normalize.rs | 3 +-- compiler/rustc_trait_selection/src/solve/normalize.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index b4c38c016e805..8befa77971836 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -146,7 +146,7 @@ where self.infcx.create_next_universe(); let (normalized, ambig_goal) = (self.normalize)(alias_term)?; - + self.stalled_goals.extend(ambig_goal); // Return ambiguous higher ranked alias as is, if // - it contains escaping vars, and // - the normalized term contains infer vars newly created @@ -164,7 +164,6 @@ where } } - self.stalled_goals.extend(ambig_goal); Ok((normalized, NeedRenormalization::No)) } } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 776648d2eaff4..13f19d701eea7 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -144,9 +144,12 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { return ty; } - let ty = ty.super_fold_with(self); - let ty::Alias(..) = *ty.kind() else { return ty }; - + let ty = match ty.kind() { + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args, .. }) => return args.type_at(0).fold_with(self), + ty::Alias(_) => ty.super_fold_with(self), + _ => return ty.super_fold_with(self), + }; + if ty.has_escaping_bound_vars() { let (replaced, ..) = BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ty); @@ -260,6 +263,7 @@ where return Err(errors); } + assert!(!value.has_ambiguous_aliases(), "unexpected ambig aliases after normalizing: {value:?}"); Ok((value, stalled_coroutine_goals)) } From ddccba7f11502cff0063d5ea3fc781db54036c76 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 20:08:10 +0200 Subject: [PATCH 22/38] fix bootstrap with new solver --- compiler/rustc_next_trait_solver/src/solve/effect_goals.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 db6b3d110c1ea..8a0f6c9bc74d8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -377,7 +377,7 @@ where _ecx: &mut EvalCtxt<'_, D>, _goal: Goal, ) -> Result, NoSolutionOrRerunNonErased> { - todo!("Iterator is not yet const") + Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) } fn consider_builtin_fused_iterator_candidate( From 9112e1ae8aa6ed408a2fd6b66e8af1772df1b52b Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 20:09:26 +0200 Subject: [PATCH 23/38] woops, fmt and random jank --- compiler/rustc_type_ir/src/relate/combine.rs | 1 - compiler/rustc_type_ir/src/relate/solver_relating.rs | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 832fc5d635335..77dfed9c3313a 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -115,7 +115,6 @@ where panic!("We do not expect to encounter `Fresh` variables in the new solver") } - (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => { match relation.structurally_relate_aliases() { StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index e264588d48a58..cf32b76caf283 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -309,13 +309,12 @@ where StructurallyRelateAliases::Yes => { assert_eq!(a.bound_vars(), b.bound_vars()); a.rebind((a.skip_binder(), b.skip_binder())); - self.infcx.enter_forall( a.rebind((a.skip_binder(), b.skip_binder())), |val| { + self.infcx.enter_forall(a.rebind((a.skip_binder(), b.skip_binder())), |val| { let (a, b) = val.keep_ambiguous_aliases_for_structurally_relate(); self.relate(a, b) })?; return Ok(a); - - }, + } StructurallyRelateAliases::No => {} } From 65f4378ac3bd1dc4fa13de5538ebc04366c9b960 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 20:28:13 +0200 Subject: [PATCH 24/38] fmt and fix ambiguity --- .../src/error_reporting/traits/ambiguity.rs | 7 ++++++- compiler/rustc_trait_selection/src/solve/normalize.rs | 11 ++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) 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 205a6abecb4de..1d048ece8d45e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -40,7 +40,12 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( let impl_may_apply = |impl_def_id| { let ocx = ObligationCtxt::new(infcx); - infcx.enter_forall_no_ambiguous_aliases(obligation.predicate, |placeholder_obligation| { + infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + let placeholder_obligation = ocx.renormalize_ambiguous_aliases( + &ObligationCause::dummy(), + param_env, + placeholder_obligation, + ); let obligation_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 13f19d701eea7..b6c7630f14055 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -145,11 +145,13 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { } let ty = match ty.kind() { - ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args, .. }) => return args.type_at(0).fold_with(self), + ty::Alias(ty::AliasTy { kind: ty::Ambiguous, args, .. }) => { + return args.type_at(0).fold_with(self); + } ty::Alias(_) => ty.super_fold_with(self), _ => return ty.super_fold_with(self), }; - + if ty.has_escaping_bound_vars() { let (replaced, ..) = BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ty); @@ -263,7 +265,10 @@ where return Err(errors); } - assert!(!value.has_ambiguous_aliases(), "unexpected ambig aliases after normalizing: {value:?}"); + assert!( + !value.has_ambiguous_aliases(), + "unexpected ambig aliases after normalizing: {value:?}" + ); Ok((value, stalled_coroutine_goals)) } From 1a6d5ad9dc9dcb9d1c2c729c8ef94797b6acd2d3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:02:57 +0200 Subject: [PATCH 25/38] cool! --- .../rustc_borrowck/src/diagnostics/mod.rs | 6 +- .../src/type_check/input_output.rs | 8 +- compiler/rustc_borrowck/src/type_check/mod.rs | 29 ++-- .../src/type_check/relate_tys.rs | 6 +- compiler/rustc_codegen_ssa/src/base.rs | 39 +++-- .../src/check/compare_eii.rs | 18 +-- .../src/check/compare_impl_item.rs | 24 ++- compiler/rustc_hir_typeck/src/callee.rs | 22 ++- compiler/rustc_hir_typeck/src/closure.rs | 23 ++- compiler/rustc_hir_typeck/src/expr.rs | 35 ++-- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 14 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 +- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 52 +++--- .../rustc_hir_typeck/src/method/suggest.rs | 13 +- compiler/rustc_infer/src/infer/context.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 54 +++---- .../src/infer/relate/higher_ranked.rs | 37 ++--- .../src/infer/relate/type_relating.rs | 40 ++--- .../src/opaque_hidden_inferred_bound.rs | 4 +- compiler/rustc_middle/src/ty/fold.rs | 5 +- .../src/error_reporting/traits/ambiguity.rs | 55 ++++--- .../traits/fulfillment_errors.rs | 84 ++++++---- .../src/error_reporting/traits/suggestions.rs | 49 +++--- .../src/traits/auto_trait.rs | 2 +- .../src/traits/coherence.rs | 3 +- .../src/traits/effects.rs | 2 +- .../src/traits/engine.rs | 44 ++++- .../src/traits/fulfill.rs | 2 +- .../src/traits/project.rs | 5 +- .../src/traits/select/candidate_assembly.rs | 4 +- .../src/traits/select/confirmation.rs | 51 +++--- .../src/traits/select/mod.rs | 152 +++++++++--------- compiler/rustc_type_ir/src/unnormalized.rs | 5 + 35 files changed, 479 insertions(+), 430 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 18c8e393635e3..7ebc153cc8849 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1460,8 +1460,9 @@ 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_no_ambiguous_aliases( + && let self_ty = self + .infcx + .instantiate_binder_with_fresh_vars( fn_call_span, BoundRegionConversionTime::FnCall, tcx.fn_sig(method_did) @@ -1469,6 +1470,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .skip_norm_wip() .input(0), ) + .no_ambiguous_aliases() && 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 5a8a626759de8..87236482a18ae 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -48,12 +48,14 @@ 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_no_ambiguous_aliases( + let mut user_provided_sig = self + .infcx + .instantiate_binder_with_fresh_vars( self.body.span, BoundRegionConversionTime::FnCall, user_provided_sig, - ); + ) + .no_ambiguous_aliases(); // 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 8429a2953ba15..c07585a78f525 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1076,12 +1076,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { && let target_sig = target_fn_tys.with(target_hdr) && let Some(target_sig) = target_sig.no_bound_vars() { - let src_sig = - self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + let src_sig = self + .infcx + .instantiate_binder_with_fresh_vars( span, BoundRegionConversionTime::HigherRankedType, src_sig, - ); + ) + .no_ambiguous_aliases(); let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig)); self.prove_predicate( ty::ClauseKind::WellFormed(src_ty.into()), @@ -1677,12 +1679,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *ty.kind() else { unreachable!(); }; - let expected_ty = - self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + let expected_ty = self + .infcx + .instantiate_binder_with_fresh_vars( self.body().source_info(location).span, BoundRegionConversionTime::HigherRankedType, binder_ty.into(), - ); + ) + .no_ambiguous_aliases(); self.sub_types( operand_ty, expected_ty, @@ -1918,11 +1922,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else { unreachable!(); }; - let found_ty = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - self.body.source_info(location).span, - BoundRegionConversionTime::HigherRankedType, - binder_ty.into(), - ); + let found_ty = self + .infcx + .instantiate_binder_with_fresh_vars( + self.body.source_info(location).span, + BoundRegionConversionTime::HigherRankedType, + binder_ty.into(), + ) + .no_ambiguous_aliases(); self.relate_types( ty, context.ambient_variance(), diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 5d8eb35ff368b..487e018551cbc 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -174,7 +174,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { { debug_assert!(!binder.has_ambiguous_aliases()); let value = if let Some(inner) = binder.no_bound_vars() { - inner + ty::UnnormalizedAmbiguous::dummy(inner) } else { let infcx = self.type_checker.infcx; let mut lazy_universe = None; @@ -208,7 +208,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { }; debug!(?value); - f(self, value) + f(self, value.no_ambiguous_aliases()) } #[instrument(skip(self), level = "debug")] @@ -247,7 +247,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { let replaced = infcx.tcx.replace_bound_vars_uncached(binder, delegate); debug!(?replaced); - replaced + replaced.no_ambiguous_aliases() } fn create_next_universe(&mut self) -> ty::UniverseIndex { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 323701ceeadd6..e2dd9a1c0474d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -128,26 +128,31 @@ pub fn validate_trivial_unsize<'tcx>( tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let universe = infcx.universe(); let ocx = ObligationCtxt::new(&infcx); - infcx.enter_forall_no_ambiguous_aliases(hr_target_principal, |target_principal| { - let source_principal = infcx - .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + ocx.enter_forall( + &ObligationCause::dummy(), + param_env, + hr_target_principal, + |target_principal| { + let source_principal = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), BoundRegionConversionTime::HigherRankedType, + param_env, hr_source_principal, ); - let Ok(()) = ocx.eq( - &ObligationCause::dummy(), - param_env, - target_principal, - source_principal, - ) else { - return false; - }; - if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() { - return false; - } - infcx.leak_check(universe, None).is_ok() - }) + let Ok(()) = ocx.eq( + &ObligationCause::dummy(), + param_env, + target_principal, + source_principal, + ) else { + return false; + }; + if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() { + return false; + } + infcx.leak_check(universe, None).is_ok() + }, + ) } (_, None) => true, _ => false, diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index c5139ee70a40a..4f5cc77eaf94a 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -73,16 +73,14 @@ pub(crate) fn compare_eii_function_types<'tcx>( debug!(?declaration_sig); // We need to check wf of the unnormalized sig. - let unnormalized_external_impl_sig = tcx - .fn_sig(external_impl) - .instantiate(tcx, infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id())) - .map(|sig| { - infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - external_impl_span, - infer::BoundRegionConversionTime::HigherRankedType, - sig, - ) - }); + let unnormalized_external_impl_sig = infcx.instantiate_unnormalized_binder_with_fresh_vars( + external_impl_span, + infer::BoundRegionConversionTime::HigherRankedType, + tcx.fn_sig(external_impl).instantiate( + tcx, + infcx.fresh_args_for_item(external_impl_span, external_impl.to_def_id()), + ), + ); let external_impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_external_impl_sig); debug!(?external_impl_sig); 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 2151011fe0efb..a8d60c97f1ca5 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -327,13 +327,11 @@ fn compare_method_predicate_entailment<'tcx>( let mut wf_tys = FxIndexSet::default(); // We need to check wf of unnormalized sig. - let unnormalized_impl_sig = tcx.fn_sig(impl_m.def_id).instantiate_identity().map(|sig| { - infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - impl_m_span, - BoundRegionConversionTime::HigherRankedType, - sig, - ) - }); + let unnormalized_impl_sig = infcx.instantiate_unnormalized_binder_with_fresh_vars( + impl_m_span, + BoundRegionConversionTime::HigherRankedType, + tcx.fn_sig(impl_m.def_id).instantiate_identity(), + ); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id); let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig); @@ -537,13 +535,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // Normalize the impl signature with fresh variables for lifetime inference. let misc_cause = ObligationCause::misc(return_span, impl_m_def_id); - let impl_sig = tcx.fn_sig(impl_m.def_id).instantiate_identity().map(|sig| { - infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - return_span, - BoundRegionConversionTime::HigherRankedType, - sig, - ) - }); + let impl_sig = infcx.instantiate_unnormalized_binder_with_fresh_vars( + return_span, + BoundRegionConversionTime::HigherRankedType, + tcx.fn_sig(impl_m.def_id).instantiate_identity(), + ); let impl_sig = ocx.normalize(&misc_cause, param_env, impl_sig); 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 6416bdabff81f..623d259677ece 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -232,12 +232,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Closure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { let def_id = def_id.expect_local(); let closure_sig = args.as_closure().sig(); - let closure_sig = self - .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( - call_expr.span, - BoundRegionConversionTime::FnCall, - closure_sig, - ); + let closure_sig = self.instantiate_binder_with_fresh_vars( + call_expr.span, + BoundRegionConversionTime::FnCall, + closure_sig, + ); let adjustments = self.adjust_steps(autoderef); self.record_deferred_call_resolution( def_id, @@ -260,12 +259,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::CoroutineClosure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { let def_id = def_id.expect_local(); let closure_args = args.as_coroutine_closure(); - let coroutine_closure_sig = self - .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( - call_expr.span, - BoundRegionConversionTime::FnCall, - closure_args.coroutine_closure_sig(), - ); + let coroutine_closure_sig = self.instantiate_binder_with_fresh_vars( + call_expr.span, + BoundRegionConversionTime::FnCall, + closure_args.coroutine_closure_sig(), + ); 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 diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 1f2026e34436f..6c58002825925 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -824,19 +824,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796 self.commit_if_ok(|_| { let mut all_obligations = PredicateObligations::new(); - let supplied_sig = self - .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( - self.tcx.def_span(expr_def_id), - BoundRegionConversionTime::FnCall, - supplied_sig, - |value| { - let cause = self.misc(self.tcx.def_span(expr_def_id)); - let InferOk { value, obligations } = - self.at(&cause, self.param_env).renormalize_ambiguous_aliases(value); - all_obligations.extend(obligations); - value - }, - ); + let supplied_sig = self.infcx.instantiate_binder_with_fresh_vars( + self.tcx.def_span(expr_def_id), + BoundRegionConversionTime::FnCall, + supplied_sig, + ); + + let cause = self.misc(self.tcx.def_span(expr_def_id)); + let InferOk { value: supplied_sig, obligations } = + self.at(&cause, self.param_env).renormalize_ambiguous_aliases(supplied_sig); + all_obligations.extend(obligations); // 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 3c07214aa0bd4..f1d9100a1d5f6 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -647,12 +647,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = call_expr_and_args .and_then(|(_, args)| args.get(i)) .map_or(expr.span, |arg| arg.span); - let input = self - .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( - span, - infer::BoundRegionConversionTime::FnCall, - fn_sig.input(i), - ); + let input = self.instantiate_binder_with_fresh_vars( + span, + infer::BoundRegionConversionTime::FnCall, + fn_sig.input(i), + ); self.require_type_is_sized_deferred( input, span, @@ -665,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Also, as we just want to check sizedness, instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. - let output = self.instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + let output = self.instantiate_binder_with_fresh_vars( expr.span, infer::BoundRegionConversionTime::FnCall, fn_sig.output(), @@ -1572,12 +1571,11 @@ 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_renormalize_ambiguous_aliases( - 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(), + ), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { let guar = self @@ -1610,12 +1608,11 @@ 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_renormalize_ambiguous_aliases( - 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(), + ), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { let guar = self diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 5d5712326cd87..d9bb8492871e0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -435,7 +435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - pub(crate) fn instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + pub(crate) fn instantiate_binder_with_fresh_vars( &self, span: Span, lbrct: BoundRegionConversionTime, @@ -444,15 +444,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { where T: TypeFoldable> + Copy, { - self.instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( - span, - lbrct, - value, - |value| { - self.register_infer_ok_obligations( - self.at(&self.misc(span), self.param_env).renormalize_ambiguous_aliases(value), - ) - }, + let value = self.infcx.instantiate_binder_with_fresh_vars(span, lbrct, value); + self.register_infer_ok_obligations( + self.at(&self.misc(span), self.param_env).renormalize_ambiguous_aliases(value), ) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 6d91eb18398d7..415630dab38b3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -3034,13 +3034,11 @@ 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_renormalize_ambiguous_aliases( - call_name.span, - BoundRegionConversionTime::FnCall, - fn_sig, - ); + self.call_ctxt.fn_ctxt.instantiate_binder_with_fresh_vars( + call_name.span, + BoundRegionConversionTime::FnCall, + fn_sig, + ); } None } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index a9b7305efdbd9..0fc0611177af2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -394,7 +394,9 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { item_segment: &rustc_hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> { - let trait_ref = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + // FIXME(#155345): We don't expect ambiguous aliases here as actually + // the `poly_trait_ref` is expected to be unnormalized. + let trait_ref = self.instantiate_binder_with_fresh_vars( span, // FIXME(mgca): `item_def_id` can be an AssocConst; rename this variant. infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id), diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 65ce0427a6cd4..0c83c1948d6f2 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -792,7 +792,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { where T: TypeFoldable> + Copy, { - self.fcx.instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( + self.fcx.instantiate_binder_with_fresh_vars( self.span, BoundRegionConversionTime::FnCall, value, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index e0992e2edea55..ecf1d80ca2c7d 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1073,13 +1073,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { match method.kind { ty::AssocKind::Fn { .. } => self.probe(|_| { let args = self.fresh_args_for_item(self.span, method.def_id); - let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args).map(|sig| { - self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - self.span, - BoundRegionConversionTime::FnCall, - sig, - ) - }); + let fty = self.instantiate_unnormalized_binder_with_fresh_vars( + self.span, + BoundRegionConversionTime::FnCall, + self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args), + ); // We shouldn't register predicates to fcx in `probe()` as they're not rollbacked. // Although it probably doesn't matter much for diagnostics. let ocx = ObligationCtxt::new(&self.infcx); @@ -1909,12 +1907,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref, _) => self.probe(|_| { - let trait_ref = self - .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases( - self.span, - BoundRegionConversionTime::FnCall, - trait_ref, - ); + let trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + BoundRegionConversionTime::FnCall, + trait_ref, + ); 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 @@ -2044,13 +2041,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - let trait_ref = self - .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( - self.span, - BoundRegionConversionTime::FnCall, - poly_trait_ref, - |value| ocx.renormalize_ambiguous_aliases(cause, self.param_env, value), - ); + let trait_ref = ocx.instantiate_binder_with_fresh_vars( + cause, + BoundRegionConversionTime::FnCall, + self.param_env, + poly_trait_ref, + ); (xform_self_ty, xform_ret_ty) = self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); xform_self_ty = @@ -2109,16 +2105,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { trait_predicate = Some(trait_ref.upcast(self.tcx)); } ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => { - // If we normalize the whole trait ref, this candidate can fail. - // Unsure if that's desirable. See - // `tests/ui/traits/trait-upcasting/mono-impossible.rs`. - let trait_ref = self - .instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( - self.span, - BoundRegionConversionTime::FnCall, - poly_trait_ref, - |value| value.no_ambiguous_aliases(), - ); + let trait_ref = ocx.instantiate_binder_with_fresh_vars( + cause, + BoundRegionConversionTime::FnCall, + self.param_env, + poly_trait_ref, + ); (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 c70b7cb820f26..cae3572856373 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2285,14 +2285,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // not methods because they don’t have an instance of the struct to work with. if def_kind == DefKind::AssocFn { let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id); - let fn_sig = - tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args).map(|sig| { - self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - span, - BoundRegionConversionTime::FnCall, - sig, - ) - }); + let fn_sig = self.instantiate_unnormalized_binder_with_fresh_vars( + span, + BoundRegionConversionTime::FnCall, + tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args), + ); let fn_sig = self.normalize(span, fn_sig); if similar_candidate.is_method() { if let Some(args) = args diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 1b79d31a95e97..0a13969fd8c37 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -202,11 +202,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { &self, value: ty::Binder<'tcx, T>, ) -> ty::UnnormalizedAmbiguous<'tcx, T> { - ty::UnnormalizedAmbiguous::new(self.instantiate_binder_with_fresh_vars_raw( + self.instantiate_binder_with_fresh_vars( DUMMY_SP, BoundRegionConversionTime::HigherRankedType, value, - )) + ) } fn enter_forall>, U>( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9c7f74e2061cf..0c0a4a1ac7cf2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -850,16 +850,14 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - self.enter_forall_no_ambiguous_aliases( - predicate, - |ty::SubtypePredicate { a_is_expected, a, b }| { - if a_is_expected { - Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) - } else { - Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a)) - } - }, - ) + self.enter_forall(predicate, |pred| { + let ty::SubtypePredicate { a_is_expected, a, b } = pred.no_ambiguous_aliases(); + if a_is_expected { + Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) + } else { + Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a)) + } + }) } /// Number of type variables created so far. @@ -1389,22 +1387,20 @@ impl<'tcx> InferCtxt<'tcx> { /// /// If you're in the old solver or your binder doesn't have `Ambiguous` aliases, use /// `instantiate_binder_with_fresh_vars_no_ambiguous_aliases` instead. - pub fn instantiate_binder_with_fresh_vars_renormalize_ambiguous_aliases_with( + pub fn instantiate_unnormalized_binder_with_fresh_vars( &self, span: Span, lbrct: BoundRegionConversionTime, - value: ty::Binder<'tcx, T>, - mut renormalize_ambig: F, - ) -> T + value: ty::Unnormalized<'tcx, ty::Binder<'tcx, T>>, + ) -> ty::Unnormalized<'tcx, T> where T: TypeFoldable> + Copy, - F: FnMut(ty::UnnormalizedAmbiguous<'tcx, T>) -> T, { - let instantiated = self.instantiate_binder_with_fresh_vars_raw(span, lbrct, value); - renormalize_ambig(ty::UnnormalizedAmbiguous::new(instantiated)) + value + .map(|v| self.instantiate_binder_with_fresh_vars(span, lbrct, v).no_ambiguous_aliases()) } - pub fn instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + pub fn instantiate_binder_with_fresh_vars_old_solver( &self, span: Span, lbrct: BoundRegionConversionTime, @@ -1413,33 +1409,21 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable> + Copy, { - assert!(!value.has_ambiguous_aliases()); - self.instantiate_binder_with_fresh_vars_raw(span, lbrct, value) - } - - pub fn instantiate_unnormalized_binder_with_fresh_vars( - &self, - span: Span, - lbrct: BoundRegionConversionTime, - value: ty::Unnormalized<'tcx, ty::Binder<'tcx, T>>, - ) -> ty::Unnormalized<'tcx, T> - where - T: TypeFoldable> + Copy, - { - value.map(|v| self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases(span, lbrct, v)) + debug_assert!(!self.next_trait_solver()); + self.instantiate_binder_with_fresh_vars(span, lbrct, value).no_ambiguous_aliases() } - fn instantiate_binder_with_fresh_vars_raw( + pub fn instantiate_binder_with_fresh_vars( &self, span: Span, lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, - ) -> T + ) -> ty::UnnormalizedAmbiguous<'tcx, T> where T: TypeFoldable> + Copy, { if let Some(inner) = value.no_bound_vars() { - return inner; + return ty::UnnormalizedAmbiguous::new(inner); } let bound_vars = value.bound_vars(); diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index a5605ebdb6397..ed28dfb9ce913 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -9,6 +9,13 @@ use crate::infer::InferCtxt; use crate::infer::snapshot::CombinedSnapshot; impl<'tcx> InferCtxt<'tcx> { + pub fn enter_forall_and_leak_universe_old_solver(&self, binder: ty::Binder<'tcx, T>) -> T + where + T: TypeFoldable>, + { + debug_assert!(!self.next_trait_solver()); + self.enter_forall_and_leak_universe(binder).no_ambiguous_aliases() + } /// Replaces all bound variables (lifetimes, types, and constants) bound by /// `binder` with placeholder variables in a new universe. This means that the /// new placeholders can only be named by inference variables created after @@ -22,32 +29,17 @@ impl<'tcx> InferCtxt<'tcx> { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html /// /// This is expected to be used in the old solver only so no ambiguous aliases allowed. - pub fn enter_forall_and_leak_universe(&self, binder: ty::Binder<'tcx, T>) -> T - where - T: TypeFoldable>, - { - debug_assert!(!binder.has_ambiguous_aliases()); - self.enter_forall_and_leak_universe_raw(binder) - } - - pub fn enter_forall_with_ambiguous_aliases_and_leak_universe( + #[instrument(level = "debug", skip(self), ret)] + pub fn enter_forall_and_leak_universe( &self, binder: ty::Binder<'tcx, T>, ) -> ty::UnnormalizedAmbiguous<'tcx, T> - where - T: TypeFoldable>, - { - ty::UnnormalizedAmbiguous::new(self.enter_forall_and_leak_universe_raw(binder)) - } - - #[instrument(level = "debug", skip(self), ret)] - fn enter_forall_and_leak_universe_raw(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable>, { // Inlined `no_bound_vars`. if !binder.as_ref().skip_binder().has_escaping_bound_vars() { - return binder.skip_binder(); + return ty::UnnormalizedAmbiguous::dummy(binder.skip_binder()); } let next_universe = self.create_next_universe(); @@ -98,13 +90,13 @@ 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_raw(forall); + let value = self.enter_forall_and_leak_universe(forall); debug!(?value); - f(ty::UnnormalizedAmbiguous::new(value)) + f(value) } #[instrument(level = "debug", skip(self, f))] - pub fn enter_forall_no_ambiguous_aliases( + pub fn enter_forall_old_solver( &self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U, @@ -112,9 +104,10 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable>, { + debug_assert!(!self.next_trait_solver()); let value = self.enter_forall_and_leak_universe(forall); debug!(?value); - f(value) + f(value.no_ambiguous_aliases()) } /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index f0751631beea9..9660f457b7fc1 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -299,23 +299,15 @@ 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_no_ambiguous_aliases(b, |b| { - let a = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - span, - HigherRankedType, - a, - ); - self.relate(a, b) + infcx.enter_forall(b, |b| { + let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); + self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) })?; } ty::Contravariant => { - infcx.enter_forall_no_ambiguous_aliases(a, |a| { - let b = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - span, - HigherRankedType, - b, - ); - self.relate(a, b) + infcx.enter_forall(a, |a| { + let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); + self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) })?; } @@ -330,23 +322,15 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`. // Check if `exists<..> A == for<..> B` ty::Invariant => { - infcx.enter_forall_no_ambiguous_aliases(b, |b| { - let a = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - span, - HigherRankedType, - a, - ); - self.relate(a, b) + infcx.enter_forall(b, |b| { + let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); + self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) })?; // Check if `exists<..> B == for<..> A`. - infcx.enter_forall_no_ambiguous_aliases(a, |a| { - let b = infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - span, - HigherRankedType, - b, - ); - self.relate(a, b) + infcx.enter_forall(a, |a| { + let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); + self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) })?; } ty::Bivariant => { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index d3bee1970b25c..f04d670c33f59 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -94,8 +94,8 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { .iter_identity_copied() .map(Unnormalized::skip_norm_wip) { - infcx.enter_forall_no_ambiguous_aliases(pred.kind(), |predicate| { - let ty::ClauseKind::Projection(proj) = predicate else { + infcx.enter_forall(pred.kind(), |predicate| { + let ty::ClauseKind::Projection(proj) = predicate.no_ambiguous_aliases() else { return; }; // Only check types, since those are the only things that may diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 3d9148d6ed7ba..606d2438531e0 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -265,8 +265,9 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, delegate: impl BoundVarReplacerDelegate<'tcx>, - ) -> T { - self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate) + ) -> ty::UnnormalizedAmbiguous<'tcx, T> { + let value = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate); + ty::UnnormalizedAmbiguous::new(value) } /// Replaces any late-bound regions bound in `value` with 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 1d048ece8d45e..66a7cbfedc79a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -102,37 +102,42 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( }; let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| { - let ocx = ObligationCtxt::new(infcx); - infcx.enter_forall_no_ambiguous_aliases(obligation.predicate, |placeholder_obligation| { - let obligation_trait_ref = ocx.normalize( - &ObligationCause::dummy(), - param_env, - Unnormalized::new_wip(placeholder_obligation.trait_ref), - ); + let ocx: ObligationCtxt<'_, '_> = ObligationCtxt::new(infcx); + ocx.enter_forall( + &ObligationCause::dummy(), + param_env, + obligation.predicate, + |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + Unnormalized::new_wip(placeholder_obligation.trait_ref), + ); - let param_env_predicate = infcx - .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + let param_env_predicate = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), BoundRegionConversionTime::HigherRankedType, + param_env, poly_trait_predicate, ); - let param_env_trait_ref = ocx.normalize( - &ObligationCause::dummy(), - param_env, - Unnormalized::new_wip(param_env_predicate.trait_ref), - ); + let param_env_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + Unnormalized::new_wip(param_env_predicate.trait_ref), + ); - if let Err(_) = ocx.eq( - &ObligationCause::dummy(), - param_env, - obligation_trait_ref, - param_env_trait_ref, - ) { - return false; - } + if let Err(_) = ocx.eq( + &ObligationCause::dummy(), + param_env, + obligation_trait_ref, + param_env_trait_ref, + ) { + return false; + } - ocx.try_evaluate_obligations().is_empty() - }) + ocx.try_evaluate_obligations().is_empty() + }, + ) }; let mut ambiguities = Vec::new(); 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 998e2c93fe7b4..05b633167c127 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 @@ -833,11 +833,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { diag.downgrade_to_delayed_bug(); } - if let Ok(Some(ImplSource::UserDefined(impl_data))) = self - .enter_forall_no_ambiguous_aliases(trait_ref, |trait_ref_for_select| { + let ocx = ObligationCtxt::new(self); + let impl_source = ocx.enter_forall( + &ObligationCause::dummy(), + obligation.param_env, + trait_ref, + |trait_ref_for_select| { SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref_for_select)) - }) - { + }, + ); + if let Ok(Some(ImplSource::UserDefined(impl_data))) = impl_source { let impl_did = impl_data.impl_def_id; let trait_did = trait_ref.def_id(); let impl_span = self.tcx.def_span(impl_did); @@ -958,11 +963,20 @@ 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_no_ambiguous_aliases(found_args, |found_args| { - self.enter_forall_no_ambiguous_aliases(expected_args, |expected_args| { - !self.can_eq(obligation.param_env, expected_args, found_args) - }) - }) { + let ocx = ObligationCtxt::new(self); + if ocx.enter_forall( + &ObligationCause::dummy(), + obligation.param_env, + found_args, + |found_args| { + ocx.enter_forall( + &ObligationCause::dummy(), + obligation.param_env, + expected_args, + |expected_args| !self.can_eq(obligation.param_env, expected_args, found_args), + ) + }, + ) { return None; } @@ -1402,7 +1416,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut pred = obligation.predicate.as_trait_clause(); while let Some((next_code, next_pred)) = code.parent_with_predicate() { if let Some(pred) = pred { - self.enter_forall_no_ambiguous_aliases(pred, |pred| { + let ocx = ObligationCtxt::new(self); + ocx.enter_forall(&ObligationCause::dummy(), obligation.param_env, pred, |pred| { let ty = self.tcx.short_string(pred.self_ty(), diag.long_ty_path()); let trait_path = self .tcx @@ -1421,6 +1436,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn can_match_trait( &self, + ocx: &ObligationCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, goal: ty::TraitPredicate<'tcx>, assumption: ty::PolyTraitPredicate<'tcx>, @@ -1430,9 +1446,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; } - let trait_assumption = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + let trait_assumption = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), infer::BoundRegionConversionTime::HigherRankedType, + param_env, assumption, ); @@ -1441,13 +1458,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn can_match_host_effect( &self, + ocx: &ObligationCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, goal: ty::HostEffectPredicate<'tcx>, assumption: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, ) -> bool { - let assumption = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + let assumption = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), infer::BoundRegionConversionTime::HigherRankedType, + param_env, assumption, ); @@ -1466,13 +1485,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn can_match_projection( &self, + ocx: &ObligationCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, goal: ty::ProjectionPredicate<'tcx>, assumption: ty::PolyProjectionPredicate<'tcx>, ) -> bool { - let assumption = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + let assumption = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), infer::BoundRegionConversionTime::HigherRankedType, + param_env, assumption, ); @@ -1500,23 +1521,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let param_env = error.param_env; + let ocx = ObligationCtxt::new(self); if let Some(error) = error.predicate.as_trait_clause() { - self.enter_forall_no_ambiguous_aliases(error, |error| { + ocx.enter_forall(&ObligationCause::dummy(), param_env, error, |error| { 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)) + .any(|implied| self.can_match_trait(&ocx, param_env, error, implied)) }) } else if let Some(error) = Self::as_host_effect_clause(error.predicate) { - self.enter_forall_no_ambiguous_aliases(error, |error| { + ocx.enter_forall(&ObligationCause::dummy(), param_env, error, |error| { 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)) + .any(|implied| self.can_match_host_effect(&ocx, param_env, error, implied)) }) } else if let Some(error) = error.predicate.as_projection_clause() { - self.enter_forall_no_ambiguous_aliases(error, |error| { + ocx.enter_forall(&ObligationCause::dummy(), param_env, error, |error| { 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)) + .any(|implied| self.can_match_projection(&ocx, param_env, error, implied)) }) } else { false @@ -1545,14 +1567,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { let ocx = ObligationCtxt::new(self); - let data = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - obligation.cause.span, + let data = ocx.instantiate_binder_with_fresh_vars( + &obligation.cause, infer::BoundRegionConversionTime::HigherRankedType, + obligation.param_env, bound_predicate.rebind(data), ); 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. let normalized_term = ocx.normalize( &obligation.cause, obligation.param_env, @@ -1686,7 +1707,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; }; - let trait_ref = self.enter_forall_and_leak_universe( + let ocx = ObligationCtxt::new(self); + let trait_ref = ocx.enter_forall_and_leak_universe( + &ObligationCause::dummy(), + obligation.param_env, predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)), ); let Ok(Some(ImplSource::UserDefined(impl_data))) = @@ -2075,11 +2099,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // that failed. This should uncover a better hint for what *is* implemented. if self.probe(|_| { let ocx = ObligationCtxt::new(self); - - self.enter_forall_no_ambiguous_aliases(trait_pred, |obligation_trait_ref| { + let cause = &ObligationCause::dummy(); + ocx.enter_forall(&cause, param_env, trait_pred, |obligation_trait_ref| { let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); let impl_trait_ref = ocx.normalize( - &ObligationCause::dummy(), + &cause, param_env, ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), ); 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 bde878a756fe3..299c517bb5af0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1014,9 +1014,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; } - let self_ty = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + let ocx = ObligationCtxt::new(self); + let self_ty = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), BoundRegionConversionTime::FnCall, + obligation.param_env, trait_pred.self_ty(), ); @@ -1345,8 +1347,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err: &mut Diag<'_>, trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { + let ocx = ObligationCtxt::new(self); let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); - self.enter_forall_no_ambiguous_aliases(self_ty, |ty: Ty<'_>| { + ocx.enter_forall(&ObligationCause::dummy(), obligation.param_env, self_ty, |ty: Ty<'_>| { let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_id) else { return false; }; @@ -1558,18 +1561,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return None; }; - let output = self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + let ocx = ObligationCtxt::new(self); + let output = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), BoundRegionConversionTime::FnCall, + param_env, output, ); let inputs = inputs .skip_binder() .iter() .map(|ty| { - self.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - DUMMY_SP, + ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), BoundRegionConversionTime::FnCall, + param_env, inputs.rebind(*ty), ) }) @@ -4845,20 +4851,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some(failed_pred) = failed_pred.as_trait_clause() && where_pred.def_id() == failed_pred.def_id() { - self.enter_forall_no_ambiguous_aliases(where_pred, |where_pred| { - let failed_pred = self - .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - expr.span, - BoundRegionConversionTime::FnCall, - failed_pred, - ); + let ocx = ObligationCtxt::new(self); + let cause = ObligationCause::dummy(); + ocx.enter_forall(&cause, param_env, where_pred, |where_pred| { + let failed_pred = ocx.instantiate_binder_with_fresh_vars( + &cause, + BoundRegionConversionTime::FnCall, + param_env, + failed_pred, + ); let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); for (expected, actual) in zipped { self.probe(|_| { match self - .at(&ObligationCause::misc(expr.span, body_id), param_env) + .at(&cause, param_env) // Doesn't actually matter if we define opaque types here, this is just used for // diagnostics, and the result is never kept around. .eq(DefineOpaqueTypes::Yes, expected, actual) @@ -5589,7 +5597,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { self.probe(|_| { let ocx = ObligationCtxt::new(self); - self.enter_forall_no_ambiguous_aliases(pred, |pred| { + ocx.enter_forall(&ObligationCause::dummy(), param_env, pred, |pred| { let pred = ocx.normalize( &ObligationCause::dummy(), param_env, @@ -6061,9 +6069,12 @@ fn hint_missing_borrow<'tcx>( return; } + let ocx = ObligationCtxt::new(infcx); let found_args = match found.kind() { ty::FnPtr(sig_tys, _) => { - infcx.enter_forall_no_ambiguous_aliases(*sig_tys, |sig_tys| sig_tys.inputs().iter()) + ocx.enter_forall(&ObligationCause::dummy(), param_env, *sig_tys, |sig_tys| { + sig_tys.inputs().iter() + }) } kind => { span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind) @@ -6071,7 +6082,9 @@ fn hint_missing_borrow<'tcx>( }; let expected_args = match expected.kind() { ty::FnPtr(sig_tys, _) => { - infcx.enter_forall_no_ambiguous_aliases(*sig_tys, |sig_tys| sig_tys.inputs().iter()) + ocx.enter_forall(&ObligationCause::dummy(), param_env, *sig_tys, |sig_tys| { + sig_tys.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 44e331f6bb2fa..afe7cb4b36e96 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -739,7 +739,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); - selcx.infcx.enter_forall_no_ambiguous_aliases(binder, |pred| { + selcx.infcx.enter_forall_old_solver(binder, |pred| { selcx.infcx.register_region_outlives_constraint(pred, ty::VisibleForLeakCheck::Yes,&dummy_cause); }); } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 5be402c6da33e..1553a534b38c8 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -748,8 +748,7 @@ 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_with_ambiguous_aliases_and_leak_universe(predicate.kind()); + let predicate_kind = goal.infcx().enter_forall_and_leak_universe(predicate.kind()); let ocx = ObligationCtxt::new(infcx); let predicate_kind = ocx.renormalize_ambiguous_aliases(&ObligationCause::dummy(), param_env, predicate_kind); diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index b3097006d0d9a..b7924c1e18356 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -89,7 +89,7 @@ fn match_candidate<'tcx>( return Err(NoSolution); } - let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars_old_solver( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, candidate, diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index c972a31daa6e1..2f83d7b95dd9f 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -8,7 +8,10 @@ use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; -use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace}; +use rustc_infer::infer::{ + BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, + TypeTrace, +}; use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; @@ -361,6 +364,45 @@ where self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut()) } + pub fn enter_forall>, U>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: ty::Binder<'tcx, T>, + f: impl FnOnce(T) -> U, + ) -> U { + self.infcx.enter_forall(value, |value| { + f(self.renormalize_ambiguous_aliases(cause, param_env, value)) + }) + } + + pub fn enter_forall_and_leak_universe( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + binder: ty::Binder<'tcx, T>, + ) -> T + where + T: TypeFoldable>, + { + let value = self.infcx.enter_forall_and_leak_universe(binder); + self.renormalize_ambiguous_aliases(cause, param_env, value) + } + + pub fn instantiate_binder_with_fresh_vars( + &self, + cause: &ObligationCause<'tcx>, + lbrct: BoundRegionConversionTime, + param_env: ty::ParamEnv<'tcx>, + value: ty::Binder<'tcx, T>, + ) -> T + where + T: TypeFoldable> + Copy, + { + let value = self.infcx.instantiate_binder_with_fresh_vars(cause.span, lbrct, value); + self.renormalize_ambiguous_aliases(cause, param_env, value) + } + pub fn structurally_normalize_ty( &self, cause: &ObligationCause<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index ce8f05637f9a6..c67491ee94f9a 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -450,7 +450,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_old_solver(binder)); 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 9a5ea15540515..003c274e076d8 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_old_solver(obligation.predicate); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); match project_and_unify_term(selcx, &placeholder_obligation) { @@ -1910,7 +1911,7 @@ 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_no_ambiguous_aliases( + let cache_entry = infcx.instantiate_binder_with_fresh_vars_old_solver( cause.span, BoundRegionConversionTime::HigherRankedType, poly_cache_entry, 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 a161154692fd7..486cc3cb8b3d0 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_old_solver(poly_trait_predicate); // The bounds returned by `item_bounds` may contain duplicates after // normalization, so try to deduplicate when possible to avoid @@ -924,7 +924,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_no_ambiguous_aliases( + self.infcx.enter_forall_old_solver( poly_trait_predicate, |placeholder_trait_predicate| { let self_ty = placeholder_trait_predicate.self_ty(); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index cd13912969e0c..b0344aa15376a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -147,7 +147,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { idx: usize, ) -> Result, SelectionError<'tcx>> { let placeholder_trait_predicate = - self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref; + self.infcx.enter_forall_and_leak_universe_old_solver(obligation.predicate).trait_ref; let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty()); let candidate_predicate = self .for_each_item_bound( @@ -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_no_ambiguous_aliases( + let candidate = self.infcx.instantiate_binder_with_fresh_vars_old_solver( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, candidate, @@ -236,7 +236,7 @@ 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_old_solver(obligation.predicate.self_ty()), ); let types = match tcx.as_lang_item(trait_def) { Some(LangItem::Sized) => self.sizedness_conditions(self_ty, SizedTraitKind::Sized), @@ -267,7 +267,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_old_solver(types); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); self.collect_predicates_for_types( @@ -348,7 +348,7 @@ 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_old_solver(obligation.predicate); let mut assume = predicate.trait_ref.args.const_at(2); if self.tcx().features().generic_const_exprs() { @@ -389,10 +389,10 @@ 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_old_solver(self_ty); 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_old_solver(constituents); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); let mut obligations = self.collect_predicates_for_types( @@ -490,7 +490,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_old_solver(obligation.predicate); 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"); @@ -499,7 +500,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let object_trait_ref = data.principal().unwrap_or_else(|| { span_bug!(obligation.cause.span, "object candidate with no principal") }); - let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_old_solver( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, object_trait_ref, @@ -512,7 +513,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_no_ambiguous_aliases( + let upcast_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_old_solver( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, unnormalized_upcast_trait_ref, @@ -598,7 +599,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_old_solver(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); @@ -617,7 +619,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_old_solver(sig.output()); let output_ty = normalize_with_depth_to( self, obligation.param_env, @@ -642,7 +644,7 @@ 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_old_solver(obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let args = trait_ref.args; @@ -665,7 +667,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_old_solver(obligation.predicate); 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); @@ -695,7 +698,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_old_solver(obligation.predicate); 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); @@ -725,7 +729,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_old_solver(obligation.predicate); 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); @@ -755,7 +760,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_old_solver(obligation.predicate); 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); @@ -786,7 +792,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_old_solver(obligation.predicate); let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let trait_ref = match *self_ty.kind() { @@ -815,7 +822,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_old_solver(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); @@ -881,7 +889,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_old_solver(sig.output()); nested.push(obligation.with( tcx, ty::TraitRef::new(tcx, future_trait_def_id, [placeholder_output_ty]), @@ -962,7 +971,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: TraitObligation<'tcx>, found_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result, SelectionError<'tcx>> { - let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars_old_solver( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, found_trait_ref, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d7f49c1cfe437..c056544d431b6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -624,9 +624,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.evaluate_trait_predicate_recursively(previous_stack, obligation) } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => self - .infcx - .enter_forall_no_ambiguous_aliases(bound_predicate.rebind(data), |data| { + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => { + self.infcx.enter_forall_old_solver(bound_predicate.rebind(data), |data| { match effects::evaluate_host_effect_obligation( self, &obligation.with(self.tcx(), data), @@ -637,7 +636,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(effects::EvaluationFailure::Ambiguous) => Ok(EvaluatedToAmbig), Err(effects::EvaluationFailure::NoSolution) => Ok(EvaluatedToErr), } - }), + }) + } ty::PredicateKind::Subtype(p) => { let p = bound_predicate.rebind(p); @@ -1721,7 +1721,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let trait_bound = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + let trait_bound = self.infcx.instantiate_binder_with_fresh_vars_old_solver( obligation.cause.span, HigherRankedType, trait_bound, @@ -1778,7 +1778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug_assert_eq!(obligation.predicate.def_id(), env_predicate.item_def_id()); let mut nested_obligations = PredicateObligations::new(); - let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( + let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars_old_solver( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, env_predicate, @@ -2532,7 +2532,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_old_solver(obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); @@ -2623,28 +2623,24 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx - .enter_forall_no_ambiguous_aliases( - hr_target_principal, - |target_principal| { - let source_principal = self - .infcx - .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - obligation.cause.span, - HigherRankedType, - hr_source_principal, - ); - self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( - DefineOpaqueTypes::Yes, - ToTrace::to_trace( - &obligation.cause, - hr_target_principal, - hr_source_principal, - ), - target_principal, - source_principal, - ) - }, - ) + .enter_forall_old_solver(hr_target_principal, |target_principal| { + let source_principal = + self.infcx.instantiate_binder_with_fresh_vars_old_solver( + obligation.cause.span, + HigherRankedType, + hr_source_principal, + ); + self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + hr_target_principal, + hr_source_principal, + ), + target_principal, + source_principal, + ) + }) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); @@ -2663,23 +2659,31 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // here instead of equating and processing obligations. hr_source_projection.item_def_id() == hr_target_projection.item_def_id() && self.infcx.probe(|_| { - self.infcx.enter_forall_no_ambiguous_aliases(hr_target_projection, - |target_projection| { - let source_projection = - self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases(obligation.cause.span, HigherRankedType, hr_source_projection); - self.infcx - .at(&obligation.cause, obligation.param_env) - .eq_trace( - DefineOpaqueTypes::Yes, - ToTrace::to_trace( - &obligation.cause, - hr_target_projection, - hr_source_projection, - ), - target_projection, - source_projection, - ) - },) + self.infcx + .enter_forall_old_solver( + hr_target_projection, + |target_projection| { + let source_projection = self + .infcx + .instantiate_binder_with_fresh_vars_old_solver( + obligation.cause.span, + HigherRankedType, + hr_source_projection, + ); + self.infcx + .at(&obligation.cause, obligation.param_env) + .eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + hr_target_projection, + hr_source_projection, + ), + target_projection, + source_projection, + ) + }, + ) .is_ok() }) }); @@ -2692,28 +2696,24 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } nested.extend( self.infcx - .enter_forall_no_ambiguous_aliases( - hr_target_projection, - |target_projection| { - let source_projection = self - .infcx - .instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - obligation.cause.span, - HigherRankedType, - hr_source_projection, - ); - self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( - DefineOpaqueTypes::Yes, - ToTrace::to_trace( - &obligation.cause, - hr_target_projection, - hr_source_projection, - ), - target_projection, - source_projection, - ) - }, - ) + .enter_forall_old_solver(hr_target_projection, |target_projection| { + let source_projection = + self.infcx.instantiate_binder_with_fresh_vars_old_solver( + obligation.cause.span, + HigherRankedType, + hr_source_projection, + ); + self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + hr_target_projection, + hr_source_projection, + ), + target_projection, + source_projection, + ) + }) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); @@ -2757,12 +2757,16 @@ 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 trait_ref = self.infcx.instantiate_binder_with_fresh_vars_no_ambiguous_aliases( - obligation.cause.span, - HigherRankedType, - poly_trait_ref, - ); + let predicate = + self.infcx.enter_forall_and_leak_universe(obligation.predicate).no_ambiguous_aliases(); + let trait_ref = self + .infcx + .instantiate_binder_with_fresh_vars( + obligation.cause.span, + HigherRankedType, + poly_trait_ref, + ) + .no_ambiguous_aliases(); self.infcx .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::No, predicate.trait_ref, trait_ref) diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index 356043cf5d299..752c10d9cf5de 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -163,6 +163,11 @@ impl UnnormalizedAmbiguous { Self { value, _tcx: PhantomData } } + pub fn dummy(value: T) -> Self { + // TODO: assert no unnormalized alias without escaping bound vars + Self { value, _tcx: PhantomData } + } + /// This should only be used when structurally relating types. pub fn keep_ambiguous_aliases_for_structurally_relate(self) -> T { self.value From 335882a9e47768cb9ea2e582201f043d13fa232c Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:06:37 +0200 Subject: [PATCH 26/38] w --- .../rustc_borrowck/src/diagnostics/mod.rs | 19 ++++----- compiler/rustc_borrowck/src/lib.rs | 17 +++++++- .../src/type_check/input_output.rs | 13 +++---- compiler/rustc_borrowck/src/type_check/mod.rs | 39 +++++++------------ 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 7ebc153cc8849..248396ba9849b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1460,17 +1460,14 @@ 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), - ) - .no_ambiguous_aliases() + && 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), + ) && self.infcx.can_eq(self.infcx.param_env, ty, self_ty) { err.subdiagnostic(CaptureReasonSuggest::FreshReborrow { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8b9f4291603a9..c8d6b7c02a6f4 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -32,7 +32,8 @@ use rustc_index::bit_set::MixedBitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::{ - InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, + BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, + TyCtxtInferExt, }; use rustc_middle::mir::*; use rustc_middle::query::Providers; @@ -707,6 +708,20 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { next_region } + + /// We expect all aliases to already be fully normalized during borrowck, + /// so we can redefine this method to just unwrap the unnormalized alias binder. + pub(crate) fn instantiate_binder_with_fresh_vars( + &self, + span: Span, + lbrct: BoundRegionConversionTime, + value: ty::Binder<'tcx, T>, + ) -> T + where + T: TypeFoldable> + Copy, + { + self.infcx.instantiate_binder_with_fresh_vars(span, lbrct, value).no_ambiguous_aliases() + } } impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 87236482a18ae..fe40173b905d6 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -48,14 +48,11 @@ 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( - self.body.span, - BoundRegionConversionTime::FnCall, - user_provided_sig, - ) - .no_ambiguous_aliases(); + let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( + self.body.span, + BoundRegionConversionTime::FnCall, + user_provided_sig, + ); // 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 c07585a78f525..13983f349d6a5 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1076,14 +1076,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { && let target_sig = target_fn_tys.with(target_hdr) && let Some(target_sig) = target_sig.no_bound_vars() { - let src_sig = self - .infcx - .instantiate_binder_with_fresh_vars( - span, - BoundRegionConversionTime::HigherRankedType, - src_sig, - ) - .no_ambiguous_aliases(); + let src_sig = self.infcx.instantiate_binder_with_fresh_vars( + span, + BoundRegionConversionTime::HigherRankedType, + src_sig, + ); let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig)); self.prove_predicate( ty::ClauseKind::WellFormed(src_ty.into()), @@ -1679,14 +1676,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *ty.kind() else { unreachable!(); }; - let expected_ty = self - .infcx - .instantiate_binder_with_fresh_vars( - self.body().source_info(location).span, - BoundRegionConversionTime::HigherRankedType, - binder_ty.into(), - ) - .no_ambiguous_aliases(); + let expected_ty = self.infcx.instantiate_binder_with_fresh_vars( + self.body().source_info(location).span, + BoundRegionConversionTime::HigherRankedType, + binder_ty.into(), + ); self.sub_types( operand_ty, expected_ty, @@ -1922,14 +1916,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else { unreachable!(); }; - let found_ty = self - .infcx - .instantiate_binder_with_fresh_vars( - self.body.source_info(location).span, - BoundRegionConversionTime::HigherRankedType, - binder_ty.into(), - ) - .no_ambiguous_aliases(); + let found_ty = self.infcx.instantiate_binder_with_fresh_vars( + self.body.source_info(location).span, + BoundRegionConversionTime::HigherRankedType, + binder_ty.into(), + ); self.relate_types( ty, context.ambient_variance(), From d39b14fce06b889b133b3403c5769d139c1f6044 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:09:13 +0200 Subject: [PATCH 27/38] w --- .../src/type_check/relate_tys.rs | 2 - compiler/rustc_codegen_ssa/src/base.rs | 41 ++++++++----------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 487e018551cbc..8f80081859016 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -172,7 +172,6 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { where T: ty::TypeFoldable> + Copy, { - debug_assert!(!binder.has_ambiguous_aliases()); let value = if let Some(inner) = binder.no_bound_vars() { ty::UnnormalizedAmbiguous::dummy(inner) } else { @@ -216,7 +215,6 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { where T: ty::TypeFoldable> + Copy, { - debug_assert!(!binder.has_ambiguous_aliases()); if let Some(inner) = binder.no_bound_vars() { return inner; } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index e2dd9a1c0474d..92132db2fe6da 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -128,31 +128,22 @@ pub fn validate_trivial_unsize<'tcx>( tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let universe = infcx.universe(); let ocx = ObligationCtxt::new(&infcx); - ocx.enter_forall( - &ObligationCause::dummy(), - param_env, - hr_target_principal, - |target_principal| { - let source_principal = ocx.instantiate_binder_with_fresh_vars( - &ObligationCause::dummy(), - BoundRegionConversionTime::HigherRankedType, - param_env, - hr_source_principal, - ); - let Ok(()) = ocx.eq( - &ObligationCause::dummy(), - param_env, - target_principal, - source_principal, - ) else { - return false; - }; - if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() { - return false; - } - infcx.leak_check(universe, None).is_ok() - }, - ) + let cause = ObligationCause::dummy(); + ocx.enter_forall(&cause, param_env, hr_target_principal, |target_principal| { + let source_principal = ocx.instantiate_binder_with_fresh_vars( + &cause, + BoundRegionConversionTime::HigherRankedType, + param_env, + hr_source_principal, + ); + let Ok(()) = ocx.eq(&cause, param_env, target_principal, source_principal) else { + return false; + }; + if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() { + return false; + } + infcx.leak_check(universe, None).is_ok() + }) } (_, None) => true, _ => false, From 976f639465b7f7cd85c56d55fb8745c53a673ba2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:12:28 +0200 Subject: [PATCH 28/38] w --- compiler/rustc_infer/src/infer/relate/higher_ranked.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index ed28dfb9ce913..59f5a99e0dff8 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -27,8 +27,6 @@ impl<'tcx> InferCtxt<'tcx> { /// `fn enter_forall` should be preferred over this method. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - /// - /// This is expected to be used in the old solver only so no ambiguous aliases allowed. #[instrument(level = "debug", skip(self), ret)] pub fn enter_forall_and_leak_universe( &self, From 8ad4d277b5f468709a866d69f2f054e1c24283c4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:14:17 +0200 Subject: [PATCH 29/38] w --- .../src/infer/relate/type_relating.rs | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 9660f457b7fc1..009424efcefe7 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -299,15 +299,23 @@ 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 a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); - self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) + infcx.enter_forall_old_solver(b, |b| { + let a = infcx.instantiate_binder_with_fresh_vars_old_solver( + span, + HigherRankedType, + a, + ); + self.relate(a, b) })?; } ty::Contravariant => { - infcx.enter_forall(a, |a| { - let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b); - self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) + infcx.enter_forall_old_solver(a, |a| { + let b = infcx.instantiate_binder_with_fresh_vars_old_solver( + span, + HigherRankedType, + b, + ); + self.relate(a, b) })?; } @@ -322,15 +330,23 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`. // Check if `exists<..> A == for<..> B` ty::Invariant => { - infcx.enter_forall(b, |b| { - let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a); - self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) + infcx.enter_forall_old_solver(b, |b| { + let a = infcx.instantiate_binder_with_fresh_vars_old_solver( + span, + HigherRankedType, + a, + ); + 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); - self.relate(a.no_ambiguous_aliases(), b.no_ambiguous_aliases()) + infcx.enter_forall_old_solver(a, |a| { + let b = infcx.instantiate_binder_with_fresh_vars_old_solver( + span, + HigherRankedType, + b, + ); + self.relate(a, b) })?; } ty::Bivariant => { From 1f33cf67609684683b8508e3c3fede1cafb6de13 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:15:22 +0200 Subject: [PATCH 30/38] w --- compiler/rustc_infer/src/infer/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0c0a4a1ac7cf2..ad23cfdddddc9 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1384,9 +1384,6 @@ impl<'tcx> InferCtxt<'tcx> { /// 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. - /// - /// If you're in the old solver or your binder doesn't have `Ambiguous` aliases, use - /// `instantiate_binder_with_fresh_vars_no_ambiguous_aliases` instead. pub fn instantiate_unnormalized_binder_with_fresh_vars( &self, span: Span, From d5706384d73064f9d376cd7c271dd316a7ba77e7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:22:08 +0200 Subject: [PATCH 31/38] cool stuff --- .../src/solve/assembly/mod.rs | 2 +- .../src/solve/assembly/structural_traits.rs | 21 ++++++++++--------- ...-in-higher-ranked-fn-signature.next.stderr | 6 +++--- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 9546a7612a92f..c7b621f8b7b72 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -111,7 +111,7 @@ where goal.param_env, trait_ref, bounds, - ) { + )? { Ok(requirements) => { ecx.add_goals(GoalSource::ImplWhereBound, requirements); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) 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 14e1ca5618a06..2e6015cc761a5 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 @@ -5,8 +5,8 @@ use derive_where::derive_where; use rustc_type_ir::data_structures::HashMap; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::{SolverProjectionLangItem, SolverTraitLangItem}; -use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::solve::inspect::ProbeKind; +use rustc_type_ir::solve::{NoSolutionOrRerunNonErased, SizedTraitKind}; use rustc_type_ir::{ self as ty, Binder, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable, TypeSuperFoldable, Unnormalized, Upcast as _, elaborate, @@ -879,14 +879,13 @@ pub(in crate::solve) fn predicates_for_object_candidate( param_env: I::ParamEnv, trait_ref: Binder>, object_bounds: I::BoundExistentialPredicates, -) -> Result>, Ambiguous> +) -> Result>, Ambiguous>, NoSolutionOrRerunNonErased> where D: SolverDelegate, I: Interner, { let cx = ecx.cx(); - let trait_ref = - ecx.instantiate_binder_with_infer(param_env, trait_ref).map_err(|_| Ambiguous)?; + let trait_ref = ecx.instantiate_binder_with_infer(param_env, trait_ref)?; 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 @@ -942,12 +941,14 @@ where nested: vec![], }; - let requirements = requirements.try_fold_with(&mut folder)?; - Ok(folder - .nested - .into_iter() - .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause))) - .collect()) + let requirements = requirements.try_fold_with(&mut folder).map(|requirements| { + folder + .nested + .into_iter() + .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause))) + .collect() + }); + Ok(requirements) } struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate> { diff --git a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr index 31d74d1c022a1..26e682dfb7a7c 100644 --- a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr +++ b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` - --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50 +error[E0284]: type annotations needed: cannot normalize `<_ as Trait<'a>>::Assoc` + --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:12 | LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::(); - | ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `<_ as Trait<'a>>::Assoc` error: aborting due to 1 previous error From 31fba6b22c3998387365bfeaaf1d508969c1867f Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:28:04 +0200 Subject: [PATCH 32/38] w --- .../src/solve/assembly/mod.rs | 6 +++-- .../src/solve/assembly/structural_traits.rs | 23 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index c7b621f8b7b72..ec495d15b15aa 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -23,6 +23,7 @@ use tracing::{debug, instrument}; use super::trait_goals::TraitGoalProvenVia; use super::{has_only_region_constraints, inspect}; use crate::delegate::SolverDelegate; +use crate::solve::assembly::structural_traits::Ambiguous; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, @@ -111,14 +112,15 @@ where goal.param_env, trait_ref, bounds, - )? { + ) { Ok(requirements) => { ecx.add_goals(GoalSource::ImplWhereBound, requirements); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - Err(_) => { + Err(Ok(Ambiguous)) => { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } + Err(Err(err)) => return Err(err), } }) } 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 2e6015cc761a5..467ed9e2a2355 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,13 +879,14 @@ pub(in crate::solve) fn predicates_for_object_candidate( param_env: I::ParamEnv, trait_ref: Binder>, object_bounds: I::BoundExistentialPredicates, -) -> Result>, Ambiguous>, NoSolutionOrRerunNonErased> +) -> Result>, Result> where D: SolverDelegate, I: Interner, { let cx = ecx.cx(); - let trait_ref = ecx.instantiate_binder_with_infer(param_env, trait_ref)?; + let trait_ref = + ecx.instantiate_binder_with_infer(param_env, trait_ref).map_err(|err| Err(err))?; 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 @@ -941,14 +942,13 @@ where nested: vec![], }; - let requirements = requirements.try_fold_with(&mut folder).map(|requirements| { + requirements.try_fold_with(&mut folder).map(|requirements| { folder .nested .into_iter() .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause))) .collect() - }); - Ok(requirements) + }) } struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate> { @@ -989,7 +989,7 @@ where fn try_eagerly_replace_alias( &mut self, alias_term: ty::AliasTerm, - ) -> Result, Ambiguous> { + ) -> Result, Result> { if alias_term.self_ty() != self.self_ty { return Ok(None); } @@ -1013,13 +1013,13 @@ where // If there's more than one projection that we can unify here, then we // need to stall until inference constrains things so that there's only // one choice. - return Err(Ambiguous); + return Err(Ok(Ambiguous)); } let replacement = self .ecx .instantiate_binder_with_infer(self.param_env, *replacement) - .map_err(|_| Ambiguous)?; + .map_err(|e| Err(e))?; self.nested.extend( self.ecx .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term) @@ -1038,13 +1038,16 @@ where D: SolverDelegate, I: Interner, { - type Error = Ambiguous; + type Error = Result; fn cx(&self) -> I { self.ecx.cx() } - fn try_fold_ty(&mut self, ty: I::Ty) -> Result { + fn try_fold_ty( + &mut self, + ty: I::Ty, + ) -> Result> { if let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind() && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { From 4f21dade57c6d446434ebcece933cfbfa2117a6c Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:30:02 +0200 Subject: [PATCH 33/38] w --- compiler/rustc_trait_selection/src/traits/coherence.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 1553a534b38c8..06852149e88ca 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -748,10 +748,12 @@ 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 ocx = ObligationCtxt::new(infcx); - let predicate_kind = - ocx.renormalize_ambiguous_aliases(&ObligationCause::dummy(), param_env, predicate_kind); + let predicate_kind = ocx.enter_forall_and_leak_universe( + &ObligationCause::dummy(), + param_env, + predicate.kind(), + ); let trait_ref = match predicate_kind { ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref, ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) From 0e87d5d4135467425e3fded322c3baed878862e7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:31:13 +0200 Subject: [PATCH 34/38] w --- .../src/error_reporting/traits/ambiguity.rs | 115 +++++++++--------- 1 file changed, 59 insertions(+), 56 deletions(-) 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 66a7cbfedc79a..6dabb32116393 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -40,65 +40,68 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( let impl_may_apply = |impl_def_id| { let ocx = ObligationCtxt::new(infcx); - infcx.enter_forall(obligation.predicate, |placeholder_obligation| { - let placeholder_obligation = ocx.renormalize_ambiguous_aliases( - &ObligationCause::dummy(), - param_env, - placeholder_obligation, - ); - let obligation_trait_ref = ocx.normalize( - &ObligationCause::dummy(), - param_env, - Unnormalized::new_wip(placeholder_obligation.trait_ref), - ); - - let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); - let impl_trait_ref = - tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(); - let impl_trait_ref = ocx.normalize( - &ObligationCause::dummy(), - param_env, - Unnormalized::new_wip(impl_trait_ref), - ); - - if let Err(_) = - ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) - { - return false; - } + ocx.enter_forall( + &ObligationCause::dummy(), + param_env, + obligation.predicate, + |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + Unnormalized::new_wip(placeholder_obligation.trait_ref), + ); - let impl_trait_header = tcx.impl_trait_header(impl_def_id); - let impl_polarity = impl_trait_header.polarity; + let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = + tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(); + let impl_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + Unnormalized::new_wip(impl_trait_ref), + ); - match (impl_polarity, predicate_polarity) { - (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive) - | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {} - _ => return false, - } + if let Err(_) = ocx.eq( + &ObligationCause::dummy(), + param_env, + obligation_trait_ref, + impl_trait_ref, + ) { + return false; + } - let obligations = tcx - .predicates_of(impl_def_id) - .instantiate(tcx, impl_args) - .into_iter() - .map(|(predicate, _)| { - Obligation::new( - tcx, - ObligationCause::dummy(), - param_env, - predicate.skip_norm_wip(), - ) - }) - // Kinda hacky, but let's just throw away obligations that overflow. - // This may reduce the accuracy of this check (if the obligation guides - // inference or it actually resulted in error after others are processed) - // ... but this is diagnostics code. - .filter(|obligation| { - infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok() - }); - ocx.register_obligations(obligations); - - ocx.try_evaluate_obligations().is_empty() - }) + let impl_trait_header = tcx.impl_trait_header(impl_def_id); + let impl_polarity = impl_trait_header.polarity; + + match (impl_polarity, predicate_polarity) { + (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive) + | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {} + _ => return false, + } + + let obligations = tcx + .predicates_of(impl_def_id) + .instantiate(tcx, impl_args) + .into_iter() + .map(|(predicate, _)| { + Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + predicate.skip_norm_wip(), + ) + }) + // Kinda hacky, but let's just throw away obligations that overflow. + // This may reduce the accuracy of this check (if the obligation guides + // inference or it actually resulted in error after others are processed) + // ... but this is diagnostics code. + .filter(|obligation| { + infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok() + }); + ocx.register_obligations(obligations); + + ocx.try_evaluate_obligations().is_empty() + }, + ) }; let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| { From 2ca555ae96780031ace87f432ff7dfbc8b8fac74 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:36:26 +0200 Subject: [PATCH 35/38] w --- compiler/rustc_trait_selection/src/traits/normalize.rs | 2 +- compiler/rustc_type_ir/src/predicate.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 6037043349bea..12ad674143cf6 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -62,7 +62,7 @@ impl<'tcx> At<'_, 'tcx> { InferOk { value, obligations } } else { // We won't have ambiguous aliases in old solver so no-op. - InferOk { value: value.do_normalize(), obligations: Default::default() } + InferOk { value: value.no_ambiguous_aliases(), obligations: Default::default() } } } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index cde2fd2cdb5c1..30344af15438e 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -649,7 +649,7 @@ impl AliasTermKind { AliasTermKind::InherentTy { def_id } => def_id.into(), AliasTermKind::OpaqueTy { def_id } => def_id.into(), AliasTermKind::FreeTy { def_id } => def_id.into(), - AliasTermKind::AmbiguousTy => todo!("this method is expected to be removed"), + AliasTermKind::AmbiguousTy => unreachable!("this method is expected to be removed"), AliasTermKind::UnevaluatedConst { def_id } => def_id.into(), AliasTermKind::ProjectionConst { def_id } => def_id.into(), AliasTermKind::FreeConst { def_id } => def_id.into(), diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 1f6dee6b631c5..0550571375e6f 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -94,7 +94,7 @@ impl AliasTyKind { AliasTyKind::Inherent { def_id } => def_id.into(), AliasTyKind::Opaque { def_id } => def_id.into(), AliasTyKind::Free { def_id } => def_id.into(), - AliasTyKind::Ambiguous => todo!("this method is expected to be removed"), + AliasTyKind::Ambiguous => unreachable!("this method is expected to be removed"), } } } From 2716b240f08210b802ccd5d45ea33f7e462119cc Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:53:07 +0200 Subject: [PATCH 36/38] flags --- compiler/rustc_type_ir/src/flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 5d384dd802aaf..8a6f840cbc641 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -96,7 +96,7 @@ bitflags::bitflags! { | TypeFlags::HAS_AMBIGUOUS_ALIAS.bits(); /// Is a type or const error reachable? - const HAS_NON_REGION_ERROR = 1 << 16; + const HAS_NON_REGION_ERROR = 1 << 16; /// Is a region error reachable? const HAS_RE_ERROR = 1 << 17; /// Is an error type/lifetime/const reachable? From 00a714845ba111642d084fe69ff052f94bd2fe79 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 14 May 2026 23:53:25 +0200 Subject: [PATCH 37/38] fix adt_const_params normalization --- compiler/rustc_middle/src/ty/consts.rs | 4 ++++ .../src/solve/eval_ctxt/mod.rs | 16 ++++++++++++++-- compiler/rustc_type_ir/src/inherent.rs | 6 +++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 7421024bba0cc..a313cb0764f85 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -194,6 +194,10 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { Const::new_unevaluated(interner, uv) } + fn new_value(interner: TyCtxt<'tcx>, value: ty::Value<'tcx>) -> Self { + Const::new_value(interner, value.valtree, value.ty) + } + fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self { Const::new_expr(interner, expr) } 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 896d5e66973da..e5725cfbf7457 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 @@ -1470,12 +1470,24 @@ where &mut self, param_env: I::ParamEnv, uv: ty::UnevaluatedConst, - ) -> Result, RerunNonErased> { + ) -> Result, NoSolutionOrRerunNonErased> { if self.typing_mode().is_erased_not_coherence() { self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)?; } - Ok(self.delegate.evaluate_const(param_env, uv)) + if let Some(ct) = self.delegate.evaluate_const(param_env, uv) { + Ok(Some(match ct.kind() { + // FIXME(adt_const_params): `evaluate_const` currently does not normalize the type + // of const values. + ty::ConstKind::Value(value) => Const::new_value( + self.cx(), + self.normalize(param_env, ty::Unnormalized::new_wip(value))?, + ), + _ => ct, + })) + } else { + Ok(None) + } } pub(super) fn evaluate_const_and_instantiate_normalizes_to_term( diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 8859ab7c037b0..b33b80900a8b4 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -278,6 +278,8 @@ pub trait Const>: fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst) -> Self; + fn new_value(interner: I, value: I::ValueConst) -> Self; + fn new_expr(interner: I, expr: I::ExprConst) -> Self; fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self; @@ -296,7 +298,9 @@ pub trait Const>: } #[rust_analyzer::prefer_underscore_import] -pub trait ValueConst>: Copy + Debug + Hash + Eq { +pub trait ValueConst>: + TypeFoldable + Copy + Debug + Hash + Eq +{ fn ty(self) -> I::Ty; fn valtree(self) -> I::ValTree; } From bb74aede52e37e6243ce141e96655332a870a53a Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 15 May 2026 01:54:59 +0200 Subject: [PATCH 38/38] coolio --- .../src/diagnostics/region_errors.rs | 7 +++- .../src/diagnostics/region_name.rs | 5 ++- compiler/rustc_borrowck/src/type_check/mod.rs | 1 + .../rustc_borrowck/src/universal_regions.rs | 2 +- .../src/check/compare_eii.rs | 5 ++- .../src/check/compare_impl_item.rs | 20 +++++----- .../src/check/compare_impl_item/refine.rs | 20 +++++----- compiler/rustc_hir_analysis/src/check/mod.rs | 5 ++- .../rustc_hir_analysis/src/check/wfcheck.rs | 22 +++++----- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/hir_ty_lowering/bounds.rs | 4 +- .../src/hir_ty_lowering/mod.rs | 13 +++--- compiler/rustc_hir_typeck/src/closure.rs | 37 ++++++++++------- compiler/rustc_hir_typeck/src/lib.rs | 16 ++++++-- .../rustc_lint/src/impl_trait_overcaptures.rs | 4 +- compiler/rustc_middle/src/ty/fold.rs | 40 ++++++++++++++----- compiler/rustc_mir_build/src/builder/mod.rs | 27 ++++++++----- .../rustc_mir_build/src/check_tail_calls.rs | 17 +++++--- .../src/check_call_recursion.rs | 9 ++++- compiler/rustc_mir_transform/src/shim.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 10 +++-- .../infer/nice_region_error/util.rs | 4 +- .../src/error_reporting/traits/suggestions.rs | 10 +++-- .../src/traits/dyn_compatibility.rs | 9 ++++- compiler/rustc_ty_utils/src/implied_bounds.rs | 10 +++-- compiler/rustc_type_ir/src/unnormalized.rs | 4 ++ 26 files changed, 197 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index bac3661ec51ad..e38266aa8186c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1082,7 +1082,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let typeck_results = tcx.typeck(self.mir_def_id()); // We don't use `ty.peel_refs()` to get the number of `*`s needed to get the root type. - let liberated_sig = tcx.liberate_late_bound_regions(closure_def_id.to_def_id(), args.sig()); + let liberated_sig = tcx + .liberate_late_bound_regions( + closure_def_id.to_def_id(), + ty::Unnormalized::new_wip(args.sig()), + ) + .skip_norm_wip(); let mut peeled_ty = liberated_sig.output(); let mut count = 0; while let ty::Ref(_, ref_ty, _) = *peeled_ty.kind() { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 963f902b71fcb..e12ceb69f3901 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -418,8 +418,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // Get the parent fn's signature with liberated late-bound regions, // so we have `ReLateParam` instead of `ReBound`. - let parent_fn_sig = tcx.fn_sig(parent_def_id).instantiate_identity().skip_norm_wip(); - let liberated_sig = tcx.liberate_late_bound_regions(parent_def_id, parent_fn_sig); + let parent_fn_sig = tcx.fn_sig(parent_def_id).instantiate_identity(); + let liberated_sig = + tcx.liberate_late_bound_regions(parent_def_id, parent_fn_sig).skip_norm_wip(); let parent_param_ty = *liberated_sig.inputs().get(param_index)?; // Get the upvar's NLL type (with ReVar regions from renumbering). diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 13983f349d6a5..b6a9322db96f2 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -811,6 +811,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { region_ctxt_fn, ) }); + let unnormalized_sig = unnormalized_sig.no_ambiguous_aliases(); debug!(?unnormalized_sig); // IMPORTANT: We have to prove well formed for the function signature before // we normalize it, as otherwise types like `<&'a &'b () as Trait>::Assoc` diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 804d2757cf998..d2a2e124eb9eb 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -892,7 +892,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind); ty::Region::new_var(self.tcx, indices.to_region_vid(liberated_region)) }); - value + value.no_ambiguous_aliases() } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index 4f5cc77eaf94a..8e916991e2c25 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -68,8 +68,9 @@ pub(crate) fn compare_eii_function_types<'tcx>( let mut wf_tys = FxIndexSet::default(); let norm_cause = ObligationCause::misc(external_impl_span, external_impl); - let declaration_sig = tcx.fn_sig(foreign_item).instantiate_identity().skip_norm_wip(); - let declaration_sig = tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig); + let declaration_sig = tcx.fn_sig(foreign_item).instantiate_identity(); + let declaration_sig = + tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig).skip_norm_wip(); debug!(?declaration_sig); // We need to check wf of the unnormalized sig. 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 a8d60c97f1ca5..b221e2bc7c5b3 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -338,8 +338,8 @@ fn compare_method_predicate_entailment<'tcx>( debug!(?impl_sig); - let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args).skip_norm_wip(); - let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig); + let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args); + let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig).skip_norm_wip(); // Next, add all inputs and output as well-formed tys. Importantly, // we have to do this before normalization, since the normalized ty may @@ -552,8 +552,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let unnormalized_trait_sig = tcx .liberate_late_bound_regions( impl_m.def_id, - tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args).skip_norm_wip(), + tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args), ) + .skip_norm_wip() .fold_with(&mut collector); let trait_sig = @@ -1257,12 +1258,12 @@ fn check_region_late_boundedness<'tcx>( .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id)); let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id); - let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args).skip_norm_wip(); - let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig); + let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args); + let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig).skip_norm_wip(); let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id); - let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args).skip_norm_wip(); - let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig); + let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args); + let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig).skip_norm_wip(); let ocx = ObligationCtxt::new(&infcx); @@ -1513,11 +1514,12 @@ fn compare_self_type<'tcx>( } ty::AssocContainer::Trait => tcx.types.self_param, }; - let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip().input(0); + let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().map(|sig| sig.input(0)); let (infcx, param_env) = tcx .infer_ctxt() .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id)); - let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); + let self_arg_ty = + tcx.liberate_late_bound_regions(method.def_id, self_arg_ty).skip_norm_wip(); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); get_self_string(self_arg_ty, can_eq_self) }; diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index cdda54f7eb943..c7ca008b43d52 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -44,23 +44,23 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( let impl_def_id = impl_m.container_id(tcx); let impl_m_args = ty::GenericArgs::identity_for_item(tcx, impl_m.def_id); let trait_m_to_impl_m_args = impl_m_args.rebase_onto(tcx, impl_def_id, impl_trait_ref.args); - let bound_trait_m_sig = - tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_to_impl_m_args).skip_norm_wip(); - let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, bound_trait_m_sig); + let bound_trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_to_impl_m_args); + let trait_m_sig = + tcx.liberate_late_bound_regions(impl_m.def_id, bound_trait_m_sig).skip_norm_wip(); // replace the self type of the trait ref with `Self` so that diagnostics render better. - let trait_m_sig_with_self_for_diag = tcx.liberate_late_bound_regions( - impl_m.def_id, - tcx.fn_sig(trait_m.def_id) - .instantiate( + let trait_m_sig_with_self_for_diag = tcx + .liberate_late_bound_regions( + impl_m.def_id, + tcx.fn_sig(trait_m.def_id).instantiate( tcx, tcx.mk_args_from_iter( [tcx.types.self_param.into()] .into_iter() .chain(trait_m_to_impl_m_args.iter().skip(1)), ), - ) - .skip_norm_wip(), - ); + ), + ) + .skip_norm_wip(); let Ok(hidden_tys) = tcx.collect_return_position_impl_trait_in_trait_tys(impl_m.def_id) else { // Error already emitted, no need to delay another. diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 30d3e109a0080..e56cdfed6d646 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -538,8 +538,9 @@ fn suggestion_signature<'tcx>( tcx, tcx.liberate_late_bound_regions( assoc.def_id, - tcx.fn_sig(assoc.def_id).instantiate(tcx, args).skip_norm_wip(), - ), + tcx.fn_sig(assoc.def_id).instantiate(tcx, args), + ) + .skip_norm_wip(), assoc.ident(tcx), tcx.predicates_of(assoc.def_id) .instantiate_own(tcx, args) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index dd506dd2b7fc9..8b732ed6e78dc 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -425,10 +425,12 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { // For methods, we check the function signature's return type for any GATs // to constrain. In the `into_iter` case, we see that the return type // `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from. - let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions( - item_def_id.to_def_id(), - tcx.fn_sig(item_def_id).instantiate_identity().skip_norm_wip(), - ); + let sig = tcx + .liberate_late_bound_regions( + item_def_id.to_def_id(), + tcx.fn_sig(item_def_id).instantiate_identity(), + ) + .skip_norm_wip(); gather_gat_bounds( tcx, param_env, @@ -1014,7 +1016,7 @@ pub(crate) fn check_associated_item( Ok(()) } ty::AssocKind::Fn { .. } => { - let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); + let sig = tcx.fn_sig(def_id).instantiate_identity(); let hir_sig = tcx.hir_node_by_def_id(def_id).fn_sig().expect("bad signature for method"); check_fn_or_method(wfcx, sig, hir_sig.decl, def_id); @@ -1233,7 +1235,7 @@ fn check_item_fn( enter_wf_checking_ctxt(tcx, def_id, |wfcx| { check_eiis_fn(tcx, def_id); - let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); + let sig = tcx.fn_sig(def_id).instantiate_identity(); check_fn_or_method(wfcx, sig, decl, def_id); Ok(()) }) @@ -1701,12 +1703,12 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: #[instrument(level = "debug", skip(wfcx, hir_decl))] fn check_fn_or_method<'tcx>( wfcx: &WfCheckingCtxt<'_, 'tcx>, - sig: ty::PolyFnSig<'tcx>, + sig: ty::Unnormalized<'tcx, ty::PolyFnSig<'tcx>>, hir_decl: &hir::FnDecl<'_>, def_id: LocalDefId, ) { let tcx = wfcx.tcx(); - let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); + let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig).skip_norm_wip(); // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` @@ -1812,8 +1814,8 @@ fn check_method_receiver<'tcx>( let span = fn_sig.decl.inputs[0].span; let loc = Some(WellFormedLoc::Param { function: method.def_id.expect_local(), param_idx: 0 }); - let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip(); - let sig = tcx.liberate_late_bound_regions(method.def_id, sig); + let sig = tcx.fn_sig(method.def_id).instantiate_identity(); + let sig = tcx.liberate_late_bound_regions(method.def_id, sig).skip_norm_wip(); let sig = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(sig)); debug!("check_method_receiver: sig={:?}", sig); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8c182f9165e13..3a8b9892edad9 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -471,7 +471,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { name: Symbol::intern(<_name), }) } - ), + ).no_ambiguous_aliases(), ), }); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 6e2c7a82af3b1..f0c00c92e0917 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -840,7 +840,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit { span: path_span, - ty: tcx.liberate_late_bound_regions(item_def_id, output), + ty: tcx + .liberate_late_bound_regions(item_def_id, ty::Unnormalized::new_wip(output)) + .skip_norm_wip(), fn_span: tcx.hir_span_if_local(item_def_id), note: (), })); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5a86e8186a5aa..c81852d40e47c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3687,16 +3687,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_ref.def_id, )?; + let fn_sig = tcx.fn_sig(assoc.def_id).instantiate( + tcx, + trait_ref.args.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)), + ); let fn_sig = tcx - .fn_sig(assoc.def_id) - .instantiate( - tcx, - trait_ref - .args - .extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)), - ) + .liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig) .skip_norm_wip(); - let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig); Some(if let Some(arg_idx) = arg_idx { *fn_sig.inputs().get(arg_idx)? diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 6c58002825925..7f510b0f6fdf8 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -250,18 +250,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // coroutine. To do so, we use the `CoroutineClosureSignature` to compute // the coroutine type, filling in the tupled_upvars_ty and kind_ty with infer // vars which will get constrained during upvar analysis. - let coroutine_output_ty = tcx.liberate_late_bound_regions( - expr_def_id.to_def_id(), - closure_args.coroutine_closure_sig().map_bound(|sig| { - sig.to_coroutine( - tcx, - parent_args, - coroutine_kind_ty, - tcx.coroutine_for_closure(expr_def_id), - coroutine_upvars_ty, - ) - }), - ); + let coroutine_output_ty = tcx + .liberate_late_bound_regions( + expr_def_id.to_def_id(), + ty::Unnormalized::new_wip(closure_args.coroutine_closure_sig().map_bound( + |sig| { + sig.to_coroutine( + tcx, + parent_args, + coroutine_kind_ty, + tcx.coroutine_for_closure(expr_def_id), + coroutine_upvars_ty, + ) + }, + )), + ) + .skip_norm_wip(); liberated_sig = tcx.mk_fn_sig( liberated_sig.inputs().iter().copied(), coroutine_output_ty, @@ -1118,8 +1122,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_def_id: LocalDefId, bound_sig: ty::PolyFnSig<'tcx>, ) -> ClosureSignatures<'tcx> { - let liberated_sig = - self.tcx().liberate_late_bound_regions(expr_def_id.to_def_id(), bound_sig); + let liberated_sig = self + .tcx() + .liberate_late_bound_regions( + expr_def_id.to_def_id(), + ty::Unnormalized::new_wip(bound_sig), + ) + .skip_norm_wip(); let liberated_sig = self.normalize(self.tcx.def_span(expr_def_id), Unnormalized::new_wip(liberated_sig)); ClosureSignatures { bound_sig, liberated_sig } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 55a01ddfba779..856da8221f92f 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -142,18 +142,26 @@ fn typeck_with_inspect<'tcx>( // type that has an infer in it, lower the type directly so that it'll // be correctly filled with infer. We'll use this inference to provide // a suggestion later on. - fcx.lowerer().lower_fn_ty(id, header.safety(), header.abi, decl, None, None) + ty::Unnormalized::new_wip(fcx.lowerer().lower_fn_ty( + id, + header.safety(), + header.abi, + decl, + None, + None, + )) } else { - tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip() + tcx.fn_sig(def_id).instantiate_identity() }; - check_abi(tcx, id, span, fn_sig.abi()); + check_abi(tcx, id, span, fn_sig.skip_norm_wip().abi()); check_custom_abi(tcx, def_id, fn_sig.skip_binder(), *fn_sig_span); loops::check(tcx, def_id, body); // Compute the function signature from point of view of inside the fn. - let mut fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); + let mut fn_sig = + tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig).skip_norm_wip(); // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 65dfa8b93de78..035cf09fda242 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -142,7 +142,7 @@ enum ParamKind { } fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { - let sig = tcx.fn_sig(parent_def_id).instantiate_identity().skip_norm_wip(); + let sig = tcx.fn_sig(parent_def_id).instantiate_identity(); let mut in_scope_parameters = FxIndexMap::default(); // Populate the in_scope_parameters list first with all of the generics in scope @@ -163,7 +163,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { in_scope_parameters.insert(def_id, ParamKind::Free(def_id)); } - let sig = tcx.liberate_late_bound_regions(parent_def_id.to_def_id(), sig); + let sig = tcx.liberate_late_bound_regions(parent_def_id.to_def_id(), sig).skip_norm_wip(); // Then visit the signature to walk through all the binders (incl. the late-bound // vars on the function itself, which we need to count too). diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 606d2438531e0..403e3f45d8ed3 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -207,7 +207,7 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, mut fld_r: F, - ) -> (T, FxIndexMap, ty::Region<'tcx>>) + ) -> (ty::UnnormalizedAmbiguous<'tcx, T>, FxIndexMap, ty::Region<'tcx>>) where F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>, T: TypeFoldable>, @@ -223,14 +223,14 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, mut replace_regions: F, - ) -> T + ) -> ty::UnnormalizedAmbiguous<'tcx, T> where F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>, T: TypeFoldable>, { let value = value.skip_binder(); if !value.has_escaping_bound_vars() { - value + ty::UnnormalizedAmbiguous::dummy(value) } else { let delegate = FnMutDelegate { regions: &mut replace_regions, @@ -238,7 +238,7 @@ impl<'tcx> TyCtxt<'tcx> { consts: &mut |b| bug!("unexpected bound ct in binder: {b:?}"), }; let mut replacer = BoundVarReplacer::new(self, delegate); - value.fold_with(&mut replacer) + ty::UnnormalizedAmbiguous::new(value.fold_with(&mut replacer)) } } @@ -270,13 +270,11 @@ impl<'tcx> TyCtxt<'tcx> { ty::UnnormalizedAmbiguous::new(value) } - /// Replaces any late-bound regions bound in `value` with - /// free variants attached to `all_outlive_scope`. - pub fn liberate_late_bound_regions( + pub fn liberate_late_bound_regions_normalized( self, all_outlive_scope: DefId, value: ty::Binder<'tcx, T>, - ) -> T + ) -> ty::UnnormalizedAmbiguous<'tcx, T> where T: TypeFoldable>, { @@ -286,6 +284,25 @@ impl<'tcx> TyCtxt<'tcx> { }) } + /// Replaces any late-bound regions bound in `value` with + /// free variants attached to `all_outlive_scope`. + pub fn liberate_late_bound_regions( + self, + all_outlive_scope: DefId, + value: ty::Unnormalized<'tcx, ty::Binder<'tcx, T>>, + ) -> ty::Unnormalized<'tcx, T> + where + T: TypeFoldable>, + { + value.map(|value| { + self.instantiate_bound_regions_uncached(value, |br| { + let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind); + ty::Region::new_late_param(self, all_outlive_scope, kind) + }) + .no_ambiguous_aliases() + }) + } + pub fn shift_bound_var_indices(self, bound_vars: usize, value: T) -> T where T: TypeFoldable>, @@ -315,13 +332,14 @@ impl<'tcx> TyCtxt<'tcx> { ) } - /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also - /// method lookup and a few other places where precise region relationships are not required. + /// Replaces any late-bound regions bound in `value` with `'erased`. This should + /// generally only be used in codegen and does not expect any ambiguous aliases + /// in `value``. pub fn instantiate_bound_regions_with_erased(self, value: Binder<'tcx, T>) -> T where T: TypeFoldable>, { - self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0 + self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0.no_ambiguous_aliases() } /// Anonymize all bound variables in `value`, this is mostly used to improve caching. diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index e9f9da9c8cd91..477b623c5dca9 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -626,10 +626,12 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - (vec![], tcx.type_of(def_id).instantiate_identity().skip_norm_wip(), None) } DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => { - let sig = tcx.liberate_late_bound_regions( - def_id.to_def_id(), - tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(), - ); + let sig = tcx + .liberate_late_bound_regions( + def_id.to_def_id(), + tcx.fn_sig(def_id).instantiate_identity(), + ) + .skip_norm_wip(); (sig.inputs().to_vec(), sig.output(), None) } DefKind::Closure => { @@ -637,7 +639,12 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - match closure_ty.kind() { ty::Closure(_, args) => { let args = args.as_closure(); - let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig()); + let sig = tcx + .liberate_late_bound_regions( + def_id.to_def_id(), + ty::Unnormalized::new_wip(args.sig()), + ) + .skip_norm_wip(); let self_ty = match args.kind() { ty::ClosureKind::Fn => { Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty) @@ -670,10 +677,12 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - } ty::CoroutineClosure(did, args) => { let args = args.as_coroutine_closure(); - let sig = tcx.liberate_late_bound_regions( - def_id.to_def_id(), - args.coroutine_closure_sig(), - ); + let sig = tcx + .liberate_late_bound_regions( + def_id.to_def_id(), + ty::Unnormalized::dummy(args.coroutine_closure_sig()), + ) + .skip_normalization(); let self_ty = match args.kind() { ty::ClosureKind::Fn => { Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty) diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index 8052ee26df841..8a1eeda1acb15 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -152,11 +152,18 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { self.report_signature_mismatch( expr.span, - self.tcx.liberate_late_bound_regions( - CRATE_DEF_ID.to_def_id(), - caller_ty.fn_sig(self.tcx), - ), - self.tcx.liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)), + self.tcx + .liberate_late_bound_regions( + CRATE_DEF_ID.to_def_id(), + ty::Unnormalized::new_wip(caller_ty.fn_sig(self.tcx)), + ) + .skip_norm_wip(), + self.tcx + .liberate_late_bound_regions( + CRATE_DEF_ID.to_def_id(), + ty::Unnormalized::new_wip(ty.fn_sig(self.tcx)), + ) + .skip_norm_wip(), ); } diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs index b47e7bd168678..a1bcce7d3dddc 100644 --- a/compiler/rustc_mir_transform/src/check_call_recursion.rs +++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs @@ -52,8 +52,13 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion { { // It was. Now figure out for what type `Drop` is implemented and then // check for recursion. - if let ty::Ref(_, dropped_ty, _) = - tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind() + if let ty::Ref(_, dropped_ty, _) = tcx + .liberate_late_bound_regions( + def_id.to_def_id(), + ty::Unnormalized::new_wip(sig.input(0)), + ) + .skip_norm_wip() + .kind() { check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty }); } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 7f92199dec455..efe0354759b1d 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1182,7 +1182,9 @@ fn build_construct_coroutine_by_move_shim<'tcx>( sig.fn_sig_kind, ) }); - let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig); + let sig = tcx + .liberate_late_bound_regions(coroutine_closure_def_id, ty::Unnormalized::dummy(poly_sig)) + .skip_normalization(); let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else { bug!(); }; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f6765d604acb3..67e9bb39d0eea 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1580,10 +1580,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let span = tcx.def_span(def_id); let fresh_args = infcx.fresh_args_for_item(span, def_id.to_def_id()); - let sig = tcx.liberate_late_bound_regions( - def_id.to_def_id(), - tcx.fn_sig(def_id).instantiate(tcx, fresh_args).skip_norm_wip(), - ); + let sig = tcx + .liberate_late_bound_regions( + def_id.to_def_id(), + tcx.fn_sig(def_id).instantiate(tcx, fresh_args), + ) + .skip_norm_wip(); let mut cause = ObligationCause::misc(span, def_id); let sig = ocx.normalize(&cause, param_env, Unnormalized::new_wip(sig)); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 3ec97ce76ef07..689dd04526e46 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -66,9 +66,9 @@ pub fn find_param_with_region<'tcx>( let owner_id = tcx.hir_body_owner(body.id()); let fn_decl = tcx.hir_fn_decl_by_hir_id(owner_id)?; - let poly_fn_sig = tcx.fn_sig(id).instantiate_identity().skip_norm_wip(); + let poly_fn_sig = tcx.fn_sig(id).instantiate_identity(); - let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig); + let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig).skip_norm_wip(); body.params .iter() .take(if fn_sig.c_variadic() { 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 299c517bb5af0..ffd8e8dd88525 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -713,9 +713,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - // We `instantiate_bound_regions_with_erased` here because `make_subregion` does not handle - // `ReBound`, and we don't particularly care about the regions. - let real_ty = self.tcx.instantiate_bound_regions_with_erased(real_trait_pred.self_ty()); + let ocx = ObligationCtxt::new(self); + let real_ty = ocx.instantiate_binder_with_fresh_vars( + &ObligationCause::dummy(), + BoundRegionConversionTime::HigherRankedType, + obligation.param_env, + real_trait_pred.self_ty(), + ); if !self.can_eq(obligation.param_env, real_ty, arg_ty) { return false; } diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index b81d466f9106a..dd73551149283 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -416,6 +416,8 @@ fn virtual_call_violations_for_method<'tcx>( trait_def_id: DefId, method: ty::AssocItem, ) -> Vec { + // FIXME(#155345): Pretty much all of this function intentionally uses + // unnormalized types and should track this properly. let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip(); // The method's first parameter must be named `self` @@ -488,7 +490,9 @@ fn virtual_call_violations_for_method<'tcx>( errors.push(MethodViolation::Generic); } - let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0)); + let receiver_ty = tcx + .liberate_late_bound_regions(method.def_id, ty::Unnormalized::new_wip(sig.input(0))) + .skip_norm_wip(); // `self: Self` can't be dispatched on. // However, this is considered dyn compatible. We allow it as a special case here. @@ -924,7 +928,8 @@ fn contains_illegal_impl_trait_in_trait<'tcx>( fn_def_id: DefId, ty: ty::Binder<'tcx, Ty<'tcx>>, ) -> Option { - let ty = tcx.liberate_late_bound_regions(fn_def_id, ty); + let ty = + tcx.liberate_late_bound_regions(fn_def_id, ty::Unnormalized::new_wip(ty)).skip_norm_wip(); if tcx.asyncness(fn_def_id).is_async() { // Rendering the error as a separate `async-specific` message is better. diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 659229a58d539..e78037abf493e 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -24,16 +24,18 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' let kind = tcx.def_kind(def_id); match kind { DefKind::Fn => { - let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); - let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); + let sig = tcx.fn_sig(def_id).instantiate_identity(); + let liberated_sig = + tcx.liberate_late_bound_regions(def_id.to_def_id(), sig).skip_norm_wip(); tcx.arena.alloc_from_iter(itertools::zip_eq( liberated_sig.inputs_and_output, fn_sig_spans(tcx, def_id), )) } DefKind::AssocFn => { - let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); - let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); + let sig = tcx.fn_sig(def_id).instantiate_identity(); + let liberated_sig = + tcx.liberate_late_bound_regions(def_id.to_def_id(), sig).skip_norm_wip(); let mut assumed_wf_types: Vec<_> = tcx.assumed_wf_types(tcx.local_parent(def_id)).into(); assumed_wf_types.extend(itertools::zip_eq( diff --git a/compiler/rustc_type_ir/src/unnormalized.rs b/compiler/rustc_type_ir/src/unnormalized.rs index 752c10d9cf5de..0949bc24817f3 100644 --- a/compiler/rustc_type_ir/src/unnormalized.rs +++ b/compiler/rustc_type_ir/src/unnormalized.rs @@ -97,6 +97,10 @@ impl Unnormalized> { pub fn skip_binder(self) -> T { self.value.skip_binder() } + + pub fn bound_vars(&self) -> I::BoundVarKinds { + self.value.bound_vars() + } } impl Unnormalized {