about summary refs log tree commit diff
path: root/tests/ui
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-10-06 19:59:19 +0200
committerRalf Jung <post@ralfj.de>2024-10-25 20:31:40 +0200
commita0215d8e46aab41219dea0bb1cbaaf97dafe2f89 (patch)
treecb98c6fb900deceea7aa9f2d08455de383c45d02 /tests/ui
parent45089ec19ebebec88bace6ec237244ff0eaa7ad3 (diff)
downloadrust-a0215d8e46aab41219dea0bb1cbaaf97dafe2f89.tar.gz
rust-a0215d8e46aab41219dea0bb1cbaaf97dafe2f89.zip
Re-do recursive const stability checks
Fundamentally, we have *three* disjoint categories of functions:
1. const-stable functions
2. private/unstable functions that are meant to be callable from const-stable functions
3. functions that can make use of unstable const features

This PR implements the following system:
- `#[rustc_const_stable]` puts functions in the first category. It may only be applied to `#[stable]` functions.
- `#[rustc_const_unstable]` by default puts functions in the third category. The new attribute `#[rustc_const_stable_indirect]` can be added to such a function to move it into the second category.
- `const fn` without a const stability marker are in the second category if they are still unstable. They automatically inherit the feature gate for regular calls, it can now also be used for const-calls.

Also, several holes in recursive const stability checking are being closed.
There's still one potential hole that is hard to avoid, which is when MIR
building automatically inserts calls to a particular function in stable
functions -- which happens in the panic machinery. Those need to *not* be
`rustc_const_unstable` (or manually get a `rustc_const_stable_indirect`) to be
sure they follow recursive const stability. But that's a fairly rare and special
case so IMO it's fine.

The net effect of this is that a `#[unstable]` or unmarked function can be
constified simply by marking it as `const fn`, and it will then be
const-callable from stable `const fn` and subject to recursive const stability
requirements. If it is publicly reachable (which implies it cannot be unmarked),
it will be const-unstable under the same feature gate. Only if the function ever
becomes `#[stable]` does it need a `#[rustc_const_unstable]` or
`#[rustc_const_stable]` marker to decide if this should also imply
const-stability.

Adding `#[rustc_const_unstable]` is only needed for (a) functions that need to
use unstable const lang features (including intrinsics), or (b) `#[stable]`
functions that are not yet intended to be const-stable. Adding
`#[rustc_const_stable]` is only needed for functions that are actually meant to
be directly callable from stable const code. `#[rustc_const_stable_indirect]` is
used to mark intrinsics as const-callable and for `#[rustc_const_unstable]`
functions that are actually called from other, exposed-on-stable `const fn`. No
other attributes are required.
Diffstat (limited to 'tests/ui')
-rw-r--r--tests/ui/borrowck/issue-64453.rs1
-rw-r--r--tests/ui/borrowck/issue-64453.stderr13
-rw-r--r--tests/ui/consts/auxiliary/unstable_but_const_stable.rs13
-rw-r--r--tests/ui/consts/auxiliary/unstable_intrinsic.rs26
-rw-r--r--tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs4
-rw-r--r--tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr14
-rw-r--r--tests/ui/consts/const-eval/simd/insert_extract.rs3
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.rs76
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.stderr127
-rw-r--r--tests/ui/consts/copy-intrinsic.rs2
-rw-r--r--tests/ui/consts/copy-intrinsic.stderr8
-rw-r--r--tests/ui/consts/intrinsic_without_const_stab.rs17
-rw-r--r--tests/ui/consts/intrinsic_without_const_stab.stderr11
-rw-r--r--tests/ui/consts/intrinsic_without_const_stab_fail.rs15
-rw-r--r--tests/ui/consts/intrinsic_without_const_stab_fail.stderr11
-rw-r--r--tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs34
-rw-r--r--tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr108
-rw-r--r--tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs8
-rw-r--r--tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr46
-rw-r--r--tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs8
-rw-r--r--tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr46
-rw-r--r--tests/ui/consts/rustc-const-stability-require-const.rs31
-rw-r--r--tests/ui/consts/rustc-const-stability-require-const.stderr54
-rw-r--r--tests/ui/consts/unstable-const-stable.rs14
-rw-r--r--tests/ui/consts/unstable-const-stable.stderr43
-rw-r--r--tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr22
-rw-r--r--tests/ui/intrinsics/const-eval-select-stability.rs2
-rw-r--r--tests/ui/intrinsics/const-eval-select-stability.stderr13
-rw-r--r--tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs1
-rw-r--r--tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr10
-rw-r--r--tests/ui/stability-attribute/missing-const-stability.rs13
-rw-r--r--tests/ui/stability-attribute/missing-const-stability.stderr10
-rw-r--r--tests/ui/target-feature/feature-hierarchy.rs1
-rw-r--r--tests/ui/target-feature/no-llvm-leaks.rs1
-rw-r--r--tests/ui/traits/const-traits/auxiliary/staged-api.rs9
-rw-r--r--tests/ui/traits/const-traits/effects/minicore.rs2
-rw-r--r--tests/ui/traits/const-traits/issue-79450.rs1
-rw-r--r--tests/ui/traits/const-traits/issue-79450.stderr2
-rw-r--r--tests/ui/traits/const-traits/staged-api.rs34
-rw-r--r--tests/ui/traits/const-traits/staged-api.stable.stderr56
-rw-r--r--tests/ui/traits/const-traits/staged-api.unstable.stderr102
41 files changed, 731 insertions, 281 deletions
diff --git a/tests/ui/borrowck/issue-64453.rs b/tests/ui/borrowck/issue-64453.rs
index 33d55be5812..5f1f35d6ca9 100644
--- a/tests/ui/borrowck/issue-64453.rs
+++ b/tests/ui/borrowck/issue-64453.rs
@@ -3,7 +3,6 @@ struct Value;
 
 static settings_dir: String = format!("");
 //~^ ERROR cannot call non-const fn
-//~| ERROR is not yet stable as a const
 
 fn from_string(_: String) -> Value {
     Value
diff --git a/tests/ui/borrowck/issue-64453.stderr b/tests/ui/borrowck/issue-64453.stderr
index e671817633b..98b05ead649 100644
--- a/tests/ui/borrowck/issue-64453.stderr
+++ b/tests/ui/borrowck/issue-64453.stderr
@@ -1,12 +1,3 @@
-error: `Arguments::<'a>::new_const` is not yet stable as a const fn
-  --> $DIR/issue-64453.rs:4:31
-   |
-LL | static settings_dir: String = format!("");
-   |                               ^^^^^^^^^^^
-   |
-   = help: add `#![feature(const_fmt_arguments_new)]` to the crate attributes to enable
-   = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0015]: cannot call non-const fn `format` in statics
   --> $DIR/issue-64453.rs:4:31
    |
