diff options
| author | Michael Goulet <michael@errs.io> | 2025-06-06 18:05:29 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-06-07 02:35:28 +0000 |
| commit | aa1b296dd6ff158a8fac8e33fb575b24d960ede9 (patch) | |
| tree | 2627a1777a526c25ab071e3d3bd3a79546f74134 | |
| parent | 7efd90a1a56f5f4cf5a73f40b1b84032407873a1 (diff) | |
| download | rust-aa1b296dd6ff158a8fac8e33fb575b24d960ede9.tar.gz rust-aa1b296dd6ff158a8fac8e33fb575b24d960ede9.zip | |
Unify normalization of terms in deeply normalize
4 files changed, 30 insertions, 71 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 96e03e3bea5..e9b58eb959b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -823,6 +823,13 @@ impl<'tcx> InferCtxt<'tcx> { ty::Region::new_var(self.tcx, region_var) } + pub fn next_term_var_of_kind(&self, term: ty::Term<'tcx>, span: Span) -> ty::Term<'tcx> { + match term.kind() { + ty::TermKind::Ty(_) => self.next_ty_var(span).into(), + ty::TermKind::Const(_) => self.next_const_var(span).into(), + } + } + /// Return the universe that the region `r` was created in. For /// most regions (e.g., `'static`, named regions from the user, /// etc) this is the root universe U0. For inference variables or diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 1193a9059ca..de1bd724052 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -206,10 +206,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let infcx = self.goal.infcx; match goal.predicate.kind().no_bound_vars() { Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { - let unconstrained_term = match term.kind() { - ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), - ty::TermKind::Const(_) => infcx.next_const_var(span).into(), - }; + let unconstrained_term = infcx.next_term_var_of_kind(term, span); let goal = goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index a8d32221204..8f44c26b70d 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,4 +1,3 @@ -use std::assert_matches::assert_matches; use std::fmt::Debug; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -96,66 +95,18 @@ impl<'tcx, E> NormalizationFolder<'_, 'tcx, E> where E: FromSolverError<'tcx, NextSolverError<'tcx>>, { - fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> { - assert_matches!(alias_ty.kind(), ty::Alias(..)); - - let infcx = self.at.infcx; - let tcx = infcx.tcx; - let recursion_limit = tcx.recursion_limit(); - if !recursion_limit.value_within_limit(self.depth) { - let ty::Alias(_, data) = *alias_ty.kind() else { - unreachable!(); - }; - - self.at.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(data.into()), - self.at.cause.span, - true, - |_| {}, - ); - } - - self.depth += 1; - - let new_infer_ty = infcx.next_ty_var(self.at.cause.span); - let obligation = Obligation::new( - tcx, - self.at.cause.clone(), - self.at.param_env, - ty::PredicateKind::AliasRelate( - alias_ty.into(), - new_infer_ty.into(), - ty::AliasRelationDirection::Equate, - ), - ); - - self.fulfill_cx.register_predicate_obligation(infcx, obligation); - self.select_all_and_stall_coroutine_predicates()?; - - // Alias is guaranteed to be fully structurally resolved, - // so we can super fold here. - let ty = infcx.resolve_vars_if_possible(new_infer_ty); - let result = ty.try_super_fold_with(self)?; - self.depth -= 1; - Ok(result) - } - - fn normalize_unevaluated_const( + fn normalize_alias_term( &mut self, - alias_ct: ty::Const<'tcx>, - ) -> Result<ty::Const<'tcx>, Vec<E>> { - assert_matches!(alias_ct.kind(), ty::ConstKind::Unevaluated(..)); - + alias_term: ty::Term<'tcx>, + ) -> Result<ty::Term<'tcx>, Vec<E>> { let infcx = self.at.infcx; let tcx = infcx.tcx; let recursion_limit = tcx.recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { - let ty::ConstKind::Unevaluated(uv) = alias_ct.kind() else { - unreachable!(); - }; + let term = alias_term.to_alias_term().unwrap(); self.at.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(uv.into()), + OverflowCause::DeeplyNormalize(term), self.at.cause.span, true, |_| {}, @@ -164,14 +115,14 @@ where self.depth += 1; - let new_infer_ct = infcx.next_const_var(self.at.cause.span); + let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span); let obligation = Obligation::new( tcx, self.at.cause.clone(), self.at.param_env, ty::PredicateKind::AliasRelate( - alias_ct.into(), - new_infer_ct.into(), + alias_term.into(), + infer_term.into(), ty::AliasRelationDirection::Equate, ), ); @@ -181,8 +132,13 @@ where // Alias is guaranteed to be fully structurally resolved, // so we can super fold here. - let ct = infcx.resolve_vars_if_possible(new_infer_ct); - let result = ct.try_super_fold_with(self)?; + let term = infcx.resolve_vars_if_possible(infer_term); + // super-folding the `term` will directly fold the `Ty` or `Const` so + // we have to match on the term and super-fold them manually. + let result = match term.kind() { + ty::TermKind::Ty(ty) => ty.try_super_fold_with(self)?.into(), + ty::TermKind::Const(ct) => ct.try_super_fold_with(self)?.into(), + }; self.depth -= 1; Ok(result) } @@ -242,7 +198,8 @@ where 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(|| self.normalize_alias_ty(ty))?; + let result = + ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type(); Ok(PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, @@ -252,7 +209,7 @@ where result, )) } else { - ensure_sufficient_stack(|| self.normalize_alias_ty(ty)) + Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type()) } } @@ -269,7 +226,8 @@ where if ct.has_escaping_bound_vars() { let (ct, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct); - let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct))?; + let result = + ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const(); Ok(PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, @@ -279,7 +237,7 @@ where result, )) } else { - ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct)) + Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const()) } } } diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 3f741345404..2e20ede2f50 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -39,10 +39,7 @@ impl<'tcx> At<'_, 'tcx> { return Ok(term); } - let new_infer = match term.kind() { - ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(), - ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(), - }; + let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span); // We simply emit an `alias-eq` goal here, since that will take care of // normalizing the LHS of the projection until it is a rigid projection |
