Add a normalize_ty callback to try_evaluate_const
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 071c62d..98d0cd3 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -326,7 +326,9 @@ fn evaluate_const( ) -> Option<ty::Const<'tcx>> { let ct = ty::Const::new_alias(self.tcx, ty::IsRigid::No, alias_const); - match crate::traits::try_evaluate_const(&self.0, ct, param_env) { + match crate::traits::try_evaluate_const(&self.0, ct, param_env, |ty| { + Ok::<_, !>(ty.skip_norm_wip()) + }) { Ok(ct) => Some(ct), Err(EvaluateConstErr::EvaluationFailure(e)) => Some(ty::Const::new_error(self.tcx, e)), Err(
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c885406..798bca8 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -853,8 +853,12 @@ fn evaluate_nested_obligations( ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: ty::Const<'tcx>| { if let ty::ConstKind::Alias(_, alias_const) = c.kind() { - let ct = - super::try_evaluate_const(selcx.infcx, c, obligation.param_env); + let ct = super::try_evaluate_const( + selcx.infcx, + c, + obligation.param_env, + |ty| Ok::<_, !>(ty.skip_norm_wip()), + ); if let Err(EvaluateConstErr::InvalidConstParamTy(_)) = ct { let span = alias_const.kind.def_span(self.tcx);
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 74413d4..2a1cb4c 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -67,7 +67,9 @@ pub fn is_const_evaluatable<'tcx>( tcx.dcx().span_bug(span, "evaluating `ConstKind::Expr` is not currently supported"); } ty::ConstKind::Alias(_, _) => { - match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env) { + match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env, |ty| { + Ok::<_, !>(ty.skip_norm_wip()) + }) { Err(EvaluateConstErr::HasGenericsOrInfers) => { Err(NotConstEvaluatable::Error(infcx.dcx().span_delayed_bug( span, @@ -98,7 +100,9 @@ pub fn is_const_evaluatable<'tcx>( _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), }; - match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env) { + match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env, |ty| { + Ok::<_, !>(ty.skip_norm_wip()) + }) { // If we're evaluating a generic foreign constant, under a nightly compiler while // the current crate does not enable `feature(generic_const_exprs)`, abort // compilation with a useful error.
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index d045205..941d80d 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -764,6 +764,7 @@ fn process_obligation( self.selcx.infcx, c, obligation.param_env, + |ty| Ok::<_, !>(ty.skip_norm_wip()), ) { Ok(val) => Ok(val), e @ Err(EvaluateConstErr::HasGenericsOrInfers) => {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index eda63e0..8b9b21b 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -572,8 +572,7 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { ty::ParamEnv::new(tcx.mk_clauses(&clauses)) } -#[derive(Debug)] -pub enum EvaluateConstErr { +pub enum EvaluateConstErr<E> { /// The constant being evaluated was either a generic parameter or inference variable, *or*, /// some alias const with either generic parameters or inference variables in its /// generic arguments. @@ -585,6 +584,18 @@ pub enum EvaluateConstErr { /// CTFE failed to evaluate the constant in some unrecoverable way (e.g. encountered a `panic!`). /// This is also used when the constant was already tainted by error. EvaluationFailure(ErrorGuaranteed), + FailedNormalization(E), +} + +impl<E> std::fmt::Debug for EvaluateConstErr<E> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::HasGenericsOrInfers => f.write_str("HasGenericsOrInfers"), + Self::InvalidConstParamTy(e) => f.debug_tuple("InvalidConstParamTy").field(e).finish(), + Self::EvaluationFailure(e) => f.debug_tuple("EvaluationFailure").field(e).finish(), + Self::FailedNormalization(_) => f.write_str("FailedNormalization(..)"), + } + } } // FIXME(BoxyUwU): Private this once we `generic_const_exprs` isn't doing its own normalization routine @@ -601,7 +612,7 @@ pub fn evaluate_const<'tcx>( ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> ty::Const<'tcx> { - match try_evaluate_const(infcx, ct, param_env) { + match try_evaluate_const(infcx, ct, param_env, |v| Ok::<_, !>(v.skip_norm_wip())) { Ok(ct) => ct, Err(EvaluateConstErr::EvaluationFailure(e) | EvaluateConstErr::InvalidConstParamTy(e)) => { ty::Const::new_error(infcx.tcx, e) @@ -618,12 +629,13 @@ pub fn evaluate_const<'tcx>( /// /// You should not call this function unless you are implementing normalization itself. Prefer to use /// `normalize_erasing_regions` or the `normalize` functions on `ObligationCtxt`/`FnCtxt`/`InferCtxt`. -#[instrument(level = "debug", skip(infcx), ret)] -pub fn try_evaluate_const<'tcx>( +#[instrument(level = "debug", skip(infcx, normalize_ty), ret)] +pub fn try_evaluate_const<'tcx, E>( infcx: &InferCtxt<'tcx>, ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, -) -> Result<ty::Const<'tcx>, EvaluateConstErr> { + normalize_ty: impl FnOnce(Unnormalized<'tcx, Ty<'tcx>>) -> Result<Ty<'tcx>, E>, +) -> Result<ty::Const<'tcx>, EvaluateConstErr<E>> { let tcx = infcx.tcx; let ct = infcx.resolve_vars_if_possible(ct); debug!(?ct); @@ -762,7 +774,9 @@ pub fn try_evaluate_const<'tcx>( let span = alias_const.kind.def_span(tcx); match tcx.const_eval_resolve_for_typeck(typing_env, erased_alias_const, span) { Ok(Ok(val)) => { - Ok(ty::Const::new_value(tcx, val, alias_const.type_of(tcx).skip_norm_wip())) + let ty = normalize_ty(alias_const.type_of(tcx)) + .map_err(EvaluateConstErr::FailedNormalization)?; + Ok(ty::Const::new_value(tcx, val, ty)) } Ok(Err(_)) => { let e = tcx.dcx().delayed_bug(
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9b4ee13..038b0ae 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -921,8 +921,12 @@ fn evaluate_predicate_recursively<'o>( let evaluate = |c: ty::Const<'tcx>| { if let ty::ConstKind::Alias(_, _) = c.kind() { - match crate::traits::try_evaluate_const(self.infcx, c, obligation.param_env) - { + match crate::traits::try_evaluate_const( + self.infcx, + c, + obligation.param_env, + |v| Ok::<_, !>(v.skip_norm_wip()), + ) { Ok(val) => Ok(val), Err(e) => Err(e), }