diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index f92277b1113..b7e05376c0e 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -1,3 +1,4 @@
+use rustc_attr as attr;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -5,11 +6,17 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{DefIdTree, TyCtxt};
 use rustc_span::symbol::Symbol;
 
-/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
-pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
+/// Whether the `def_id` is an unstable const fn and what feature gate(s) are necessary to enable
+/// it.
+pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<(Symbol, Option<Symbol>)> {
     if tcx.is_const_fn_raw(def_id) {
         let const_stab = tcx.lookup_const_stability(def_id)?;
-        if const_stab.is_const_unstable() { Some(const_stab.feature) } else { None }
+        match const_stab.level {
+            attr::StabilityLevel::Unstable { implied_by, .. } => {
+                Some((const_stab.feature, implied_by))
+            }
+            attr::StabilityLevel::Stable { .. } => None,
+        }
     } else {
         None
     }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 1a23b06d2e8..d11cc65da16 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -926,15 +926,24 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // If the `const fn` we are trying to call is not const-stable, ensure that we have
                 // the proper feature gate enabled.
-                if let Some(gate) = is_unstable_const_fn(tcx, callee) {
+                if let Some((gate, implied_by)) = is_unstable_const_fn(tcx, callee) {
                     trace!(?gate, "calling unstable const fn");
                     if self.span.allows_unstable(gate) {
                         return;
                     }
+                    if let Some(implied_by_gate) = implied_by && self.span.allows_unstable(implied_by_gate) {
+                        return;
+                    }
 
                     // Calling an unstable function *always* requires that the corresponding gate
-                    // be enabled, even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`.
-                    if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) {
+                    // (or implied gate) be enabled, even if the function has
+                    // `#[rustc_allow_const_fn_unstable(the_gate)]`.
+                    let gate_declared = |gate| {
+                        tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate)
+                    };
+                    let feature_gate_declared = gate_declared(gate);
+                    let implied_gate_declared = implied_by.map(gate_declared).unwrap_or(false);
+                    if !feature_gate_declared && !implied_gate_declared {
                         self.check_op(ops::FnCallUnstable(callee, Some(gate)));
                         return;
                     }
@@ -947,7 +956,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     }
 
                     // Otherwise, we are something const-stable calling a const-unstable fn.
-
                     if super::rustc_allow_const_fn_unstable(tcx, caller, gate) {
                         trace!("rustc_allow_const_fn_unstable gate active");
                         return;
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 7299fc9705c..7617818f642 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -265,6 +265,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
                 self.index.implications.insert(implied_by, feature);
             }
 
+            if let Some(ConstStability {
+                level: Unstable { implied_by: Some(implied_by), .. },
+                feature,
+                ..
+            }) = const_stab
+            {
+                self.index.implications.insert(implied_by, feature);
+            }
+
             self.index.stab_map.insert(def_id, stab);
             stab
         });
