about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs4
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs26
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs2
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs18
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs21
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs25
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs8
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs22
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs16
-rw-r--r--compiler/rustc_privacy/src/lib.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs17
21 files changed, 107 insertions, 171 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 3d55ffc595f..a74016e220e 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -192,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
                 (
                     ty::PredicateKind::ConstEvaluatable(a),
                     ty::PredicateKind::ConstEvaluatable(b),
-                ) => tcx.try_unify_abstract_consts(self_param_env.and((a, b))),
+                ) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
                 (
                     ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
                     ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 0a8a1bec9b8..33ed3b96aa8 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1101,8 +1101,6 @@ fn check_type_defn<'tcx, F>(
 
             // Explicit `enum` discriminant values must const-evaluate successfully.
             if let Some(discr_def_id) = variant.explicit_discr {
-                let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
-
                 let cause = traits::ObligationCause::new(
                     tcx.def_span(discr_def_id),
                     wfcx.body_id,
@@ -1112,10 +1110,7 @@ fn check_type_defn<'tcx, F>(
                     cause,
                     wfcx.param_env,
                     ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
-                        ty::UnevaluatedConst::new(
-                            ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
-                            discr_substs,
-                        ),
+                        ty::Const::from_anon_const(tcx, discr_def_id),
                     ))
                     .to_predicate(tcx),
                 ));
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index db8f8de68f2..2e84e1d0160 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -318,10 +318,10 @@ fn const_evaluatable_predicates_of<'tcx>(
         fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
             let def_id = self.tcx.hir().local_def_id(c.hir_id);
             let ct = ty::Const::from_anon_const(self.tcx, def_id);
-            if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
+            if let ty::ConstKind::Unevaluated(_) = ct.kind() {
                 let span = self.tcx.hir().span(c.hir_id);
                 self.preds.insert((
-                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
+                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
                         .to_predicate(self.tcx),
                     span,
                 ));
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 45c84680ad2..a58cbc3767e 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -55,6 +55,7 @@
 #![feature(drain_filter)]
 #![feature(intra_doc_pointers)]
 #![feature(yeet_expr)]
+#![feature(result_option_inspect)]
 #![feature(const_option)]
 #![recursion_limit = "512"]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index a7e86141a04..473894ac1ca 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -4,7 +4,9 @@ use crate::mir;
 use crate::ty::subst::InternalSubsts;
 use crate::ty::visit::TypeVisitable;
 use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
+use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -83,7 +85,29 @@ impl<'tcx> TyCtxt<'tcx> {
         match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: None };
-                self.const_eval_global_id_for_typeck(param_env, cid, span)
+                self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
+                    // We are emitting the lint here instead of in `is_const_evaluatable`
+                    // as we normalize obligations before checking them, and normalization
+                    // uses this function to evaluate this constant.
+                    //
+                    // @lcnr believes that successfully evaluating even though there are
+                    // used generic parameters is a bug of evaluation, so checking for it
+                    // here does feel somewhat sensible.
+                    if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
+                        assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst));
+                        let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def);
+                        if mir_body.is_polymorphic {
+                            let Some(local_def_id) = ct.def.did.as_local() else { return };
+                            self.struct_span_lint_hir(
+                                lint::builtin::CONST_EVALUATABLE_UNCHECKED,
+                                self.hir().local_def_id_to_hir_id(local_def_id),
+                                self.def_span(ct.def.did),
+                                "cannot use constants which depend on generic parameters in types",
+                                |err| err,
+                            )
+                        }
+                    }
+                })
             }
             Ok(None) => Err(ErrorHandled::TooGeneric),
             Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 315e3794f15..f998e608344 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -263,6 +263,10 @@ impl<'tcx> Const<'tcx> {
         self.try_eval_usize(tcx, param_env)
             .unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
     }
+
+    pub fn is_ct_infer(self) -> bool {
+        matches!(self.kind(), ty::ConstKind::Infer(_))
+    }
 }
 
 pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 03866d5e054..4ab761e0715 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -15,7 +15,7 @@ use super::ScalarInt;
 
 /// An unevaluated (potentially generic) constant used in the type-system.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
