about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs30
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs52
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs154
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs249
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs35
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs6
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs8
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs2
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_transmute/src/lib.rs11
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs12
22 files changed, 243 insertions, 351 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 9159bc36987..54f82dcc8ae 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -723,11 +723,8 @@ fn codegen_stmt<'tcx>(
                 }
                 Rvalue::Repeat(ref operand, times) => {
                     let operand = codegen_operand(fx, operand);
-                    let times = fx
-                        .monomorphize(times)
-                        .eval(fx.tcx, ParamEnv::reveal_all())
-                        .try_to_bits(fx.tcx.data_layout.pointer_size)
-                        .unwrap();
+                    let times =
+                        fx.monomorphize(times).eval_target_usize(fx.tcx, ParamEnv::reveal_all());
                     if operand.layout().size.bytes() == 0 {
                         // Do nothing for ZST's
                     } else if fx.clif_type(operand.layout().ty) == Some(types::I8) {
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index a934b0767f1..b9d4bc9ff29 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -77,31 +77,9 @@ pub(crate) fn eval_mir_constant<'tcx>(
     fx: &FunctionCx<'_, '_, 'tcx>,
     constant: &Constant<'tcx>,
 ) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
-    let constant_kind = fx.monomorphize(constant.literal);
-    let uv = match constant_kind {
-        ConstantKind::Ty(const_) => match const_.kind() {
-            ty::ConstKind::Unevaluated(uv) => uv.expand(),
-            ty::ConstKind::Value(val) => {
-                return Some((fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty()));
-            }
-            err => span_bug!(
-                constant.span,
-                "encountered bad ConstKind after monomorphizing: {:?}",
-                err
-            ),
-        },
-        ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _)
-            if fx.tcx.is_static(def) =>
-        {
-            span_bug!(constant.span, "MIR constant refers to static");
-        }
-        ConstantKind::Unevaluated(uv, _) => uv,
-        ConstantKind::Val(val, _) => return Some((val, constant_kind.ty())),
-    };
-
-    let val = fx
-        .tcx
-        .const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None)
+    let cv = fx.monomorphize(constant.literal);
+    let val = cv
+        .eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span))
         .map_err(|err| match err {
             ErrorHandled::Reported(_) => {
                 fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
@@ -111,7 +89,7 @@ pub(crate) fn eval_mir_constant<'tcx>(
             }
         })
         .ok();
-    val.map(|val| (val, constant_kind.ty()))
+    val.map(|val| (val, cv.ty()))
 }
 
 pub(crate) fn codegen_constant_operand<'tcx>(
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 067c824aba0..02f022b9454 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -670,10 +670,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
                 // avoiding collisions and will make the emitted type names shorter.
                 let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
                     let mut hasher = StableHasher::new();
-                    let ct = ct.eval(tcx, ty::ParamEnv::reveal_all());
-                    hcx.while_hashing_spans(false, |hcx| {
-                        ct.to_valtree().hash_stable(hcx, &mut hasher)
-                    });
+                    let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), None).unwrap();
+                    hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
                     hasher.finish::<Hash64>()
                 });
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index babcf9bee24..4d7bd60ceca 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -24,43 +24,31 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &self,
         constant: &mir::Constant<'tcx>,
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
-        let ct = self.monomorphize(constant.literal);
-        let uv = match ct {
-            mir::ConstantKind::Ty(ct) => match ct.kind() {
-                ty::ConstKind::Unevaluated(uv) => uv.expand(),
-                ty::ConstKind::Value(val) => {
-                    return Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val)));
+        self.monomorphize(constant.literal)
+            .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
+            .map_err(|err| {
+                match err {
+                    ErrorHandled::Reported(_) => {
+                        self.cx
+                            .tcx()
+                            .sess
+                            .emit_err(errors::ErroneousConstant { span: constant.span });
+                    }
+                    ErrorHandled::TooGeneric => {
+                        self.cx.tcx().sess.diagnostic().emit_bug(
+                            errors::PolymorphicConstantTooGeneric { span: constant.span },
+                        );
+                    }
                 }
-                err => span_bug!(
-                    constant.span,
-                    "encountered bad ConstKind after monomorphizing: {:?}",
-                    err
-                ),
-            },
-            mir::ConstantKind::Unevaluated(uv, _) => uv,
-            mir::ConstantKind::Val(val, _) => return Ok(val),
-        };
-
-        self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
-            match err {
-                ErrorHandled::Reported(_) => {
-                    self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span });
-                }
-                ErrorHandled::TooGeneric => {
-                    self.cx
-                        .tcx()
-                        .sess
-                        .diagnostic()
-                        .emit_bug(errors::PolymorphicConstantTooGeneric { span: constant.span });
-                }
-            }
-            err
-        })
+                err
+            })
     }
 
     /// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
     /// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to
     /// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
