about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/messages.ftl
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 /compiler/rustc_const_eval/messages.ftl
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 'compiler/rustc_const_eval/messages.ftl')
-rw-r--r--compiler/rustc_const_eval/messages.ftl27
1 files changed, 20 insertions, 7 deletions
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 24dbe688f36..3e4f83c8242 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -41,8 +41,6 @@ const_eval_const_context = {$kind ->
     *[other] {""}
 }
 
-const_eval_const_stable = const-stable functions can only call other const-stable functions
-
 const_eval_copy_nonoverlapping_overlapping =
     `copy_nonoverlapping` called on overlapping ranges
 
@@ -259,6 +257,9 @@ const_eval_non_const_fn_call =
 const_eval_non_const_impl =
     impl defined here, but it is not `const`
 
+const_eval_non_const_intrinsic =
+    cannot call non-const intrinsic `{$name}` in {const_eval_const_context}s
+
 const_eval_not_enough_caller_args =
     calling a function with fewer arguments than it requires
 
@@ -397,17 +398,29 @@ const_eval_uninhabited_enum_variant_read =
     read discriminant of an uninhabited enum variant
 const_eval_uninhabited_enum_variant_written =
     writing discriminant of an uninhabited enum variant
+
+const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
+    .help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
+const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
+    .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
+
 const_eval_unreachable = entering unreachable code
 const_eval_unreachable_unwind =
     unwinding past a stack frame that does not allow unwinding
 
 const_eval_unsized_local = unsized locals are not supported
 const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
-
-const_eval_unstable_in_stable =
-    const-stable function cannot use `#[feature({$gate})]`
-    .unstable_sugg = if the function is not (yet) meant to be stable, make this function unstably const
-    .bypass_sugg = otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval)
+const_eval_unstable_in_stable_exposed =
+    const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]`
+    .is_function_call = mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
+    .unstable_sugg = if the {$is_function_call2 ->
+            [true] caller
+            *[false] function
+        } is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+    .bypass_sugg = otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+
+const_eval_unstable_intrinsic = `{$name}` is not yet stable as a const intrinsic
+    .help = add `#![feature({$feature})]` to the crate attributes to enable
 
 const_eval_unterminated_c_string =
     reading a null-terminated string starting at {$pointer} with no null found before end of allocation