-#[derive(Hash, HashStable)]
+#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct UnevaluatedConst<'tcx> {
     pub def: ty::WithOptConstParam<DefId>,
     pub substs: SubstsRef<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index a6d0678e99d..7201737be65 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -34,12 +34,6 @@ impl FlagComputation {
         result.flags
     }
 
-    pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags {
-        let mut result = FlagComputation::new();
-        result.add_unevaluated_const(uv);
-        result.flags
-    }
-
     fn add_flags(&mut self, flags: TypeFlags) {
         self.flags = self.flags | flags;
     }
@@ -256,7 +250,7 @@ impl FlagComputation {
                 self.add_substs(substs);
             }
             ty::PredicateKind::ConstEvaluatable(uv) => {
-                self.add_unevaluated_const(uv);
+                self.add_const(uv);
             }
             ty::PredicateKind::ConstEquate(expected, found) => {
                 self.add_const(expected);
@@ -289,7 +283,10 @@ impl FlagComputation {
     fn add_const(&mut self, c: ty::Const<'_>) {
         self.add_ty(c.ty());
         match c.kind() {
-            ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
+            ty::ConstKind::Unevaluated(uv) => {
+                self.add_substs(uv.substs);
+                self.add_flags(TypeFlags::HAS_CT_PROJECTION);
+            }
             ty::ConstKind::Infer(infer) => {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
                 match infer {
@@ -313,11 +310,6 @@ impl FlagComputation {
         }
     }
 
-    fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) {
-        self.add_substs(ct.substs);
-        self.add_flags(TypeFlags::HAS_CT_PROJECTION);
-    }
-
     fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
         self.add_substs(projection.substs);
         match projection.term.unpack() {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index f456999ae3e..54f1499eb3d 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -126,13 +126,6 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
         c.super_fold_with(self)
     }
 
-    fn fold_ty_unevaluated(
-        &mut self,
-        uv: ty::UnevaluatedConst<'tcx>,
-    ) -> ty::UnevaluatedConst<'tcx> {
-        uv.super_fold_with(self)
-    }
-
     fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
         p.super_fold_with(self)
     }
@@ -169,13 +162,6 @@ pub trait FallibleTypeFolder<'tcx>: Sized {
         c.try_super_fold_with(self)
     }
 
-    fn try_fold_ty_unevaluated(
-        &mut self,
-        c: ty::UnevaluatedConst<'tcx>,
-    ) -> Result<ty::UnevaluatedConst<'tcx>, Self::Error> {
-        c.try_super_fold_with(self)
-    }
-
     fn try_fold_predicate(
         &mut self,
         p: ty::Predicate<'tcx>,
@@ -215,13 +201,6 @@ where
         Ok(self.fold_const(c))
     }
 