diff --git a/tests/ui/stability-attribute/auxiliary/const-stability-attribute-implies.rs b/tests/ui/stability-attribute/auxiliary/const-stability-attribute-implies.rs
new file mode 100644
index 00000000000..f78871b5a1d
--- /dev/null
+++ b/tests/ui/stability-attribute/auxiliary/const-stability-attribute-implies.rs
@@ -0,0 +1,12 @@
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![stable(feature = "stability_attribute_implies", since = "1.0.0")]
+#![rustc_const_stable(feature = "stability_attribute_implies", since = "1.0.0")]
+
+#[stable(feature = "stability_attribute_implies", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_foo", since = "1.62.0")]
+pub const fn foo() {}
+
+#[stable(feature = "stability_attribute_implies", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_foo")]
+pub const fn foobar() {}
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs
new file mode 100644
index 00000000000..6d6d793c62b
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs
@@ -0,0 +1,16 @@
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![stable(feature = "stability_attribute_implies", since = "1.0.0")]
+#![rustc_const_stable(feature = "stability_attribute_implies", since = "1.0.0")]
+
+// Tests that `implied_by = "const_bar"` results in an error being emitted if `const_bar` does not
+// exist.
+
+#[stable(feature = "stability_attribute_implies", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")]
+//~^ ERROR feature `const_bar` implying `const_foobar` does not exist
+pub const fn foobar() -> u32 {
+    0
+}
+
+const VAR: u32 = foobar();
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr
new file mode 100644
index 00000000000..6d8b01a5495
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr
@@ -0,0 +1,8 @@
+error: feature `const_bar` implying `const_foobar` does not exist
+  --> $DIR/const-stability-attribute-implies-missing.rs:10:1
+   |
+LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.rs
new file mode 100644
index 00000000000..47e8d2b3609
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.rs
@@ -0,0 +1,16 @@
+// aux-build:const-stability-attribute-implies.rs
+#![crate_type = "lib"]
+
+// Tests that despite the `const_foobar` feature being implied by now-stable feature `const_foo`,
+// if `const_foobar` isn't allowed in this crate then an error will be emitted.
+
+extern crate const_stability_attribute_implies;
+use const_stability_attribute_implies::{foo, foobar};
+
+pub const fn bar() -> u32 {
+    foo(); // no error - stable
+    foobar(); //~ ERROR `foobar` is not yet stable as a const fn
+    0
+}
+
+pub const VAR: u32 = bar();
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr
new file mode 100644
index 00000000000..8ef5a364ecc
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr
@@ -0,0 +1,10 @@
+error: `foobar` is not yet stable as a const fn
+  --> $DIR/const-stability-attribute-implies-no-feature.rs:12:5
+   |
+LL |     foobar();
+   |     ^^^^^^^^
+   |
+   = help: add `#![feature(const_foobar)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.rs
new file mode 100644
index 00000000000..ffaa171d8a5
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.rs
@@ -0,0 +1,19 @@
+// aux-build:const-stability-attribute-implies.rs
+#![crate_type = "lib"]
+#![deny(stable_features)]
+#![feature(const_foo)]
+//~^ ERROR the feature `const_foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `const_foobar`
+
+// Tests that the use of `implied_by` in the `#[rustc_const_unstable]` attribute results in a
+// diagnostic mentioning partial stabilization, and that given the implied unstable feature is
+// unused (there is no `foobar` call), that the compiler suggests removing the flag.
+
+extern crate const_stability_attribute_implies;
+use const_stability_attribute_implies::foo;
+
+pub const fn bar() -> u32 {
+    foo();
+    0
+}
+
+pub const VAR: u32 = bar();
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.stderr
new file mode 100644
index 00000000000..f6a099cd25e
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.stderr
@@ -0,0 +1,22 @@
+error: the feature `const_foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `const_foobar`
+  --> $DIR/const-stability-attribute-implies-using-stable.rs:4:12
+   |
+LL | #![feature(const_foo)]
+   |            ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/const-stability-attribute-implies-using-stable.rs:3:9
+   |
+LL | #![deny(stable_features)]
+   |         ^^^^^^^^^^^^^^^
+help: if you are using features which are still unstable, change to using `const_foobar`
+   |
+LL | #![feature(const_foobar)]
+   |            ~~~~~~~~~~~~
+help: if you are using features which are now stable, remove this line
+   |
+LL - #![feature(const_foo)]
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.rs
new file mode 100644
index 00000000000..2061c5c75bd
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.rs
@@ -0,0 +1,21 @@
+// aux-build:const-stability-attribute-implies.rs
+#![crate_type = "lib"]
+#![deny(stable_features)]
+#![feature(const_foo)]
+//~^ ERROR the feature `const_foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `const_foobar`
+
+// Tests that the use of `implied_by` in the `#[rustc_const_unstable]` attribute results in a
+// diagnostic mentioning partial stabilization and that given the implied unstable feature is
+// used (there is a `const_foobar` call), that the compiler suggests changing to that feature and
+// doesn't error about its use.
+
+extern crate const_stability_attribute_implies;
+use const_stability_attribute_implies::{foo, foobar};
+
+pub const fn bar() -> u32 {
+    foo();
+    foobar(); // no error!
+    0
+}
+
+pub const VAR: u32 = bar();
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.stderr
new file mode 100644
index 00000000000..06385667658
--- /dev/null
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.stderr
@@ -0,0 +1,22 @@
+error: the feature `const_foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `const_foobar`
+  --> $DIR/const-stability-attribute-implies-using-unstable.rs:4:12
+   |
+LL | #![feature(const_foo)]
+   |            ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/const-stability-attribute-implies-using-unstable.rs:3:9
+   |
+LL | #![deny(stable_features)]
+   |         ^^^^^^^^^^^^^^^
+help: if you are using features which are still unstable, change to using `const_foobar`
+   |
+LL | #![feature(const_foobar)]
+   |            ~~~~~~~~~~~~
+help: if you are using features which are now stable, remove this line
+   |
+LL - #![feature(const_foo)]
+   |
+
+error: aborting due to previous error
+