+    ///
+    /// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees!
     pub fn eval_unevaluated_mir_constant_to_valtree(
         &self,
         constant: &mir::Constant<'tcx>,
@@ -80,7 +68,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             // `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but
             // the user pass through arbitrary expressions.
             // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real
-            // const generic.
+            // const generic, and get rid of this entire function.
             other => span_bug!(constant.span, "{other:#?}"),
         };
         let uv = self.monomorphize(uv);
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 76ac2b2ac60..7e3be0b5d5f 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -71,6 +71,8 @@ TrivialTypeTraversalAndLiftImpls! { ErrorHandled }
 
 pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
 pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
+/// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed.
+/// This is needed in `thir::pattern::lower_inline_const`.
 pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
 
 pub fn struct_error<'tcx>(
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 3d45b4bdc33..c5f0280e617 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2300,18 +2300,6 @@ impl<'tcx> ConstantKind<'tcx> {
     }
 
     #[inline]
-    pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option<interpret::ConstValue<'tcx>> {
-        match self {
-            ConstantKind::Ty(c) => match c.kind() {
-                ty::ConstKind::Value(valtree) => Some(tcx.valtree_to_const_val((c.ty(), valtree))),
-                _ => None,
-            },
-            ConstantKind::Val(val, _) => Some(val),
-            ConstantKind::Unevaluated(..) => None,
-        }
-    }
-
-    #[inline]
     pub fn try_to_scalar(self) -> Option<Scalar> {
         match self {
             ConstantKind::Ty(c) => match c.kind() {
@@ -2342,37 +2330,59 @@ impl<'tcx> ConstantKind<'tcx> {
     }
 
     #[inline]
-    pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
-        match self {
-            Self::Ty(c) => {
-                if let Some(val) = c.try_eval_for_mir(tcx, param_env) {
-                    match val {
-                        Ok(val) => Self::Val(val, c.ty()),
-                        Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
-                    }
+    pub fn eval(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        span: Option<Span>,
+    ) -> Result<interpret::ConstValue<'tcx>, ErrorHandled> {
+        let (uneval, param_env) = match self {
+            ConstantKind::Ty(c) => {
+                if let ty::ConstKind::Unevaluated(uneval) = c.kind() {
+                    // Avoid the round-trip via valtree, evaluate directly to ConstValue.
+                    let (param_env, uneval) = uneval.prepare_for_eval(tcx, param_env);
+                    (uneval.expand(), param_env)
                 } else {
-                    self
+                    // It's already a valtree, or an error.
+                    let val = c.eval(tcx, param_env, span)?;
+                    return Ok(tcx.valtree_to_const_val((self.ty(), val)));
                 }
             }
-            Self::Val(_, _) => self,
-            Self::Unevaluated(uneval, ty) => {
-                // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
-                match tcx.const_eval_resolve(param_env, uneval, None) {
-                    Ok(val) => Self::Val(val, ty),
-                    Err(ErrorHandled::TooGeneric) => self,
-                    Err(ErrorHandled::Reported(guar)) => {
-                        Self::Ty(ty::Const::new_error(tcx, guar.into(), ty))
-                    }
-                }
+            ConstantKind::Unevaluated(uneval, _) => (uneval, param_env),
+            ConstantKind::Val(val, _) => return Ok(val),
+        };
+        // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
+        tcx.const_eval_resolve(param_env, uneval, span)
+    }
+
+    /// Normalizes the constant to a value or an error if possible.
+    #[inline]
+    pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
+        match self.eval(tcx, param_env, None) {
+            Ok(val) => Self::Val(val, self.ty()),
+            Err(ErrorHandled::Reported(guar)) => {
+                Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty()))
             }
+            Err(ErrorHandled::TooGeneric) => self,
         }
     }
 
-    /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
     #[inline]
-    pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
-        self.try_eval_bits(tcx, param_env, ty)
-            .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
+    pub fn try_eval_scalar(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Option<Scalar> {
+        self.eval(tcx, param_env, None).ok()?.try_to_scalar()
+    }
+
+    #[inline]
+    pub fn try_eval_scalar_int(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Option<ScalarInt> {
+        self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
     }
 
     #[inline]
@@ -2382,59 +2392,38 @@ impl<'tcx> ConstantKind<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         ty: Ty<'tcx>,
     ) -> Option<u128> {
-        match self {
-            Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty),
-            Self::Val(val, t) => {
-                assert_eq!(*t, ty);
-                let size =
-                    tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
-                val.try_to_bits(size)
-            }
-            Self::Unevaluated(uneval, ty) => {
-                match tcx.const_eval_resolve(param_env, *uneval, None) {
-                    Ok(val) => {
-                        let size = tcx
-                            .layout_of(param_env.with_reveal_all_normalized(tcx).and(*ty))
-                            .ok()?
-                            .size;
-                        val.try_to_bits(size)
-                    }
-                    Err(_) => None,
-                }
-            }
-        }
+        let int = self.try_eval_scalar_int(tcx, param_env)?;
+        assert_eq!(self.ty(), ty);
+        let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
+        int.to_bits(size).ok()
     }
 
+    /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
     #[inline]
-    pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
-        match self {
-            Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
-            Self::Val(val, _) => val.try_to_bool(),
-            Self::Unevaluated(uneval, _) => {
-                match tcx.const_eval_resolve(param_env, *uneval, None) {
-                    Ok(val) => val.try_to_bool(),
-                    Err(_) => None,
-                }
-            }
-        }
+    pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
+        self.try_eval_bits(tcx, param_env, ty)
+            .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
     }
 
     #[inline]
     pub fn try_eval_target_usize(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Option<u64> {
-        match self {
-            Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
-            Self::Val(val, _) => val.try_to_target_usize(tcx),
-            Self::Unevaluated(uneval, _) => {
-                match tcx.const_eval_resolve(param_env, *uneval, None) {
-                    Ok(val) => val.try_to_target_usize(tcx),
-                    Err(_) => None,
-                }
-            }
-        }
+        self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
+    }
+
+    #[inline]
+    /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
+    pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u64 {
+        self.try_eval_target_usize(tcx, param_env)
+            .unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
+    }
+
+    #[inline]
+    pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
+        self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
     }
 
     #[inline]
@@ -2576,7 +2565,7 @@ impl<'tcx> ConstantKind<'tcx> {
         }
     }
 
-    pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
+    pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
         match c.kind() {
             ty::ConstKind::Value(valtree) => {
                 let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
@@ -2610,6 +2599,11 @@ impl<'tcx> UnevaluatedConst<'tcx> {
     pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
         UnevaluatedConst { def, args, promoted: Default::default() }
     }
+
+    #[inline]
+    pub fn from_instance(instance: ty::Instance<'tcx>) -> Self {
+        UnevaluatedConst::new(instance.def_id(), instance.args)
+    }
 }
 
 /// A collection of projections into user types.
@@ -2884,7 +2878,7 @@ fn pretty_print_const_value<'tcx>(
                 }
             }
             (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
-                let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap();
+                let n = n.try_to_target_usize(tcx).unwrap();
                 // cast is ok because we already checked for pointer size (32 or 64 bit) above
                 let range = AllocRange { start: offset, size: Size::from_bytes(n) };
                 let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index cce10417e1b..629f9f8cd7d 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,5 +1,5 @@
 use crate::middle::resolve_bound_vars as rbv;
-use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar};
+use crate::mir::interpret::{AllocId, ErrorHandled, LitToConstInput, Scalar};
 use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use rustc_data_structures::intern::Interned;
 use rustc_error_messages::MultiSpan;
