Unify normalization of terms in deeply normalize

This commit is contained in:
Michael Goulet
2025-06-06 18:05:29 +00:00
parent 7efd90a1a5
commit aa1b296dd6
4 changed files with 30 additions and 71 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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())
}
}
}

View File

@@ -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