@@ -18,7 +9,7 @@ LL | static settings_dir: String = format!("");
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0507]: cannot move out of static item `settings_dir`
-  --> $DIR/issue-64453.rs:14:37
+  --> $DIR/issue-64453.rs:13:37
    |
 LL |     let settings_data = from_string(settings_dir);
    |                                     ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
@@ -28,7 +19,7 @@ help: consider cloning the value if the performance cost is acceptable
 LL |     let settings_data = from_string(settings_dir.clone());
    |                                                 ++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0015, E0507.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/auxiliary/unstable_but_const_stable.rs b/tests/ui/consts/auxiliary/unstable_but_const_stable.rs
deleted file mode 100644
index 88044b0272c..00000000000
--- a/tests/ui/consts/auxiliary/unstable_but_const_stable.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(staged_api, rustc_attrs, intrinsics)]
-#![stable(since="1.0.0", feature = "stable")]
-
-extern "rust-intrinsic" {
-    #[unstable(feature = "unstable", issue = "42")]
-    #[rustc_const_stable(feature = "stable", since = "1.0.0")]
-    #[rustc_nounwind]
-    pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
-}
-
-#[unstable(feature = "unstable", issue = "42")]
-#[rustc_const_stable(feature = "stable", since = "1.0.0")]
-pub const fn some_unstable_fn() {}
diff --git a/tests/ui/consts/auxiliary/unstable_intrinsic.rs b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
new file mode 100644
index 00000000000..edef499dbb1
--- /dev/null
+++ b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
@@ -0,0 +1,26 @@
+#![feature(staged_api, rustc_attrs, intrinsics)]
+#![stable(since="1.0.0", feature = "stable")]
+
+#[stable(since="1.0.0", feature = "stable")]
+pub mod old_way {
+    extern "rust-intrinsic" {
+        #[unstable(feature = "unstable", issue = "42")]
+        pub fn size_of_val<T>(x: *const T) -> usize;
+
+        #[unstable(feature = "unstable", issue = "42")]
+        #[rustc_const_unstable(feature = "unstable", issue = "42")]
+        pub fn min_align_of_val<T>(x: *const T) -> usize;
+    }
+}
+
+#[stable(since="1.0.0", feature = "stable")]
+pub mod new_way {
+    #[unstable(feature = "unstable", issue = "42")]
+    #[rustc_intrinsic]
+    pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+
+    #[unstable(feature = "unstable", issue = "42")]
+    #[rustc_const_unstable(feature = "unstable", issue = "42")]
+    #[rustc_intrinsic]
+    pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
+}
diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
index 4b3cf70739c..6c93c0e63b6 100644
--- a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
+++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs
@@ -3,7 +3,7 @@
             we're apparently really bad at it",
             issue = "none")]
 
-#![feature(staged_api)]
+#![feature(staged_api, foo)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature="foo", issue = "none")]
@@ -11,7 +11,7 @@ const fn foo() -> u32 { 42 }
 
 fn meh() -> u32 { 42 }
 
-const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn
+const fn bar() -> u32 { foo() } //~ ERROR cannot use `#[feature(foo)]`
 
 fn a() {
     let _: &'static u32 = &foo(); //~ ERROR temporary value dropped while borrowed
diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
index 2e697b219c5..1de1c78faf6 100644
--- a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
+++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
@@ -1,10 +1,20 @@
-error: `foo` is not yet stable as a const fn
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
   --> $DIR/dont_promote_unstable_const_fn.rs:14:25
    |
 LL | const fn bar() -> u32 { foo() }
    |                         ^^^^^
    |
-   = help: add `#![feature(foo)]` to the crate attributes to enable
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn bar() -> u32 { foo() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo)]
+LL | const fn bar() -> u32 { foo() }
+   |
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/dont_promote_unstable_const_fn.rs:17:28
diff --git a/tests/ui/consts/const-eval/simd/insert_extract.rs b/tests/ui/consts/const-eval/simd/insert_extract.rs
index f4f25327aaf..57d4b4888ca 100644
--- a/tests/ui/consts/const-eval/simd/insert_extract.rs
+++ b/tests/ui/consts/const-eval/simd/insert_extract.rs
@@ -11,8 +11,11 @@
 #[repr(simd)] struct f32x4([f32; 4]);
 
 extern "rust-intrinsic" {
+    #[stable(feature = "foo", since = "1.3.37")]
     #[rustc_const_stable(feature = "foo", since = "1.3.37")]
     fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
+
+    #[stable(feature = "foo", since = "1.3.37")]
     #[rustc_const_stable(feature = "foo", since = "1.3.37")]
     fn simd_extract<T, U>(x: T, idx: u32) -> U;
 }