@@ -14,9 +14,8 @@ mod valtree;
 
 pub use int::*;
 pub use kind::*;
-use rustc_span::ErrorGuaranteed;
+use rustc_span::Span;
 use rustc_span::DUMMY_SP;
-use rustc_target::abi::Size;
 pub use valtree::*;
 
 use super::sty::ConstKind;
@@ -36,16 +35,6 @@ pub struct ConstData<'tcx> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(ConstData<'_>, 40);
 
-enum EvalMode {
-    Typeck,
-    Mir,
-}
-
-enum EvalResult<'tcx> {
-    ValTree(ty::ValTree<'tcx>),
-    ConstVal(ConstValue<'tcx>),
-}
-
 impl<'tcx> Const<'tcx> {
     #[inline]
     pub fn ty(self) -> Ty<'tcx> {
@@ -165,7 +154,7 @@ impl<'tcx> Const<'tcx> {
 
         let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
 
-        match Self::try_eval_lit_or_param(tcx, ty, expr) {
+        match Self::try_from_lit_or_param(tcx, ty, expr) {
             Some(v) => v,
             None => ty::Const::new_unevaluated(
                 tcx,
@@ -179,7 +168,7 @@ impl<'tcx> Const<'tcx> {
     }
 
     #[instrument(skip(tcx), level = "debug")]
-    fn try_eval_lit_or_param(
+    fn try_from_lit_or_param(
         tcx: TyCtxt<'tcx>,
         ty: Ty<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
@@ -254,14 +243,6 @@ impl<'tcx> Const<'tcx> {
         }
     }
 
-    /// Panics if self.kind != ty::ConstKind::Value
-    pub fn to_valtree(self) -> ty::ValTree<'tcx> {
-        match self.kind() {
-            ty::ConstKind::Value(valtree) => valtree,
-            _ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
-        }
-    }
-
     #[inline]
     /// Creates a constant with the given integer value and interns it.
     pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self {
@@ -294,14 +275,66 @@ impl<'tcx> Const<'tcx> {
         Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
     }
 
-    /// Attempts to convert to a `ValTree`
-    pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
+    /// Returns the evaluated constant
+    #[inline]
+    pub fn eval(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        span: Option<Span>,
+    ) -> Result<ValTree<'tcx>, ErrorHandled> {
+        assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
         match self.kind() {
-            ty::ConstKind::Value(valtree) => Some(valtree),
-            _ => None,
+            ConstKind::Unevaluated(unevaluated) => {
+                // FIXME(eddyb) maybe the `const_eval_*` methods should take
+                // `ty::ParamEnvAnd` instead of having them separate.
+                let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
+                // try to resolve e.g. associated constants to their definition on an impl, and then
+                // evaluate the const.
+                let c = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?;
+                Ok(c.expect("`ty::Const::eval` called on a non-valtree-compatible type"))
+            }
+            ConstKind::Value(val) => Ok(val),
+            ConstKind::Error(g) => Err(g.into()),
+            ConstKind::Param(_)
+            | ConstKind::Infer(_)
+            | ConstKind::Bound(_, _)
+            | ConstKind::Placeholder(_)
+            | ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric),
         }
     }
 
+    /// Normalizes the constant to a value or an error if possible.
+    #[inline]
+    pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
+        match self.eval(tcx, param_env, None) {
+            Ok(val) => Self::new_value(tcx, val, self.ty()),
+            Err(ErrorHandled::Reported(r)) => Self::new_error(tcx, r.into(), self.ty()),
+            Err(ErrorHandled::TooGeneric) => self,
+        }
+    }
+
+    #[inline]
+    pub fn try_eval_scalar(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Option<Scalar> {
+        self.eval(tcx, param_env, None).ok()?.try_to_scalar()
+    }
+
+    #[inline]
+    /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
+    /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
+    /// contains const generic parameters or pointers).
+    pub fn try_eval_scalar_int(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+    ) -> Option<ScalarInt> {
+        self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
+    }
+
     #[inline]
     /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
     /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
@@ -312,15 +345,18 @@ impl<'tcx> Const<'tcx> {
         param_env: ParamEnv<'tcx>,
         ty: Ty<'tcx>,
     ) -> Option<u128> {
+        let int = self.try_eval_scalar_int(tcx, param_env)?;
         assert_eq!(self.ty(), ty);
         let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
         // if `ty` does not depend on generic parameters, use an empty param_env
-        self.eval(tcx, param_env).try_to_bits(size)
+        int.to_bits(size).ok()
     }
 
     #[inline]
-    pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
-        self.eval(tcx, param_env).try_to_bool()
+    /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
+    pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
+        self.try_eval_bits(tcx, param_env, ty)
+            .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
     }
 
     #[inline]
@@ -329,29 +365,12 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
     ) -> Option<u64> {
-        self.eval(tcx, param_env).try_to_target_usize(tcx)
-    }
-
-    #[inline]
-    /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
-    /// unevaluated constant.
-    pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
-        if let Some(val) = self.try_eval_for_typeck(tcx, param_env) {
-            match val {
-                Ok(val) => ty::Const::new_value(tcx, val, self.ty()),
-                Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
-            }
-        } else {
-            // Either the constant isn't evaluatable or ValTree creation failed.
-            self
-        }
+        self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
     }
 
     #[inline]
-    /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
-    pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
-        self.try_eval_bits(tcx, param_env, ty)
-            .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
+    pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
+        self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
     }
 
     #[inline]
@@ -361,136 +380,30 @@ impl<'tcx> Const<'tcx> {
             .unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
     }
 
-    #[inline]
-    /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
-    /// return `None`.
-    // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
-    pub fn try_eval_for_mir(
-        self,
-        tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
-    ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
-        match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
-            Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
-            Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
-            Some(Err(e)) => Some(Err(e)),
-            None => None,
-        }
-    }
-
-    #[inline]
-    /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
-    /// return `None`.
-    // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
-    pub fn try_eval_for_typeck(
-        self,
-        tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
-    ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
-        match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
-            Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
-            Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
-            Some(Err(e)) => Some(Err(e)),
-            None => None,
+    /// Panics if self.kind != ty::ConstKind::Value
+    pub fn to_valtree(self) -> ty::ValTree<'tcx> {
+        match self.kind() {
+            ty::ConstKind::Value(valtree) => valtree,
+            _ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
         }
     }
 