-    fn try_fold_ty_unevaluated(
-        &mut self,
-        c: ty::UnevaluatedConst<'tcx>,
-    ) -> Result<ty::UnevaluatedConst<'tcx>, !> {
-        Ok(self.fold_ty_unevaluated(c))
-    }
-
     fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
         Ok(self.fold_predicate(p))
     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 4400ff12de0..984f6522359 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -683,7 +683,7 @@ pub enum PredicateKind<'tcx> {
     Coerce(CoercePredicate<'tcx>),
 
     /// Constant initializer must evaluate successfully.
-    ConstEvaluatable(ty::UnevaluatedConst<'tcx>),
+    ConstEvaluatable(ty::Const<'tcx>),
 
     /// Constants must be equal. The first component is the const that is expected.
     ConstEquate(Const<'tcx>, Const<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 66354196b4e..0b06ccc19ec 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2702,8 +2702,8 @@ define_print_and_forward_display! {
                 print_value_path(closure_def_id, &[]),
                 write("` implements the trait `{}`", kind))
             }
-            ty::PredicateKind::ConstEvaluatable(uv) => {
-                p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
+            ty::PredicateKind::ConstEvaluatable(ct) => {
+                p!("the constant `", print(ct), "` can be evaluated")
             }
             ty::PredicateKind::ConstEquate(c1, c2) => {
                 p!("the constant `", print(c1), "` equals `", print(c2), "`")
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 1164cf3e01a..2cad333e3f5 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -166,8 +166,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
             ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
                 write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
             }
-            ty::PredicateKind::ConstEvaluatable(uv) => {
-                write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
+            ty::PredicateKind::ConstEvaluatable(ct) => {
+                write!(f, "ConstEvaluatable({ct:?})")
             }
             ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
@@ -832,27 +832,6 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
-    fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        folder.try_fold_ty_unevaluated(self)
-    }
-}
-
-impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
-    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        visitor.visit_ty_unevaluated(*self)
-    }
-}
-
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
-    fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
-        self,
-        folder: &mut F,
-    ) -> Result<Self, F::Error> {
-        Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? })
-    }
-}
-
 impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.substs.visit_with(visitor)
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index c2a83ca9dbb..c9930e8ad0a 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -188,6 +188,14 @@ impl<'tcx> GenericArg<'tcx> {
             _ => bug!("expected a const, but found another kind"),
         }
     }
+
+    pub fn is_non_region_infer(self) -> bool {
+        match self.unpack() {
+            GenericArgKind::Lifetime(_) => false,
+            GenericArgKind::Type(ty) => ty.is_ty_infer(),
+            GenericArgKind::Const(ct) => ct.is_ct_infer(),
+        }
+    }
 }
 
 impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 5ca00a11ab9..c09f71f9a6d 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -197,13 +197,6 @@ pub trait TypeVisitor<'tcx>: Sized {
         c.super_visit_with(self)
     }
 
-    fn visit_ty_unevaluated(
-        &mut self,
-        uv: ty::UnevaluatedConst<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
-        uv.super_visit_with(self)
-    }
-
     fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
         p.super_visit_with(self)
     }
@@ -594,21 +587,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
 
     #[inline]
     #[instrument(level = "trace", ret)]
-    fn visit_ty_unevaluated(
-        &mut self,
-        uv: ty::UnevaluatedConst<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
-        let flags = FlagComputation::for_unevaluated_const(uv);
-        trace!(r.flags=?flags);
-        if flags.intersects(self.flags) {
-            ControlFlow::Break(FoundFlags)
-        } else {
-            ControlFlow::CONTINUE
-        }
-    }
-
-    #[inline]
-    #[instrument(level = "trace", ret)]
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
         debug!(
             "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index a3e11bbf056..91db9698c41 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -112,6 +112,22 @@ impl<'tcx> Ty<'tcx> {
     }
 }
 
+impl<'tcx> ty::Const<'tcx> {
+    /// Iterator that walks `self` and any types reachable from
+    /// `self`, in depth-first order. Note that just walks the types
+    /// that appear in `self`, it does not descend into the fields of
+    /// structs or variants. For example:
+    ///
+    /// ```text
+    /// isize => { isize }
+    /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+    /// [isize] => { [isize], isize }
+    /// ```
+    pub fn walk(self) -> TypeWalker<'tcx> {
+        TypeWalker::new(self.into())
+    }
+}
+
 /// We push `GenericArg`s on the stack in reverse order so as to
 /// maintain a pre-order traversal. As of the time of this
 /// writing, the fact that the traversal is pre-order is not
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index b36b893c78e..2636db6dbe1 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -159,34 +159,12 @@ where
                 ty.visit_with(self)
             }
             ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
-            ty::PredicateKind::ConstEvaluatable(uv)
-                if self.def_id_visitor.tcx().features().generic_const_exprs =>
-            {
-                let tcx = self.def_id_visitor.tcx();
-                if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
-                    self.visit_abstract_const_expr(tcx, ct)?;
-                }
-                ControlFlow::CONTINUE
-            }
+            ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
             ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
             _ => bug!("unexpected predicate: {:?}", predicate),
         }
     }
 