diff --git a/tests/ui/consts/const-unstable-intrinsic.rs b/tests/ui/consts/const-unstable-intrinsic.rs
new file mode 100644
index 00000000000..050abc6dd46
--- /dev/null
+++ b/tests/ui/consts/const-unstable-intrinsic.rs
@@ -0,0 +1,76 @@
+//! Ensure that unstable intrinsics can actually not be called,
+//! neither within a crate nor cross-crate.
+//@ aux-build:unstable_intrinsic.rs
+#![feature(staged_api, rustc_attrs, intrinsics)]
+#![stable(since="1.0.0", feature = "stable")]
+#![feature(local)]
+
+extern crate unstable_intrinsic;
+
+fn main() {
+    const_main();
+}
+
+const fn const_main() {
+    let x = 42;
+    unsafe {
+        unstable_intrinsic::old_way::size_of_val(&x);
+        //~^ERROR: unstable library feature 'unstable'
+        //~|ERROR: cannot call non-const intrinsic
+        unstable_intrinsic::old_way::min_align_of_val(&x);
+        //~^ERROR: unstable library feature 'unstable'
+        //~|ERROR: not yet stable as a const intrinsic
+        unstable_intrinsic::new_way::size_of_val(&x);
+        //~^ERROR: unstable library feature 'unstable'
+        //~|ERROR: cannot be (indirectly) exposed to stable
+        unstable_intrinsic::new_way::min_align_of_val(&x);
+        //~^ERROR: unstable library feature 'unstable'
+        //~|ERROR: not yet stable as a const intrinsic
+
+        old_way::size_of_val(&x);
+        //~^ERROR: cannot call non-const intrinsic
+        old_way::min_align_of_val(&x);
+        //~^ERROR: cannot use `#[feature(local)]`
+        new_way::size_of_val(&x);
+        //~^ERROR: cannot be (indirectly) exposed to stable
+        new_way::min_align_of_val(&x);
+        //~^ERROR: cannot use `#[feature(local)]`
+    }
+}
+
+#[stable(since="1.0.0", feature = "stable")]
+pub mod old_way {
+    extern "rust-intrinsic" {
+        #[unstable(feature = "local", issue = "42")]
+        pub fn size_of_val<T>(x: *const T) -> usize;
+
+        #[unstable(feature = "local", issue = "42")]
+        #[rustc_const_unstable(feature = "local", issue = "42")]
+        pub fn min_align_of_val<T>(x: *const T) -> usize;
+    }
+}
+
+#[stable(since="1.0.0", feature = "stable")]
+pub mod new_way {
+    #[unstable(feature = "local", issue = "42")]
+    #[rustc_intrinsic]
+    pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+
+    #[unstable(feature = "local", issue = "42")]
+    #[rustc_const_unstable(feature = "local", issue = "42")]
+    #[rustc_intrinsic]
+    pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
+#[inline]
+pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
+    // Const stability attributes are not inherited from parent items.
+    extern "rust-intrinsic" {
+        fn copy<T>(src: *const T, dst: *mut T, count: usize);
+    }
+
+    unsafe { copy(src, dst, count) }
+    //~^ ERROR cannot call non-const intrinsic
+}
diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr
new file mode 100644
index 00000000000..33a434c503d
--- /dev/null
+++ b/tests/ui/consts/const-unstable-intrinsic.stderr
@@ -0,0 +1,127 @@
+error[E0658]: use of unstable library feature 'unstable'
+  --> $DIR/const-unstable-intrinsic.rs:17:9
+   |
+LL |         unstable_intrinsic::old_way::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
+   = help: add `#![feature(unstable)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature 'unstable'
+  --> $DIR/const-unstable-intrinsic.rs:20:9
+   |
+LL |         unstable_intrinsic::old_way::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
+   = help: add `#![feature(unstable)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature 'unstable'
+  --> $DIR/const-unstable-intrinsic.rs:23:9
+   |
+LL |         unstable_intrinsic::new_way::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
+   = help: add `#![feature(unstable)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature 'unstable'
+  --> $DIR/const-unstable-intrinsic.rs:26:9
+   |
+LL |         unstable_intrinsic::new_way::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
+   = help: add `#![feature(unstable)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: cannot call non-const intrinsic `size_of_val` in constant functions
+  --> $DIR/const-unstable-intrinsic.rs:17:9
+   |
+LL |         unstable_intrinsic::old_way::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `min_align_of_val` is not yet stable as a const intrinsic
+  --> $DIR/const-unstable-intrinsic.rs:20:9
+   |
+LL |         unstable_intrinsic::old_way::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable)]` to the crate attributes to enable
+
+error: intrinsic `unstable_intrinsic::new_way::size_of_val` cannot be (indirectly) exposed to stable
+  --> $DIR/const-unstable-intrinsic.rs:23:9
+   |
+LL |         unstable_intrinsic::new_way::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
+
+error: `min_align_of_val` is not yet stable as a const intrinsic
+  --> $DIR/const-unstable-intrinsic.rs:26:9
+   |
+LL |         unstable_intrinsic::new_way::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable)]` to the crate attributes to enable
+
+error: cannot call non-const intrinsic `size_of_val` in constant functions
+  --> $DIR/const-unstable-intrinsic.rs:30:9
+   |
+LL |         old_way::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
+  --> $DIR/const-unstable-intrinsic.rs:32:9
+   |
+LL |         old_way::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn const_main() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(local)]
+LL | const fn const_main() {
+   |
+
+error: intrinsic `new_way::size_of_val` cannot be (indirectly) exposed to stable
+  --> $DIR/const-unstable-intrinsic.rs:34:9
+   |
+LL |         new_way::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
+
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
+  --> $DIR/const-unstable-intrinsic.rs:36:9
+   |
+LL |         new_way::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn const_main() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(local)]
+LL | const fn const_main() {
+   |
+
+error: cannot call non-const intrinsic `copy` in constant functions
+  --> $DIR/const-unstable-intrinsic.rs:74:14
+   |
+LL |     unsafe { copy(src, dst, count) }
+   |              ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs
index 805c03da546..62917c0b98b 100644
--- a/tests/ui/consts/copy-intrinsic.rs
+++ b/tests/ui/consts/copy-intrinsic.rs
@@ -5,9 +5,11 @@
 use std::mem;
 
 extern "rust-intrinsic" {
+    #[stable(feature = "dummy", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
 
+    #[stable(feature = "dummy", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
     fn copy<T>(src: *const T, dst: *mut T, count: usize);
 }
diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr
index da8139129c9..29a88f6270b 100644
--- a/tests/ui/consts/copy-intrinsic.stderr
+++ b/tests/ui/consts/copy-intrinsic.stderr
@@ -1,23 +1,23 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:28:5
+  --> $DIR/copy-intrinsic.rs:30:5
    |
 LL |     copy_nonoverlapping(0x100 as *const i32, dangle, 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:37:5
+  --> $DIR/copy-intrinsic.rs:39:5
    |
 LL |     copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:44:5
+  --> $DIR/copy-intrinsic.rs:46:5
    |
 LL |     copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:50:5
+  --> $DIR/copy-intrinsic.rs:52:5
    |
 LL |     copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
diff --git a/tests/ui/consts/intrinsic_without_const_stab.rs b/tests/ui/consts/intrinsic_without_const_stab.rs
deleted file mode 100644
index 40ec65d51be..00000000000
--- a/tests/ui/consts/intrinsic_without_const_stab.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(intrinsics, staged_api)]
-#![stable(feature = "core", since = "1.6.0")]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-#[inline]
-pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
-    // Const stability attributes are not inherited from parent items.
-    extern "rust-intrinsic" {
-        fn copy<T>(src: *const T, dst: *mut T, count: usize);
-    }
-
-    unsafe { copy(src, dst, count) }
-    //~^ ERROR cannot call non-const fn
-}
-
-fn main() {}
diff --git a/tests/ui/consts/intrinsic_without_const_stab.stderr b/tests/ui/consts/intrinsic_without_const_stab.stderr
deleted file mode 100644
index e3143080c5f..00000000000
--- a/tests/ui/consts/intrinsic_without_const_stab.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0015]: cannot call non-const fn `copy::copy::<T>` in constant functions
-  --> $DIR/intrinsic_without_const_stab.rs:13:14
-   |
-LL |     unsafe { copy(src, dst, count) }
-   |              ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/intrinsic_without_const_stab_fail.rs b/tests/ui/consts/intrinsic_without_const_stab_fail.rs
deleted file mode 100644
index 2b0745b3c11..00000000000
--- a/tests/ui/consts/intrinsic_without_const_stab_fail.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#![feature(intrinsics, staged_api)]
-#![stable(feature = "core", since = "1.6.0")]
-
-extern "rust-intrinsic" {
-    fn copy<T>(src: *const T, dst: *mut T, count: usize);
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-#[inline]
-pub const unsafe fn stuff<T>(src: *const T, dst: *mut T, count: usize) {
-    unsafe { copy(src, dst, count) } //~ ERROR cannot call non-const fn
-}
-
-fn main() {}
diff --git a/tests/ui/consts/intrinsic_without_const_stab_fail.stderr b/tests/ui/consts/intrinsic_without_const_stab_fail.stderr
deleted file mode 100644
index 8ade68eb2a9..00000000000
--- a/tests/ui/consts/intrinsic_without_const_stab_fail.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0015]: cannot call non-const fn `copy::<T>` in constant functions
-  --> $DIR/intrinsic_without_const_stab_fail.rs:12:14
-   |
-LL |     unsafe { copy(src, dst, count) }
-   |              ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
index 461499e942f..d6f07994e82 100644
--- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
+++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
@@ -5,7 +5,7 @@
             issue = "none")]
 
 #![feature(foo, foo2)]