-    #[inline]
-    fn try_eval_inner(
-        self,
-        tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
-        eval_mode: EvalMode,
-    ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
-        assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
-        if let ConstKind::Unevaluated(unevaluated) = self.kind() {
-            use crate::mir::interpret::ErrorHandled;
-
-            // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
-            // also does later, but we want to do it before checking for
-            // inference variables.
-            // Note that we erase regions *before* calling `with_reveal_all_normalized`,
-            // so that we don't try to invoke this query with
-            // any region variables.
-
-            // HACK(eddyb) when the query key would contain inference variables,
-            // attempt using identity args and `ParamEnv` instead, that will succeed
-            // when the expression doesn't depend on any parameters.
-            // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
-            // we can call `infcx.const_eval_resolve` which handles inference variables.
-            let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
-                tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
-                    def: unevaluated.def,
-                    args: GenericArgs::identity_for_item(tcx, unevaluated.def),
-                })
-            } else {
-                tcx.erase_regions(param_env)
-                    .with_reveal_all_normalized(tcx)
-                    .and(tcx.erase_regions(unevaluated))
-            };
-
-            // FIXME(eddyb) maybe the `const_eval_*` methods should take
-            // `ty::ParamEnvAnd` instead of having them separate.
-            let (param_env, unevaluated) = param_env_and.into_parts();
-            // try to resolve e.g. associated constants to their definition on an impl, and then
-            // evaluate the const.
-            match eval_mode {
-                EvalMode::Typeck => {
-                    match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
-                        // NOTE(eddyb) `val` contains no lifetimes/types/consts,
-                        // and we use the original type, so nothing from `args`
-                        // (which may be identity args, see above),
-                        // can leak through `val` into the const we return.
-                        Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
-                        Err(ErrorHandled::TooGeneric) => None,
-                        Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
-                    }
-                }
-                EvalMode::Mir => {
-                    match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
-                        // NOTE(eddyb) `val` contains no lifetimes/types/consts,
-                        // and we use the original type, so nothing from `args`
-                        // (which may be identity args, see above),
-                        // can leak through `val` into the const we return.
-                        Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
-                        Err(ErrorHandled::TooGeneric) => None,
-                        Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
-                    }
-                }
-            }
-        } else {
-            None
+    /// Attempts to convert to a `ValTree`
+    pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
+        match self.kind() {
+            ty::ConstKind::Value(valtree) => Some(valtree),
+            _ => None,
         }
     }
 
     #[inline]