-    fn visit_abstract_const_expr(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        ct: AbstractConst<'tcx>,
-    ) -> ControlFlow<V::BreakTy> {
-        walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
-            ACNode::Leaf(leaf) => self.visit_const(leaf),
-            ACNode::Cast(_, _, ty) => self.visit_ty(ty),
-            ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
-                ControlFlow::CONTINUE
-            }
-        })
-    }
-
     fn visit_predicates(
         &mut self,
         predicates: ty::GenericPredicates<'tcx>,
@@ -309,9 +287,16 @@ where
         self.visit_ty(c.ty())?;
         let tcx = self.def_id_visitor.tcx();
         if let Ok(Some(ct)) = AbstractConst::from_const(tcx, c) {
-            self.visit_abstract_const_expr(tcx, ct)?;
+            walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
+                ACNode::Leaf(leaf) => self.visit_const(leaf),
+                ACNode::Cast(_, _, ty) => self.visit_ty(ty),
+                ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
+                    ControlFlow::CONTINUE
+                }
+            })
+        } else {
+            ControlFlow::CONTINUE
         }
-        ControlFlow::CONTINUE
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index b06f24ddf2e..84038625fb2 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -9,14 +9,12 @@
 //! `thir_abstract_const` which can then be checked for structural equality with other
 //! generic constants mentioned in the `caller_bounds` of the current environment.
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def::DefKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::{
     walk_abstract_const, AbstractConst, FailureKind, Node, NotConstEvaluatable,
 };
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
-use rustc_session::lint;
 use rustc_span::Span;
 
 use std::iter;
@@ -161,11 +159,20 @@ pub fn try_unify_abstract_consts<'tcx>(
 #[instrument(skip(infcx), level = "debug")]
 pub fn is_const_evaluatable<'tcx>(
     infcx: &InferCtxt<'tcx>,
-    uv: ty::UnevaluatedConst<'tcx>,
+    ct: ty::Const<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     span: Span,
 ) -> Result<(), NotConstEvaluatable> {
     let tcx = infcx.tcx;
+    let uv = match ct.kind() {
+        ty::ConstKind::Unevaluated(uv) => uv,
+        ty::ConstKind::Param(_)
+        | ty::ConstKind::Bound(_, _)
+        | ty::ConstKind::Placeholder(_)
+        | ty::ConstKind::Value(_)
+        | ty::ConstKind::Error(_) => return Ok(()),
+        ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
+    };
 
     if tcx.features().generic_const_exprs {
         if let Some(ct) = AbstractConst::new(tcx, uv)? {
@@ -253,25 +260,7 @@ pub fn is_const_evaluatable<'tcx>(
                 Err(NotConstEvaluatable::Error(reported))
             }
             Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
-            Ok(_) => {
-                if uv.substs.has_non_region_param() {
-                    assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
-                    let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
-
-                    if mir_body.is_polymorphic {
-                        let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
-                        tcx.struct_span_lint_hir(
-                            lint::builtin::CONST_EVALUATABLE_UNCHECKED,
-                            tcx.hir().local_def_id_to_hir_id(local_def_id),
-                            span,
-                            "cannot use constants which depend on generic parameters in types",
-                            |err| err
-                        )
-                    }
-                }
-
-                Ok(())
-            },
+            Ok(_) => Ok(()),
         }
     }
 }