-#![feature(const_async_blocks, staged_api)]
+#![feature(const_async_blocks, staged_api, rustc_attrs)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature="foo", issue = "none")]
@@ -14,33 +14,55 @@ const fn foo() -> u32 { 42 }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
+const fn bar() -> u32 { foo() } //~ ERROR cannot use `#[feature(foo)]`
 
 #[unstable(feature = "foo2", issue = "none")]
+#[rustc_const_unstable(feature = "foo2", issue = "none")]
 const fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
+const fn bar2() -> u32 { foo2() } //~ ERROR cannot use `#[feature(foo2)]`
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // conformity is required
 const fn bar3() -> u32 {
     let x = async { 13 };
-    //~^ ERROR const-stable function cannot use `#[feature(const_async_blocks)]`
+    //~^ ERROR cannot use `#[feature(const_async_blocks)]`
     foo()
-    //~^ ERROR is not yet stable as a const fn
+    //~^ ERROR cannot use `#[feature(foo)]`
 }
 
 // check whether this function cannot be called even with the feature gate active
 #[unstable(feature = "foo2", issue = "none")]
+#[rustc_const_unstable(feature = "foo2", issue = "none")]
 const fn foo2_gated() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn
+const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
+
+// Functions without any attribute are checked like stable functions,
+// even if they are in a stable module.
+mod stable {
+    #![stable(feature = "rust1", since = "1.0.0")]
+
+    pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
+}
+// And same for const-unstable functions that are marked as "stable_indirect".
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo", issue = "none")]
+#[rustc_const_stable_indirect]
+const fn stable_indirect() -> u32 { foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
+
+// These functiuons *can* be called from fully stable functions.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
+const fn bar2_gated_exposed() -> u32 {
+    stable::bar2_gated_stable_indirect() + stable_indirect()
+}
 
 fn main() {}
diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
index fedc5a4809d..899cec07ac7 100644
--- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
+++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
@@ -1,51 +1,127 @@
-error: `foo` is not yet stable as a const fn
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
   --> $DIR/min_const_fn_libstd_stability.rs:17:25
    |
 LL | const fn bar() -> u32 { foo() }
    |                         ^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn bar() -> u32 { foo() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo)]
+LL | const fn bar() -> u32 { foo() }
+   |
 
-error: `foo2` is not yet stable as a const fn
-  --> $DIR/min_const_fn_libstd_stability.rs:25:26
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_fn_libstd_stability.rs:26:26
    |
 LL | const fn bar2() -> u32 { foo2() }
    |                          ^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn bar2() -> u32 { foo2() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo2)]
+LL | const fn bar2() -> u32 { foo2() }
+   |
 
-error: const-stable function cannot use `#[feature(const_async_blocks)]`
-  --> $DIR/min_const_fn_libstd_stability.rs:31:13
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_async_blocks)]`
+  --> $DIR/min_const_fn_libstd_stability.rs:32:13
    |
 LL |     let x = async { 13 };
    |             ^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be stable, make this function unstably const
+help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn bar3() -> u32 {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval)
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
    |
 LL + #[rustc_allow_const_fn_unstable(const_async_blocks)]
 LL | const fn bar3() -> u32 {
    |
 
-error: `foo` is not yet stable as a const fn
-  --> $DIR/min_const_fn_libstd_stability.rs:33:5
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
+  --> $DIR/min_const_fn_libstd_stability.rs:34:5
    |
 LL |     foo()
    |     ^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn bar3() -> u32 {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo)]
+LL | const fn bar3() -> u32 {
+   |
 
-error: `foo2_gated` is not yet stable as a const fn
-  --> $DIR/min_const_fn_libstd_stability.rs:44:32
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_fn_libstd_stability.rs:46:32
    |
 LL | const fn bar2_gated() -> u32 { foo2_gated() }
    |                                ^^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn bar2_gated() -> u32 { foo2_gated() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo2)]
+LL | const fn bar2_gated() -> u32 { foo2_gated() }
+   |
+
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_fn_libstd_stability.rs:53:63
+   |
+LL |     pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
+   |                                                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL +     #[rustc_const_unstable(feature = "...", issue = "...")]
+LL |     pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL +     #[rustc_allow_const_fn_unstable(foo2)]
+LL |     pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
+   |
+
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_fn_libstd_stability.rs:59:37
+   |
+LL | const fn stable_indirect() -> u32 { foo2_gated() }
+   |                                     ^^^^^^^^^^^^
+   |
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn stable_indirect() -> u32 { foo2_gated() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo2)]
+LL | const fn stable_indirect() -> u32 { foo2_gated() }
+   |
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
index 274b4444799..3e82b9ff924 100644
--- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
+++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
@@ -13,24 +13,26 @@ const unsafe fn foo() -> u32 { 42 }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR not yet stable as a const fn
+const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR cannot use `#[feature(foo)]`
 
 #[unstable(feature = "foo2", issue = "none")]