-    pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
-        if let ConstKind::Value(val) = self.kind() { Some(val) } else { None }
-    }
-
-    #[inline]
     pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
-        self.try_to_value()?.try_to_scalar()
-    }
-
-    #[inline]
-    pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
-        self.try_to_value()?.try_to_scalar_int()
-    }
-
-    #[inline]
-    pub fn try_to_bits(self, size: Size) -> Option<u128> {
-        self.try_to_scalar_int()?.to_bits(size).ok()
-    }
-
-    #[inline]
-    pub fn try_to_bool(self) -> Option<bool> {
-        self.try_to_scalar_int()?.try_into().ok()
+        self.try_to_valtree()?.try_to_scalar()
     }
 
     #[inline]
     pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
-        self.try_to_value()?.try_to_target_usize(tcx)
+        self.try_to_valtree()?.try_to_target_usize(tcx)
     }
 
     pub fn is_ct_infer(self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 17fbbd7c6b7..a0a7331a37e 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -2,7 +2,7 @@ use super::Const;
 use crate::mir;
 use crate::ty::abstract_const::CastKind;
 use crate::ty::GenericArgsRef;
-use crate::ty::{self, List, Ty};
+use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
@@ -26,6 +26,39 @@ impl<'tcx> UnevaluatedConst<'tcx> {
     pub fn expand(self) -> mir::UnevaluatedConst<'tcx> {
         mir::UnevaluatedConst { def: self.def, args: self.args, promoted: None }
     }
+
+    /// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
+    /// hurts performance.
+    #[inline]
+    pub(crate) fn prepare_for_eval(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> (ty::ParamEnv<'tcx>, Self) {
+        // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
+        // also does later, but we want to do it before checking for
+        // inference variables.
+        // Note that we erase regions *before* calling `with_reveal_all_normalized`,
+        // so that we don't try to invoke this query with
+        // any region variables.
+
+        // HACK(eddyb) when the query key would contain inference variables,
+        // attempt using identity args and `ParamEnv` instead, that will succeed
+        // when the expression doesn't depend on any parameters.
+        // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
+        // we can call `infcx.const_eval_resolve` which handles inference variables.
+        if (param_env, self).has_non_region_infer() {
+            (
+                tcx.param_env(self.def),
+                ty::UnevaluatedConst {
+                    def: self.def,
+                    args: ty::GenericArgs::identity_for_item(tcx, self.def),
+                },
+            )
+        } else {
+            (tcx.erase_regions(param_env).with_reveal_all_normalized(tcx), tcx.erase_regions(self))
+        }
+    }
 }
 
 impl<'tcx> UnevaluatedConst<'tcx> {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 7736183027f..0ea61ec8d40 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -198,11 +198,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
             (Some(PatKind::Constant { value: lo }), None) => {
                 let hi = ty.numeric_max_val(self.tcx)?;
-                Some((*lo, mir::ConstantKind::from_const(hi, self.tcx)))
+                Some((*lo, mir::ConstantKind::from_ty_const(hi, self.tcx)))
             }
             (None, Some(PatKind::Constant { value: hi })) => {
                 let lo = ty.numeric_min_val(self.tcx)?;
-                Some((mir::ConstantKind::from_const(lo, self.tcx), *hi))
+                Some((mir::ConstantKind::from_ty_const(lo, self.tcx), *hi))
             }
             _ => None,
         }
@@ -626,6 +626,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args: args };
         // First try using a valtree in order to destructure the constant into a pattern.
