diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 3d7b3da45ccb9..1aeb0bd5ad9aa 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -585,6 +585,9 @@ declare_features! (
     /// Allows `if let` guard in match arms.
     (active, if_let_guard, "1.47.0", Some(51114), None),
 
+    /// Allows non trivial generic constants which have to be manually propageted upwards.
+    (active, const_evaluatable_checked, "1.48.0", Some(76560), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -600,6 +603,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::const_generics,
     sym::let_chains,
     sym::raw_dylib,
+    sym::const_evaluatable_checked,
     sym::const_trait_impl,
     sym::const_trait_bound_opt_out,
     sym::lazy_normalization_consts,
@@ -607,6 +611,6 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
 ];
 
 /// Some features are not allowed to be used together at the same time, if
-/// the two are present, produce an error
+/// the two are present, produce an error.
 pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] =
     &[(sym::const_generics, sym::min_const_generics)];
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5092b945f72c4..407663e57577a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -348,6 +348,7 @@ symbols! {
         const_compare_raw_pointers,
         const_constructor,
         const_eval_limit,
+        const_evaluatable_checked,
         const_extern_fn,
         const_fn,
         const_fn_transmute,
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 013cd71ea305d..fdb87c085b54e 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -14,6 +14,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     span: Span,
 ) -> Result<(), ErrorHandled> {
+    debug!("is_const_evaluatable({:?}, {:?})", def, substs);
+    if infcx.tcx.features().const_evaluatable_checked {
+        // FIXME(const_evaluatable_checked): Actually look into generic constants to
+        // implement const equality.
+        for pred in param_env.caller_bounds() {
+            match pred.skip_binders() {
+                ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => {
+                    debug!("is_const_evaluatable: caller_bound={:?}, {:?}", b_def, b_substs);
+                    if b_def == def && b_substs == substs {
+                        debug!("is_const_evaluatable: caller_bound ~~> ok");
+                        return Ok(());
+                    }
+                }
+                _ => {} // don't care
+            }
+        }
+    }
+
     let future_compat_lint = || {
         if let Some(local_def_id) = def.did.as_local() {
             infcx.tcx.struct_span_lint_hir(
@@ -38,24 +56,23 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
     // See #74595 for more details about this.
     let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span));
 
-    let def_kind = infcx.tcx.def_kind(def.did);
-    match def_kind {
-        DefKind::AnonConst => {
-            let mir_body = if let Some(def) = def.as_const_arg() {
-                infcx.tcx.optimized_mir_of_const_arg(def)
-            } else {
-                infcx.tcx.optimized_mir(def.did)
-            };
-            if mir_body.is_polymorphic && concrete.is_ok() {
-                future_compat_lint();
-            }
-        }
-        _ => {
-            if substs.has_param_types_or_consts() && concrete.is_ok() {
-                future_compat_lint();
+    if concrete.is_ok() && substs.has_param_types_or_consts() {
+        match infcx.tcx.def_kind(def.did) {
+            DefKind::AnonConst => {
+                let mir_body = if let Some(def) = def.as_const_arg() {
+                    infcx.tcx.optimized_mir_of_const_arg(def)
+                } else {
+                    infcx.tcx.optimized_mir(def.did)
+                };
+
+                if mir_body.is_polymorphic {
+                    future_compat_lint();
+                }
             }
+            _ => future_compat_lint(),
         }
     }
 
+    debug!(?concrete, "is_const_evaluatable");
     concrete.map(drop)
 }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index ea59375bad736..7d6b3df03b064 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -37,11 +37,12 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::mono::Linkage;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
 use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
+use rustc_middle::ty::{TypeFoldable, TypeVisitor};
 use rustc_session::config::SanitizerSet;
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
@@ -50,6 +51,8 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 
+use smallvec::SmallVec;
+
 mod type_of;
 
 struct OnlySelfBounds(bool);
@@ -1672,10 +1675,46 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate
                 .alloc_from_iter(result.predicates.iter().chain(inferred_outlives).copied());
         }
     }
+
+    if tcx.features().const_evaluatable_checked {
+        let const_evaluatable = const_evaluatable_predicates_of(tcx, def_id, &result);
+        result.predicates =
+            tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(const_evaluatable));
+    }
+
     debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
     result
 }
 
+pub fn const_evaluatable_predicates_of<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    predicates: &ty::GenericPredicates<'tcx>,
+) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> {
+    #[derive(Default)]
+    struct ConstCollector<'tcx> {
+        ct: SmallVec<[(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>); 4]>,
+    }
+
+    impl<'tcx> TypeVisitor<'tcx> for ConstCollector<'tcx> {
+        fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> bool {
+            if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
+                self.ct.push((def, substs));
+            }
+            false
+        }
+    }
+
+    let mut collector = ConstCollector::default();
+    for (pred, _span) in predicates.predicates.iter() {
+        pred.visit_with(&mut collector);
+    }
+    warn!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.ct);
+    collector.ct.into_iter().map(move |(def_id, subst)| {
+        (ty::PredicateAtom::ConstEvaluatable(def_id, subst).to_predicate(tcx), DUMMY_SP)
+    })
+}
+
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
 /// `Self: Trait` predicates for traits.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs
new file mode 100644
index 0000000000000..941bd5e9e5d0a
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs
@@ -0,0 +1,14 @@
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+type Arr<const N: usize> = [u8; N - 1];
+
+fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
+    //~^ ERROR constant expression depends
+    Default::default()
+}
+
+fn main() {
+    let x = test::<33>();
+    assert_eq!(x, [0; 32]);
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.stderr b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.stderr
new file mode 100644
index 0000000000000..6e4a22a38b17c
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.stderr
@@ -0,0 +1,10 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/feature-gate-const_evaluatable_checked.rs:6:30
+   |
+LL | fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
+   |                              ^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
new file mode 100644
index 0000000000000..a7ead78b97bae
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+type Arr<const N: usize> = [u8; N - 1];
+
+fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
+    Default::default()
+}
+
+fn main() {
+    let x = test::<33>();
+    assert_eq!(x, [0; 32]);
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs
new file mode 100644
index 0000000000000..1edf1885dd281
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs
@@ -0,0 +1,12 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+type Arr<const N: usize> = [u8; N - 1]; //~ ERROR evaluation of constant
+
+fn test<const N: usize>() -> Arr<N> where Arr<N>: Sized {
+    todo!()
+}
+
+fn main() {
+    test::<0>();
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr
new file mode 100644
index 0000000000000..1ac5e1d95537a
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/simple_fail.rs:4:33
+   |
+LL | type Arr<const N: usize> = [u8; N - 1];
+   |                                 ^^^^^ attempt to compute `0_usize - 1_usize` which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.