+#[rustc_const_unstable(feature = "foo2", issue = "none")]
 const unsafe fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR not yet stable as a const fn
+const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR cannot use `#[feature(foo2)]`
 
 // check whether this function cannot be called even with the feature gate active
 #[unstable(feature = "foo2", issue = "none")]
+#[rustc_const_unstable(feature = "foo2", issue = "none")]
 const unsafe fn foo2_gated() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
 const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
-//~^ ERROR not yet stable as a const fn
+//~^ ERROR cannot use `#[feature(foo2)]`
 
 fn main() {}
diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
index 353b117efbc..442a079020f 100644
--- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
+++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
@@ -1,26 +1,56 @@
-error: `foo` is not yet stable as a const fn
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:16:41
    |
 LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
    |                                         ^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo)]
+LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
+   |
 
-error: `foo2` is not yet stable as a const fn
-  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:24:42
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:25:42
    |
 LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
    |                                          ^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo2)]
+LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
+   |
 
-error: `foo2_gated` is not yet stable as a const fn
-  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:33:48
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:35:48
    |
 LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
    |                                                ^^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo2)]
+LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
index 94b62071362..cc7eaa51a6f 100644
--- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
+++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
@@ -13,23 +13,25 @@ const fn foo() -> u32 { 42 }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const unsafe fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
+const unsafe fn bar() -> u32 { foo() } //~ ERROR cannot use `#[feature(foo)]`
 
 #[unstable(feature = "foo2", issue = "none")]
+#[rustc_const_unstable(feature="foo2", issue = "none")]
 const fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const unsafe fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
+const unsafe fn bar2() -> u32 { foo2() } //~ ERROR cannot use `#[feature(foo2)]`
 
 // check whether this function cannot be called even with the feature gate active
 #[unstable(feature = "foo2", issue = "none")]
+#[rustc_const_unstable(feature="foo2", issue = "none")]
 const fn foo2_gated() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "rust1", since = "1.0.0")]
 // can't call non-min_const_fn
-const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn
+const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
 
 fn main() {}
diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
index e90ba9b912f..ff37cba7b9a 100644
--- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
+++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
@@ -1,26 +1,56 @@
-error: `foo` is not yet stable as a const fn
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:16:32
    |
 LL | const unsafe fn bar() -> u32 { foo() }
    |                                ^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const unsafe fn bar() -> u32 { foo() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo)]
+LL | const unsafe fn bar() -> u32 { foo() }
+   |
 
-error: `foo2` is not yet stable as a const fn
-  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:24:33
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:25:33
    |
 LL | const unsafe fn bar2() -> u32 { foo2() }
    |                                 ^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const unsafe fn bar2() -> u32 { foo2() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo2)]
+LL | const unsafe fn bar2() -> u32 { foo2() }
+   |
 
-error: `foo2_gated` is not yet stable as a const fn
-  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:39
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:35:39
    |
 LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
    |                                       ^^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(foo2)]
+LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/rustc-const-stability-require-const.rs b/tests/ui/consts/rustc-const-stability-require-const.rs
index 4fb259b335c..6cc3f0f0da1 100644
--- a/tests/ui/consts/rustc-const-stability-require-const.rs
+++ b/tests/ui/consts/rustc-const-stability-require-const.rs
@@ -1,16 +1,16 @@
 #![crate_type = "lib"]
-#![feature(staged_api)]
+#![feature(staged_api, rustc_attrs)]
 #![stable(feature = "foo", since = "1.0.0")]
 
 #[stable(feature = "foo", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_foo", issue = "none")]
 pub fn foo() {}
-//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+//~^ ERROR require the function or method to be `const`
 
 #[stable(feature = "bar", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
 pub fn bar() {}
-//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+//~^ ERROR require the function or method to be `const`
 
 #[stable(feature = "potato", since = "1.0.0")]
 pub struct Potato;
@@ -19,23 +19,23 @@ impl Potato {
     #[stable(feature = "salad", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_salad", issue = "none")]
     pub fn salad(&self) -> &'static str { "mmmmmm" }
-    //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+    //~^ ERROR require the function or method to be `const`
 
     #[stable(feature = "roasted", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
     pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
-    //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+    //~^ ERROR require the function or method to be `const`
 }
 
 #[stable(feature = "bar", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
 pub extern "C" fn bar_c() {}
-//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+//~^ ERROR require the function or method to be `const`
 
 #[stable(feature = "foo", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_foo", issue = "none")]
 pub extern "C" fn foo_c() {}
-//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+//~^ ERROR require the function or method to be `const`
 
 
 #[stable(feature = "foobar", since = "1.0.0")]
@@ -45,3 +45,20 @@ pub const fn foobar() {}
 #[stable(feature = "barfoo", since = "1.0.0")]
 #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
 pub const fn barfoo() {}
+
+// `rustc_const_stable` also requires the function to be stable.
+
+#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
+const fn barfoo_unmarked() {}
+//~^ ERROR can only be applied to functions that are declared `#[stable]`
+
+#[unstable(feature = "unstable", issue = "none")]
+#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
+pub const fn barfoo_unstable() {}
+//~^ ERROR can only be applied to functions that are declared `#[stable]`
+
+// `#[rustc_const_stable_indirect]` also requires a const fn
+#[rustc_const_stable_indirect]
+#[unstable(feature = "unstable", issue = "none")]
+pub fn not_a_const_fn() {}
+//~^ ERROR require the function or method to be `const`
diff --git a/tests/ui/consts/rustc-const-stability-require-const.stderr b/tests/ui/consts/rustc-const-stability-require-const.stderr
index 1027b9311b7..d9a7d37cbcd 100644
--- a/tests/ui/consts/rustc-const-stability-require-const.stderr
+++ b/tests/ui/consts/rustc-const-stability-require-const.stderr
@@ -1,8 +1,6 @@
-error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
   --> $DIR/rustc-const-stability-require-const.rs:7:1
    |
-LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
-   | -------------------------------------------------------------- attribute specified here
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^
    |
@@ -12,11 +10,9 @@ help: make the function or method const
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^
 
-error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
   --> $DIR/rustc-const-stability-require-const.rs:12:1
    |
-LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
-   | ------------------------------------------------------------- attribute specified here
 LL | pub fn bar() {}
    | ^^^^^^^^^^^^
    |