+        // FIXME: replace "try to do a thing, then fall back to another thing"
+        // but something more principled, like a trait query checking whether this can be turned into a valtree.
         if let Ok(Some(valtree)) =
             self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
         {
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 13550672ecc..11da9612f2f 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -209,7 +209,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                     && let operand_ty = operand.ty(self.local_decls, self.tcx)
                     && let Some(operand_ty) = operand_ty.builtin_deref(true)
                     && let ty::Array(_, len) = operand_ty.ty.kind()
-                    && let Some(len) = ConstantKind::Ty(*len).eval(self.tcx, self.param_env).try_to_scalar_int()
+                    && let Some(len) = ConstantKind::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
                 {
                     state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
                 }
@@ -228,8 +228,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 let place_ty = place.ty(self.local_decls, self.tcx);
                 if let ty::Array(_, len) = place_ty.ty.kind() {
                     ConstantKind::Ty(*len)
-                        .eval(self.tcx, self.param_env)
-                        .try_to_scalar()
+                        .try_eval_scalar(self.tcx, self.param_env)
                         .map_or(FlatSet::Top, FlatSet::Elem)
                 } else if let [ProjectionElem::Deref] = place.projection[..] {
                     state.get_len(place.local.into(), self.map())
@@ -304,8 +303,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
     ) -> Self::Value {
         constant
             .literal
-            .eval(self.tcx, self.param_env)
-            .try_to_scalar()
+            .try_eval_scalar(self.tcx, self.param_env)
             .map_or(FlatSet::Top, FlatSet::Elem)
     }
 
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 8b0a0903d18..6e191b285be 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -136,7 +136,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
                     return;
                 }
 
