rust/compiler
bors 54761cb3e8 Auto merge of #131349 - RalfJung:const-stability-checks, r=compiler-errors
Const stability checks v2

The const stability system has served us well ever since `const fn` were first stabilized. It's main feature is that it enforces *recursive* validity -- a stable const fn cannot internally make use of unstable const features without an explicit marker in the form of `#[rustc_allow_const_fn_unstable]`. This is done to make sure that we don't accidentally expose unstable const features on stable in a way that would be hard to take back. As part of this, it is enforced that a `#[rustc_const_stable]` can only call `#[rustc_const_stable]` functions. However, some problems have been coming up with increased usage:
- It is baffling that we have to mark private or even unstable functions as `#[rustc_const_stable]` when they are used as helpers in regular stable `const fn`, and often people will rather add `#[rustc_allow_const_fn_unstable]` instead which was not our intention.
- The system has several gaping holes: a private `const fn` without stability attributes whose inherited stability (walking up parent modules) is `#[stable]` is allowed to call *arbitrary* unstable const operations, but can itself be called from stable `const fn`. Similarly, `#[allow_internal_unstable]` on a macro completely bypasses the recursive nature of the check.

Fundamentally, the problem is that we have *three* disjoint categories of functions, and not enough attributes to distinguish them:
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

Functions in the first two categories cannot use unstable const features and they can only call functions from the first two categories.

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, all the holes mentioned above have been 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 be manually marked `#[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.

Also see the updated dev-guide at https://github.com/rust-lang/rustc-dev-guide/pull/2098.

I think in the future we may want to tweak this further, so that in the hopefully common case where a public function's const-stability just exactly mirrors its regular stability, we never have to add any attribute. But right now, once the function is stable this requires `#[rustc_const_stable]`.

### Open question

There is one point I could see we might want to do differently, and that is putting `#[rustc_const_unstable]`  functions (but not intrinsics) in category 2 by default, and requiring an extra attribute for `#[rustc_const_not_exposed_on_stable]` or so. This would require a bunch of extra annotations, but would have the advantage that turning a `#[rustc_const_unstable]` into `#[rustc_const_stable]`  will never change the way the function is const-checked. Currently, we often discover in the const stabilization PR that a function needs some other unstable const things, and then we rush to quickly deal with that. In this alternative universe, we'd work towards getting rid of the `rustc_const_not_exposed_on_stable` before stabilization, and once that is done stabilization becomes a trivial matter. `#[rustc_const_stable_indirect]` would then only be used for intrinsics.

I think I like this idea, but might want to do it in a follow-up PR, as it will need a whole bunch of annotations in the standard library. Also, we probably want to convert all const intrinsics to the "new" form (`#[rustc_intrinsic]` instead of an `extern` block) before doing this to avoid having to deal with two different ways of declaring intrinsics.

Cc `@rust-lang/wg-const-eval` `@rust-lang/libs-api`
Part of https://github.com/rust-lang/rust/issues/129815 (but not finished since this is not yet sufficient to safely let us expose `const fn` from hashbrown)
Fixes https://github.com/rust-lang/rust/issues/131073 by making it so that const-stable functions are always stable