@@ -26,11 +22,9 @@ help: make the function or method const
 LL | pub fn bar() {}
    | ^^^^^^^^^^^^
 
-error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
   --> $DIR/rustc-const-stability-require-const.rs:21:5
    |
-LL |     #[rustc_const_unstable(feature = "const_salad", issue = "none")]
-   |     ---------------------------------------------------------------- attribute specified here
 LL |     pub fn salad(&self) -> &'static str { "mmmmmm" }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -40,11 +34,9 @@ help: make the function or method const
 LL |     pub fn salad(&self) -> &'static str { "mmmmmm" }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
   --> $DIR/rustc-const-stability-require-const.rs:26:5
    |
-LL |     #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
-   |     ------------------------------------------------------------------ attribute specified here
 LL |     pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -54,11 +46,9 @@ help: make the function or method const
 LL |     pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
   --> $DIR/rustc-const-stability-require-const.rs:32:1
    |
-LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
-   | ------------------------------------------------------------- attribute specified here
 LL | pub extern "C" fn bar_c() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -68,11 +58,9 @@ help: make the function or method const
 LL | pub extern "C" fn bar_c() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
   --> $DIR/rustc-const-stability-require-const.rs:37:1
    |
-LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
-   | -------------------------------------------------------------- attribute specified here
 LL | pub extern "C" fn foo_c() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -82,5 +70,33 @@ help: make the function or method const
 LL | pub extern "C" fn foo_c() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
+  --> $DIR/rustc-const-stability-require-const.rs:52:1
+   |
+LL | #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
+   | ---------------------------------------------------------------- attribute specified here
+LL | const fn barfoo_unmarked() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
+  --> $DIR/rustc-const-stability-require-const.rs:57:1
+   |
+LL | #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
+   | ---------------------------------------------------------------- attribute specified here
+LL | pub const fn barfoo_unstable() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
+  --> $DIR/rustc-const-stability-require-const.rs:63:1
+   |
+LL | pub fn not_a_const_fn() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function or method const
+  --> $DIR/rustc-const-stability-require-const.rs:63:1
+   |
+LL | pub fn not_a_const_fn() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/consts/unstable-const-stable.rs b/tests/ui/consts/unstable-const-stable.rs
deleted file mode 100644
index f69e8d0efe5..00000000000
--- a/tests/ui/consts/unstable-const-stable.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ aux-build:unstable_but_const_stable.rs
-
-extern crate unstable_but_const_stable;
-use unstable_but_const_stable::*;
-
-fn main() {
-    some_unstable_fn(); //~ERROR use of unstable library feature
-    unsafe { write_bytes(4 as *mut u8, 0, 0) }; //~ERROR use of unstable library feature
-}
-
-const fn const_main() {
-    some_unstable_fn(); //~ERROR use of unstable library feature
-    unsafe { write_bytes(4 as *mut u8, 0, 0) }; //~ERROR use of unstable library feature
-}
diff --git a/tests/ui/consts/unstable-const-stable.stderr b/tests/ui/consts/unstable-const-stable.stderr
deleted file mode 100644
index c4ffbbb60db..00000000000
--- a/tests/ui/consts/unstable-const-stable.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error[E0658]: use of unstable library feature 'unstable'
-  --> $DIR/unstable-const-stable.rs:7:5
-   |
-LL |     some_unstable_fn();
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: use of unstable library feature 'unstable'
-  --> $DIR/unstable-const-stable.rs:8:14
-   |
-LL |     unsafe { write_bytes(4 as *mut u8, 0, 0) };
-   |              ^^^^^^^^^^^
-   |
-   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: use of unstable library feature 'unstable'
-  --> $DIR/unstable-const-stable.rs:12:5
-   |
-LL |     some_unstable_fn();
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: use of unstable library feature 'unstable'
-  --> $DIR/unstable-const-stable.rs:13:14
-   |
-LL |     unsafe { write_bytes(4 as *mut u8, 0, 0) };
-   |              ^^^^^^^^^^^
-   |
-   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
index 319056a9c88..d599523c727 100644
--- a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
+++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr
@@ -1,31 +1,31 @@
 error: can't mark as unstable using an already stable feature
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
    |
-LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | const fn my_fun() {}
    | -------------------- the stability attribute annotates this item
    |
 help: consider removing the attribute
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
    |
-LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: can't mark as unstable using an already stable feature
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
    |
+LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
 LL | const fn my_fun() {}
    | -------------------- the stability attribute annotates this item
    |
 help: consider removing the attribute
-  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
+  --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
    |
-LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/intrinsics/const-eval-select-stability.rs b/tests/ui/intrinsics/const-eval-select-stability.rs
index 575bc0cadda..25cbadaa22d 100644
--- a/tests/ui/intrinsics/const-eval-select-stability.rs
+++ b/tests/ui/intrinsics/const-eval-select-stability.rs
@@ -15,7 +15,7 @@ const fn nothing(){}
 #[rustc_const_stable(since = "1.0", feature = "const_hey")]
 pub const fn hey() {
     const_eval_select((), nothing, log);
-    //~^ ERROR `const_eval_select` is not yet stable as a const fn
+    //~^ ERROR cannot use `#[feature(const_eval_select)]`
 }
 
 fn main() {}
diff --git a/tests/ui/intrinsics/const-eval-select-stability.stderr b/tests/ui/intrinsics/const-eval-select-stability.stderr
index 335b9877aa0..5f443b1d4ff 100644
--- a/tests/ui/intrinsics/const-eval-select-stability.stderr
+++ b/tests/ui/intrinsics/const-eval-select-stability.stderr
@@ -1,10 +1,19 @@
-error: `const_eval_select` is not yet stable as a const fn
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_eval_select)]`
   --> $DIR/const-eval-select-stability.rs:17:5
    |
 LL |     const_eval_select((), nothing, log);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | pub const fn hey() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(const_eval_select)]
+LL | pub const fn hey() {
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs
index 4089ec72885..6d6d793c62b 100644
--- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs
@@ -14,4 +14,3 @@ pub const fn foobar() -> u32 {
 }
 
 const VAR: u32 = foobar();
-//~^ ERROR: `foobar` is not yet stable as a const fn
diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr
index 918d6ebf992..232de41c769 100644
--- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr
+++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr
@@ -4,13 +4,5 @@ error: feature `const_bar` implying `const_foobar` does not exist
 LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `foobar` is not yet stable as a const fn
-  --> $DIR/const-stability-attribute-implies-missing.rs:16:18
-   |
-LL | const VAR: u32 = foobar();
-   |                  ^^^^^^^^
-   |
-   = help: add `#![feature(const_foobar)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs
index 82da18cc9ac..f1139652550 100644
--- a/tests/ui/stability-attribute/missing-const-stability.rs
+++ b/tests/ui/stability-attribute/missing-const-stability.rs
@@ -1,6 +1,6 @@
 //@ compile-flags: -Znext-solver
 #![feature(staged_api)]