@@ -285,7 +274,7 @@ fn satisfied_from_param_env<'tcx>(
     for pred in param_env.caller_bounds() {
         match pred.kind().skip_binder() {
             ty::PredicateKind::ConstEvaluatable(uv) => {
-                if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
+                if let Some(b_ct) = AbstractConst::from_const(tcx, uv)? {
                     let const_unify_ctxt = ConstUnifyCtxt { tcx, param_env };
 
                     // Try to unify with each subtree in the AbstractConst to allow for
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 b7e6a564f39..fc0040de6b3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1304,7 +1304,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
 
                 match obligation.predicate.kind().skip_binder() {
-                    ty::PredicateKind::ConstEvaluatable(uv) => {
+                    ty::PredicateKind::ConstEvaluatable(ct) => {
+                        let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
+                            bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
+                        };
                         let mut err =
                             self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
                         let const_span = self.tcx.def_span(uv.def.did);
@@ -2368,7 +2371,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if predicate.references_error() || self.is_tainted_by_errors() {
                     return;
                 }
-                let subst = data.substs.iter().find(|g| g.has_non_region_infer());
+                let subst = data.walk().find(|g| g.is_non_region_infer());
                 if let Some(subst) = subst {
                     let err = self.emit_inference_failure_err(
                         body_id,
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index d4c73427386..a417e1440b9 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -476,9 +476,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Err(NotConstEvaluatable::MentionsInfer) => {
                             pending_obligation.stalled_on.clear();
                             pending_obligation.stalled_on.extend(
-                                uv.substs
-                                    .iter()
-                                    .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
+                                uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
                             );
                             ProcessResult::Unchanged
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 545524f63a7..0bb25a74dc8 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -837,24 +837,14 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
             }
         }
 
-        fn visit_ty_unevaluated(
-            &mut self,
-            uv: ty::UnevaluatedConst<'tcx>,
-        ) -> ControlFlow<Self::BreakTy> {
+        fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
             // Constants can only influence object safety if they reference `Self`.
             // This is only possible for unevaluated constants, so we walk these here.
             //
-            // If `AbstractConst::new` returned an error we already failed compilation
+            // If `AbstractConst::from_const` returned an error we already failed compilation
             // so we don't have to emit an additional error here.
-            //
-            // We currently recurse into abstract consts here but do not recurse in
-            // `is_const_evaluatable`. This means that the object safety check is more
-            // liberal than the const eval check.
-            //
-            // This shouldn't really matter though as we can't really use any
-            // constants which are not considered const evaluatable.
             use rustc_middle::ty::abstract_const::Node;
-            if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) {
+            if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
                 walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
                     Node::Leaf(leaf) => self.visit_const(leaf),
                     Node::Cast(_, _, ty) => self.visit_ty(ty),
@@ -863,7 +853,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
                     }
                 })
             } else {
-                ControlFlow::CONTINUE
+                ct.super_visit_with(self)
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 635cdde0e8e..0870833cc35 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -148,13 +148,8 @@ pub fn predicate_obligations<'tcx>(
             wf.compute(a.into());
             wf.compute(b.into());
         }
-        ty::PredicateKind::ConstEvaluatable(uv) => {
-            let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
-            wf.out.extend(obligations);
-
-            for arg in uv.substs.iter() {
-                wf.compute(arg);
-            }
+        ty::PredicateKind::ConstEvaluatable(ct) => {
+            wf.compute(ct.into());
         }
         ty::PredicateKind::ConstEquate(c1, c2) => {
             wf.compute(c1.into());
@@ -476,14 +471,14 @@ impl<'tcx> WfPredicates<'tcx> {
                 // obligations are handled by the parent (e.g. `ty::Ref`).
                 GenericArgKind::Lifetime(_) => continue,
 
-                GenericArgKind::Const(constant) => {
-                    match constant.kind() {
+                GenericArgKind::Const(ct) => {
+                    match ct.kind() {
                         ty::ConstKind::Unevaluated(uv) => {
                             let obligations = self.nominal_obligations(uv.def.did, uv.substs);
                             self.out.extend(obligations);
 
                             let predicate =
-                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
+                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
                                     .to_predicate(self.tcx());
                             let cause = self.cause(traits::WellFormed(None));
                             self.out.push(traits::Obligation::with_depth(
@@ -500,7 +495,7 @@ impl<'tcx> WfPredicates<'tcx> {
                                 cause,
                                 self.recursion_depth,
                                 self.param_env,
-                                ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.into()))
+                                ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
                                     .to_predicate(self.tcx()),
                             ));
                         }