try-job: test-various
2024-10-25 23:29:40 +00:00
..
rustc disable size asserts in the compiler when randomizing layouts 2024-08-31 23:56:45 +02:00
rustc_abi Make rustc_abi compile on stable again 2024-10-21 15:11:20 +02:00
rustc_arena move strict provenance lints to new feature gate, remove old feature gates 2024-10-21 15:22:17 +01:00
rustc_ast Rollup merge of #132106 - maxcabrajac:ident_ref, r=petrochenkov 2024-10-25 20:33:11 +02:00
rustc_ast_ir Add sugar for &pin (const|mut) types 2024-10-07 11:15:04 -07:00
rustc_ast_lowering Remove associated type based effects logic 2024-10-24 09:46:36 +00:00
rustc_ast_passes Pass Ident by reference in ast Visitor 2024-10-24 11:10:49 -03:00
rustc_ast_pretty Print safety correctly in extern static items 2024-10-24 00:41:27 +00:00
rustc_attr Re-do recursive const stability checks 2024-10-25 20:31:40 +02:00
rustc_baked_icu_data Don't add warn(unreachable_pub) to rustc_baked_icu. 2024-08-16 08:46:52 +10:00
rustc_borrowck Rollup merge of #131756 - compiler-errors:deeply-normalize-type-err, r=lcnr 2024-10-24 14:19:55 +11:00
rustc_builtin_macros Auto merge of #131349 - RalfJung:const-stability-checks, r=compiler-errors 2024-10-25 23:29:40 +00:00
rustc_codegen_cranelift Re-do recursive const stability checks 2024-10-25 20:31:40 +02:00
rustc_codegen_gcc coverage: SSA doesn't need to know about instrprof_increment 2024-10-25 14:24:05 +11:00
rustc_codegen_llvm coverage: SSA doesn't need to know about instrprof_increment 2024-10-25 14:24:05 +11:00
rustc_codegen_ssa coverage: SSA doesn't need to know about instrprof_increment 2024-10-25 14:24:05 +11:00
rustc_const_eval tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_data_structures Replace an FTP link in comments with an equivalent HTTPS link 2024-10-24 17:02:11 +11:00
rustc_driver
rustc_driver_impl Rollup merge of #130899 - bjorn3:wasi_bootstrap_fixes, r=davidtwco 2024-10-07 11:10:53 -07:00
rustc_error_codes terminology: #[feature] *enables* a feature (instead of "declaring" or "activating" it) 2024-10-22 07:37:54 +01:00
rustc_error_messages Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
rustc_errors "innermost", "outermost", "leftmost", and "rightmost" don't need hyphens 2024-10-23 02:45:24 -07:00
rustc_expand Re-do recursive const stability checks 2024-10-25 20:31:40 +02:00
rustc_feature Re-do recursive const stability checks 2024-10-25 20:31:40 +02:00
rustc_fluent_macro use tracked_path in rustc_fluent_macro 2024-10-19 22:32:38 +08:00
rustc_fs_util Couple of changes to make it easier to compile rustc for wasm 2024-09-26 19:51:14 +00:00
rustc_graphviz Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
rustc_hir Remove associated type based effects logic 2024-10-24 09:46:36 +00:00
rustc_hir_analysis tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_hir_pretty Remove associated type based effects logic 2024-10-24 09:46:36 +00:00
rustc_hir_typeck tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_incremental nightly feature tracking: get rid of the per-feature bool fields 2024-10-23 09:14:41 +01:00
rustc_index Rollup merge of #130625 - heiseish:issue-124028-fix, r=jieyouxu 2024-10-10 12:49:18 +02:00
rustc_index_macros Remove 'apostrophes' from rustc_parse_format 2024-10-14 23:22:51 +02:00
rustc_infer Implement const effect predicate in new solver 2024-10-24 09:46:36 +00:00
rustc_interface rust_for_linux: -Zregparm=<N> commandline flag for X86 (#116972) 2024-10-18 00:29:31 +07:00
rustc_lexer Reserve guarded string literals (RFC 3593) 2024-10-08 18:21:16 -06:00
rustc_lint Rollup merge of #132106 - maxcabrajac:ident_ref, r=petrochenkov 2024-10-25 20:33:11 +02:00
rustc_lint_defs Auto merge of #127731 - veluca93:abi_checks, r=RalfJung 2024-10-25 15:17:47 +00:00
rustc_llvm coverage: Emit MC/DC intrinsics using the normal helper method 2024-10-25 14:01:36 +11:00
rustc_log Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
rustc_macros Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
rustc_metadata tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_middle tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_mir_build Rollup merge of #129248 - compiler-errors:raw-ref-deref, r=nnethercote 2024-10-24 10:35:39 +02:00
rustc_mir_dataflow "innermost", "outermost", "leftmost", and "rightmost" don't need hyphens 2024-10-23 02:45:24 -07:00
rustc_mir_transform tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_monomorphize Auto merge of #127731 - veluca93:abi_checks, r=RalfJung 2024-10-25 15:17:47 +00:00
rustc_next_trait_solver Add support for ~const item bounds 2024-10-24 23:43:31 +00:00
rustc_parse "innermost", "outermost", "leftmost", and "rightmost" don't need hyphens 2024-10-23 02:45:24 -07:00
rustc_parse_format Remove 'apostrophes' from rustc_parse_format 2024-10-14 23:22:51 +02:00
rustc_passes tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_pattern_analysis nightly feature tracking: get rid of the per-feature bool fields 2024-10-23 09:14:41 +01:00
rustc_privacy Implement const effect predicate in new solver 2024-10-24 09:46:36 +00:00
rustc_query_impl Handle rustc_query_impl cases of rustc::potential_query_instability lint 2024-10-03 12:47:08 +03:00
rustc_query_system stop hashing compile-time constant 2024-10-23 19:46:52 +02:00
rustc_resolve Pass Ident by reference in ast Visitor 2024-10-24 11:10:49 -03:00
rustc_sanitizers Rollup merge of #131049 - compiler-errors:more-validation, r=spastorino 2024-10-22 15:28:38 +02:00
rustc_serialize Fix explicit_iter_loop in rustc_serialize 2024-10-16 15:44:16 +02:00
rustc_session Limited -Zregparm support (no Rust calling conv) descriptions 2024-10-20 18:18:01 +07:00
rustc_smir Implement const effect predicate in new solver 2024-10-24 09:46:36 +00:00
rustc_span Re-do recursive const stability checks 2024-10-25 20:31:40 +02:00
rustc_symbol_mangling nightly feature tracking: get rid of the per-feature bool fields 2024-10-23 09:14:41 +01:00
rustc_target Auto merge of #127731 - veluca93:abi_checks, r=RalfJung 2024-10-25 15:17:47 +00:00
rustc_trait_selection tcx.is_const_fn doesn't work the way it is described, remove it 2024-10-25 20:52:39 +02:00
rustc_traits Implement const effect predicate in new solver 2024-10-24 09:46:36 +00:00
rustc_transmute Fix transmute goal 2024-10-19 18:07:35 +00:00
rustc_ty_utils Be better at enforcing that const_conditions is only called on const items 2024-10-24 09:46:36 +00:00
rustc_type_ir Implement const effect predicate in new solver 2024-10-24 09:46:36 +00:00
rustc_type_ir_macros do not relate Abi and Safety 2024-10-22 23:13:04 +02:00
stable_mir Rollup merge of #132085 - celinval:update-smir-doc, r=compiler-errors 2024-10-24 23:23:55 -07:00