-                let literal = ConstantKind::from_const(len, self.tcx);
+                let literal = ConstantKind::from_ty_const(len, self.tcx);
                 let constant = Constant { span: source_info.span, literal, user_ty: None };
                 *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
             }
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index 6c3b7c58fab..1b846987d38 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -93,7 +93,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
             *rvalue = Rvalue::Use(Operand::Constant(Box::new(Constant {
                 span: rustc_span::DUMMY_SP,
                 user_ty: None,
-                literal: ConstantKind::from_const(len, self.tcx),
+                literal: ConstantKind::from_ty_const(len, self.tcx),
             })));
         }
         self.super_rvalue(rvalue, loc);
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 3a33568084c..2fc102bda13 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -230,7 +230,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
                 self.write_str("[")?;
                 self = self.print_type(ty)?;
                 self.write_str("; ")?;
-                if let Some(size) = size.try_to_bits(self.tcx().data_layout.pointer_size) {
+                if let Some(size) = size.try_to_target_usize(self.tcx()) {
                     write!(self, "{size}")?
                 } else if let ty::ConstKind::Param(param) = size.kind() {
                     self = param.print(self)?
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index da19a3ba4fd..2550570af65 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -562,7 +562,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
     fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
         // We only mangle a typed value if the const can be evaluated.
-        let ct = ct.eval(self.tcx, ty::ParamEnv::reveal_all());
+        let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all());
         match ct.kind() {
             ty::ConstKind::Value(_) => {}
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index e4f5c4003c9..135410691f1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2054,7 +2054,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     tcx: self.tcx,
                     ty_op: |ty| ty,
                     lt_op: |lt| lt,
-                    ct_op: |ct| ct.eval(self.tcx, ty::ParamEnv::empty()),
+                    ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
                 });
                 cand
             })
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 0e73bad1918..fe71a9f07df 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -257,7 +257,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
             if let ty::Array(aty, len) = self_ty.kind() {
                 flags.push((sym::_Self, Some("[]".to_string())));
-                let len = len.try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
+                let len = len.try_to_valtree().and_then(|v| v.try_to_target_usize(self.tcx));
                 flags.push((sym::_Self, Some(format!("[{aty}; _]"))));
                 if let Some(n) = len {
                     flags.push((sym::_Self, Some(format!("[{aty}; {n}]"))));
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index d2210c6d5d9..956f8e047d7 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -288,7 +288,7 @@ pub fn normalize_param_env_or_error<'tcx>(
                     // should actually be okay since without `feature(generic_const_exprs)` the only
                     // const arguments that have a non-empty param env are array repeat counts. These
                     // do not appear in the type system though.
-                    c.eval(self.0, ty::ParamEnv::empty())
+                    c.normalize(self.0, ty::ParamEnv::empty())
                 }
             }
 
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index b31c0e655fb..6444c01a67b 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -761,7 +761,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                 self.selcx.infcx,
                 &mut self.universes,
                 constant,
