Rollup merge of #142126 - compiler-errors:normalize-uv-via-relate, r=BoxyUwU
Treat normalizing consts like normalizing types in deeply normalize ...so that we don't end up putting a top-level normalizes-to goal in the fulfillment context, which ICEs. This basically just models the normalize-const code off of the normalize-ty code above it, which uses an alias-relate goal instead. Fixes rust-lang/rust#140571 r? lcnr
This commit is contained in:
@@ -231,10 +231,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
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
@@ -16,7 +15,6 @@ use tracing::instrument;
|
||||
use super::{FulfillmentCtxt, NextSolverError};
|
||||
use crate::error_reporting::InferCtxtErrorExt;
|
||||
use crate::error_reporting::traits::OverflowCause;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
|
||||
|
||||
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
|
||||
@@ -97,19 +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(..));
|
||||
|
||||
fn normalize_alias_term(
|
||||
&mut self,
|
||||
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::Alias(_, data) = *alias_ty.kind() else {
|
||||
unreachable!();
|
||||
};
|
||||
let term = alias_term.to_alias_term().unwrap();
|
||||
|
||||
self.at.infcx.err_ctxt().report_overflow_error(
|
||||
OverflowCause::DeeplyNormalize(data.into()),
|
||||
OverflowCause::DeeplyNormalize(term),
|
||||
self.at.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
@@ -118,14 +115,14 @@ where
|
||||
|
||||
self.depth += 1;
|
||||
|
||||
let new_infer_ty = infcx.next_ty_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_ty.into(),
|
||||
new_infer_ty.into(),
|
||||
alias_term.into(),
|
||||
infer_term.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
@@ -135,50 +132,13 @@ where
|
||||
|
||||
// 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(
|
||||
&mut self,
|
||||
uv: ty::UnevaluatedConst<'tcx>,
|
||||
) -> Result<ty::Const<'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) {
|
||||
self.at.infcx.err_ctxt().report_overflow_error(
|
||||
OverflowCause::DeeplyNormalize(uv.into()),
|
||||
self.at.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
);
|
||||
}
|
||||
|
||||
self.depth += 1;
|
||||
|
||||
let new_infer_ct = infcx.next_const_var(self.at.cause.span);
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
self.at.cause.clone(),
|
||||
self.at.param_env,
|
||||
ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() },
|
||||
);
|
||||
|
||||
let result = if infcx.predicate_may_hold(&obligation) {
|
||||
self.fulfill_cx.register_predicate_obligation(infcx, obligation);
|
||||
let errors = self.fulfill_cx.select_where_possible(infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
let ct = infcx.resolve_vars_if_possible(new_infer_ct);
|
||||
ct.try_fold_with(self)?
|
||||
} else {
|
||||
ty::Const::new_unevaluated(tcx, uv).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)
|
||||
}
|
||||
@@ -238,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,
|
||||
@@ -248,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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,15 +221,13 @@ where
|
||||
return Ok(ct);
|
||||
}
|
||||
|
||||
let uv = match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(ct) => ct,
|
||||
_ => return ct.try_super_fold_with(self),
|
||||
};
|
||||
let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) };
|
||||
|
||||
if uv.has_escaping_bound_vars() {
|
||||
let (uv, mapped_regions, mapped_types, mapped_consts) =
|
||||
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
|
||||
let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?;
|
||||
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_alias_term(ct.into()))?.expect_const();
|
||||
Ok(PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
@@ -278,7 +237,7 @@ where
|
||||
result,
|
||||
))
|
||||
} else {
|
||||
ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))
|
||||
Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user