-#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
+#![feature(const_trait_impl, effects, rustc_attrs, intrinsics)] //~ WARN the feature `effects` is incomplete
 #![stable(feature = "stable", since = "1.0.0")]
 
 #[stable(feature = "stable", since = "1.0.0")]
@@ -31,4 +31,15 @@ impl const Bar for Foo {
     fn fun() {}
 }
 
+#[stable(feature = "stable", since = "1.0.0")]
+#[rustc_intrinsic]
+pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+//~^ ERROR function has missing const stability attribute
+
+extern "rust-intrinsic" {
+    #[stable(feature = "stable", since = "1.0.0")]
+    #[rustc_const_stable_indirect]
+    pub fn min_align_of_val<T>(x: *const T) -> usize;
+}
+
 fn main() {}
diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr
index adf60c38611..e62a8b88261 100644
--- a/tests/ui/stability-attribute/missing-const-stability.stderr
+++ b/tests/ui/stability-attribute/missing-const-stability.stderr
@@ -1,7 +1,7 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/missing-const-stability.rs:3:30
    |
-LL | #![feature(const_trait_impl, effects)]
+LL | #![feature(const_trait_impl, effects, rustc_attrs, intrinsics)]
    |                              ^^^^^^^
    |
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
@@ -22,11 +22,17 @@ LL | |     fn fun() {}
 LL | | }
    | |_^
 
+error: function has missing const stability attribute
+  --> $DIR/missing-const-stability.rs:36:1
+   |
+LL | pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: associated function has missing const stability attribute
   --> $DIR/missing-const-stability.rs:16:5
    |
 LL |     pub const fn foo() {}
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs
index 4cf9112810c..7f14d700ecb 100644
--- a/tests/ui/target-feature/feature-hierarchy.rs
+++ b/tests/ui/target-feature/feature-hierarchy.rs
@@ -19,6 +19,7 @@ trait Copy {}
 impl Copy for bool {}
 
 extern "rust-intrinsic" {
+    #[stable(feature = "test", since = "1.0.0")]
     #[rustc_const_stable(feature = "test", since = "1.0.0")]
     fn unreachable() -> !;
 }
diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs
index 9f5dec4447f..f0c887bc1e0 100644
--- a/tests/ui/target-feature/no-llvm-leaks.rs
+++ b/tests/ui/target-feature/no-llvm-leaks.rs
@@ -17,6 +17,7 @@ trait Copy {}
 impl Copy for bool {}
 
 extern "rust-intrinsic" {
+    #[stable(feature = "test", since = "1.0.0")]
     #[rustc_const_stable(feature = "test", since = "1.0.0")]
     fn unreachable() -> !;
 }
diff --git a/tests/ui/traits/const-traits/auxiliary/staged-api.rs b/tests/ui/traits/const-traits/auxiliary/staged-api.rs
index 986165ef91e..bb591321b84 100644
--- a/tests/ui/traits/const-traits/auxiliary/staged-api.rs
+++ b/tests/ui/traits/const-traits/auxiliary/staged-api.rs
@@ -19,3 +19,12 @@ pub struct Unstable;
 impl const MyTrait for Unstable {
     fn func() {}
 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Unstable2;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "unstable2", issue = "none")]
+impl const MyTrait for Unstable2 {
+    fn func() {}
+}
diff --git a/tests/ui/traits/const-traits/effects/minicore.rs b/tests/ui/traits/const-traits/effects/minicore.rs
index a756f4d9f6c..1f0d22eeb38 100644
--- a/tests/ui/traits/const-traits/effects/minicore.rs
+++ b/tests/ui/traits/const-traits/effects/minicore.rs
@@ -515,7 +515,7 @@ trait StructuralPartialEq {}
 
 const fn drop<T: ~const Destruct>(_: T) {}
 