-                |constant| constant.eval(tcx, self.param_env),
+                |constant| constant.normalize(tcx, self.param_env),
             )
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 87beaddc6c2..f785211c548 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -358,7 +358,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
             self.infcx,
             &mut self.universes,
             constant,
-            |constant| constant.eval(self.infcx.tcx, self.param_env),
+            |constant| constant.normalize(self.infcx.tcx, self.param_env),
         ))
     }
 
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index af2ad547480..6c49e94dc31 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -129,19 +129,16 @@ mod rustc {
             c: Const<'tcx>,
         ) -> Option<Self> {
             use rustc_middle::ty::ScalarInt;
-            use rustc_middle::ty::TypeVisitableExt;
             use rustc_span::symbol::sym;
 
-            let c = c.eval(tcx, param_env);
-
-            if let Err(err) = c.error_reported() {
+            let Ok(cv) = c.eval(tcx, param_env, None) else {
                 return Some(Self {
                     alignment: true,
                     lifetimes: true,
                     safety: true,
                     validity: true,
                 });
-            }
+            };
 
             let adt_def = c.ty().ty_adt_def()?;
 
@@ -153,8 +150,8 @@ mod rustc {
             );
 
             let variant = adt_def.non_enum_variant();
-            let fields = match c.try_to_valtree() {
-                Some(ValTree::Branch(branch)) => branch,
+            let fields = match cv {
+                ValTree::Branch(branch) => branch,
                 _ => {
                     return Some(Self {
                         alignment: true,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f30384701cb..190b1b038b6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1863,7 +1863,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
                     // does nothing for `ConstKind::Param`.
                     let ct = ty::Const::from_anon_const(cx.tcx, anon_const.def_id);
                     let param_env = cx.tcx.param_env(anon_const.def_id);
-                    print_const(cx, ct.eval(cx.tcx, param_env))
+                    print_const(cx, ct.normalize(cx.tcx, param_env))
                 }
             };
 
@@ -2082,7 +2082,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Str => Primitive(PrimitiveType::Str),
         ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None))),
         ty::Array(ty, mut n) => {
-            n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
+            n = n.normalize(cx.tcx, ty::ParamEnv::reveal_all());
             let n = print_const(cx, n);
             Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into())
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 8be3c178a29..6e13148f2fc 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -37,22 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
                         None => {
                             let min_val_const = ty.numeric_min_val(cx.tcx)?;
-                            let min_constant = mir::ConstantKind::from_value(
-                                cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())),
-                                ty,
-                            );
-                            miri_to_const(cx, min_constant)?
+                            miri_to_const(cx, mir::ConstantKind::from_ty_const(min_val_const, cx.tcx))?
                         },
                     };
                     let rhs_const = match rhs {
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
                         None => {
                             let max_val_const = ty.numeric_max_val(cx.tcx)?;
-                            let max_constant = mir::ConstantKind::from_value(
-                                cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())),
-                                ty,
-                            );
-                            miri_to_const(cx, max_constant)?
+                            miri_to_const(cx, mir::ConstantKind::from_ty_const(max_val_const, cx.tcx))?
                         },
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;