-#[rustc_const_stable(feature = "const_eval_select", since = "1.0.0")]
+#[rustc_const_stable_indirect]
 #[rustc_intrinsic_must_be_overridden]
 #[rustc_intrinsic]
 const fn const_eval_select<ARG: Tuple, F, G, RET>(
diff --git a/tests/ui/traits/const-traits/issue-79450.rs b/tests/ui/traits/const-traits/issue-79450.rs
index b8b9e07b3bd..cdefebc87d6 100644
--- a/tests/ui/traits/const-traits/issue-79450.rs
+++ b/tests/ui/traits/const-traits/issue-79450.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Znext-solver
 #![allow(incomplete_features)]
-#![feature(const_fmt_arguments_new)]
 #![feature(const_trait_impl, effects)]
 
 #[const_trait]
diff --git a/tests/ui/traits/const-traits/issue-79450.stderr b/tests/ui/traits/const-traits/issue-79450.stderr
index 9e6348d37ed..49f380c1a2b 100644
--- a/tests/ui/traits/const-traits/issue-79450.stderr
+++ b/tests/ui/traits/const-traits/issue-79450.stderr
@@ -1,5 +1,5 @@
 error[E0015]: cannot call non-const fn `_print` in constant functions
-  --> $DIR/issue-79450.rs:11:9
+  --> $DIR/issue-79450.rs:10:9
    |
 LL |         println!("lul");
    |         ^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/staged-api.rs b/tests/ui/traits/const-traits/staged-api.rs
index f87e723472a..59fe6d52d5d 100644
--- a/tests/ui/traits/const-traits/staged-api.rs
+++ b/tests/ui/traits/const-traits/staged-api.rs
@@ -2,6 +2,7 @@
 //@ compile-flags: -Znext-solver
 
 #![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file.
+#![cfg_attr(unstable, feature(local_feature))]
 #![feature(const_trait_impl, effects)]
 #![allow(incomplete_features)]
 #![feature(staged_api)]
@@ -16,8 +17,8 @@ use staged_api::*;
 pub struct Foo;
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
-#[cfg_attr(stable, rustc_const_stable(feature = "foo", since = "1.0.0"))]
+#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))]
+#[cfg_attr(stable, rustc_const_stable(feature = "local_feature", since = "1.0.0"))]
 impl const MyTrait for Foo {
     //[stable]~^ ERROR trait implementations cannot be const stable yet
     fn func() {}
@@ -32,32 +33,43 @@ fn non_const_context() {
 #[unstable(feature = "none", issue = "none")]
 const fn const_context() {
     Unstable::func();
-    //[stable]~^ ERROR not yet stable as a const fn
+    //[unstable]~^ ERROR cannot use `#[feature(unstable)]`
+    //[stable]~^^ ERROR not yet stable as a const fn
     Foo::func();
-    //[unstable]~^ ERROR not yet stable as a const fn
-    // ^ fails, because the `foo` feature is not active
+    //[unstable]~^ ERROR cannot use `#[feature(local_feature)]`
+    //[stable]~^^ cannot be (indirectly) exposed to stable
+    // We get the error on `stable` since this is a trait function.
+    Unstable2::func();
+    //~^ ERROR not yet stable as a const fn
+    // ^ fails, because the `unstable2` feature is not active
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
+#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))]
 pub const fn const_context_not_const_stable() {
     //[stable]~^ ERROR function has missing const stability attribute
     Unstable::func();
     //[stable]~^ ERROR not yet stable as a const fn
     Foo::func();
-    //[unstable]~^ ERROR not yet stable as a const fn
-    // ^ fails, because the `foo` feature is not active
+    //[stable]~^ cannot be (indirectly) exposed to stable
+    // We get the error on `stable` since this is a trait function.
+    Unstable2::func();
+    //~^ ERROR not yet stable as a const fn
+    // ^ fails, because the `unstable2` feature is not active
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "cheese", since = "1.0.0")]
 const fn stable_const_context() {
     Unstable::func();
-    //~^ ERROR not yet stable as a const fn
+    //[unstable]~^ ERROR cannot use `#[feature(unstable)]`
+    //[stable]~^^ ERROR not yet stable as a const fn
     Foo::func();
-    //[unstable]~^ ERROR not yet stable as a const fn
+    //[unstable]~^ ERROR cannot use `#[feature(local_feature)]`
+    //[stable]~^^ cannot be (indirectly) exposed to stable
+    // We get the error on `stable` since this is a trait function.
     const_context_not_const_stable()
-    //[unstable]~^ ERROR not yet stable as a const fn
+    //[unstable]~^ ERROR cannot use `#[feature(local_feature)]`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/const-traits/staged-api.stable.stderr b/tests/ui/traits/const-traits/staged-api.stable.stderr
index 6c07a253f5b..40045081f93 100644
--- a/tests/ui/traits/const-traits/staged-api.stable.stderr
+++ b/tests/ui/traits/const-traits/staged-api.stable.stderr
@@ -1,5 +1,5 @@
 error: trait implementations cannot be const stable yet
-  --> $DIR/staged-api.rs:21:1
+  --> $DIR/staged-api.rs:22:1
    |
 LL | / impl const MyTrait for Foo {
 LL | |
@@ -10,40 +10,80 @@ LL | | }
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
 
 error: function has missing const stability attribute
-  --> $DIR/staged-api.rs:43:1
+  --> $DIR/staged-api.rs:49:1
    |
 LL | / pub const fn const_context_not_const_stable() {
 LL | |
 LL | |     Unstable::func();
 LL | |
 ...  |
-LL | |     // ^ fails, because the `foo` feature is not active
+LL | |     // ^ fails, because the `unstable2` feature is not active
 LL | | }
    | |_^
 
 error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:34:5
+  --> $DIR/staged-api.rs:35:5
    |
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(unstable)]` to the crate attributes to enable
 
+error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable
+  --> $DIR/staged-api.rs:38:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
+
+error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:42:5
+   |
+LL |     Unstable2::func();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable2)]` to the crate attributes to enable
+
 error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:45:5
+  --> $DIR/staged-api.rs:51:5
    |
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(unstable)]` to the crate attributes to enable
 
+error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable
+  --> $DIR/staged-api.rs:53:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
+
+error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:56:5
+   |
+LL |     Unstable2::func();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable2)]` to the crate attributes to enable
+
 error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:55:5
+  --> $DIR/staged-api.rs:64:5
    |
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: add `#![feature(unstable)]` to the crate attributes to enable
+
+error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable
+  --> $DIR/staged-api.rs:67:5
+   |
+LL |     Foo::func();
+   |     ^^^^^^^^^^^
+   |
+   = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
 
-error: aborting due to 5 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/traits/const-traits/staged-api.unstable.stderr b/tests/ui/traits/const-traits/staged-api.unstable.stderr
index 1c772f13dd5..64b3a8ab19f 100644
--- a/tests/ui/traits/const-traits/staged-api.unstable.stderr
+++ b/tests/ui/traits/const-traits/staged-api.unstable.stderr
@@ -1,42 +1,108 @@
-error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:36:5
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
+  --> $DIR/staged-api.rs:35:5
    |
-LL |     Foo::func();
-   |     ^^^^^^^^^^^
+LL |     Unstable::func();
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn const_context() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(unstable)]
+LL | const fn const_context() {
    |
-   = help: add `#![feature(foo)]` to the crate attributes to enable
 
-error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:47:5
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
+  --> $DIR/staged-api.rs:38:5
    |
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-   = help: add `#![feature(foo)]` to the crate attributes to enable
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn const_context() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(local_feature)]
+LL | const fn const_context() {
+   |
+
+error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:42:5
+   |
+LL |     Unstable2::func();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable2)]` to the crate attributes to enable
 
-error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:55:5
+error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
+  --> $DIR/staged-api.rs:56:5
+   |
+LL |     Unstable2::func();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable2)]` to the crate attributes to enable
+
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
+  --> $DIR/staged-api.rs:64:5
    |
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn stable_const_context() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(unstable)]
+LL | const fn stable_const_context() {
+   |
 
-error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:57:5
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
+  --> $DIR/staged-api.rs:67:5
    |
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn stable_const_context() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(local_feature)]
+LL | const fn stable_const_context() {
+   |
 
-error: `const_context_not_const_stable` is not yet stable as a const fn
-  --> $DIR/staged-api.rs:59:5
+error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
+  --> $DIR/staged-api.rs:71:5
    |
 LL |     const_context_not_const_stable()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: const-stable functions can only call other const-stable functions
+   = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+   |
+LL + #[rustc_const_unstable(feature = "...", issue = "...")]
+LL | const fn stable_const_context() {
+   |
+help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+   |
+LL + #[rustc_allow_const_fn_unstable(local_feature)]
+LL | const fn stable_const_context() {
+   |
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors