Skip to content

Commit d2ff6a2

Browse files
committed
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.
1 parent 2348c06 commit d2ff6a2

38 files changed

+252
-146
lines changed

alloc/src/raw_vec.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl<T> RawVec<T, Global> {
103103
/// `RawVec` with capacity `usize::MAX`. Useful for implementing
104104
/// delayed allocation.
105105
#[must_use]
106-
#[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
106+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))]
107107
pub const fn new() -> Self {
108108
Self::new_in(Global)
109109
}
@@ -179,7 +179,7 @@ impl<T, A: Allocator> RawVec<T, A> {
179179
/// Like `new`, but parameterized over the choice of allocator for
180180
/// the returned `RawVec`.
181181
#[inline]
182-
#[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
182+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))]
183183
pub const fn new_in(alloc: A) -> Self {
184184
Self { inner: RawVecInner::new_in(alloc, align_of::<T>()), _marker: PhantomData }
185185
}
@@ -409,7 +409,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
409409

410410
impl<A: Allocator> RawVecInner<A> {
411411
#[inline]
412-
#[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
412+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))]
413413
const fn new_in(alloc: A, align: usize) -> Self {
414414
let ptr = unsafe { core::mem::transmute(align) };
415415
// `cap: 0` means "unallocated". zero-sized types are ignored.

core/src/alloc/layout.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ impl Layout {
6666
#[stable(feature = "alloc_layout", since = "1.28.0")]
6767
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
6868
#[inline]
69-
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
7069
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
7170
if Layout::is_size_align_valid(size, align) {
7271
// SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
@@ -127,7 +126,6 @@ impl Layout {
127126
#[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
128127
#[must_use]
129128
#[inline]
130-
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
131129
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
132130
assert_unsafe_precondition!(
133131
check_library_ub,
@@ -159,7 +157,7 @@ impl Layout {
159157
#[must_use = "this returns the minimum alignment, \
160158
without modifying the layout"]
161159
#[inline]
162-
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
160+
#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(ptr_alignment_type))]
163161
pub const fn align(&self) -> usize {
164162
self.align.as_usize()
165163
}

core/src/cell.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2287,6 +2287,7 @@ impl<T> SyncUnsafeCell<T> {
22872287

22882288
/// Unwraps the value, consuming the cell.
22892289
#[inline]
2290+
#[rustc_const_unstable(feature = "sync_unsafe_cell", issue = "95439")]
22902291
pub const fn into_inner(self) -> T {
22912292
self.value.into_inner()
22922293
}

core/src/cell/lazy.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
7979
/// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
8080
/// ```
8181
#[unstable(feature = "lazy_cell_into_inner", issue = "125623")]
82+
#[rustc_const_unstable(feature = "lazy_cell_into_inner", issue = "125623")]
8283
pub const fn into_inner(this: Self) -> Result<T, F> {
8384
match this.state.into_inner() {
8485
State::Init(data) => Ok(data),

core/src/char/methods.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,7 @@ const fn len_utf16(code: u32) -> usize {
17701770
/// Panics if the buffer is not large enough.
17711771
/// A buffer of length four is large enough to encode any `char`.
17721772
#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
1773-
#[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")]
1773+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0"))]
17741774
#[doc(hidden)]
17751775
#[inline]
17761776
#[rustc_allow_const_fn_unstable(const_eval_select)]

core/src/ffi/c_str.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ enum FromBytesWithNulErrorKind {
137137

138138
// FIXME: const stability attributes should not be required here, I think
139139
impl FromBytesWithNulError {
140-
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
140+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
141141
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
142142
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
143143
}
144-
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
144+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
145145
const fn not_nul_terminated() -> FromBytesWithNulError {
146146
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
147147
}
@@ -730,7 +730,7 @@ impl AsRef<CStr> for CStr {
730730
/// located within `isize::MAX` from `ptr`.
731731
#[inline]
732732
#[unstable(feature = "cstr_internals", issue = "none")]
733-
#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
733+
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))]
734734
#[rustc_allow_const_fn_unstable(const_eval_select)]
735735
const unsafe fn strlen(ptr: *const c_char) -> usize {
736736
const fn strlen_ct(s: *const c_char) -> usize {

core/src/fmt/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,10 @@ pub struct Arguments<'a> {
333333
#[unstable(feature = "fmt_internals", issue = "none")]
334334
impl<'a> Arguments<'a> {
335335
#[inline]
336-
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
336+
#[cfg_attr(
337+
bootstrap,
338+
rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")
339+
)]
337340
pub const fn new_const<const N: usize>(pieces: &'a [&'static str; N]) -> Self {
338341
const { assert!(N <= 1) };
339342
Arguments { pieces, fmt: None, args: &[] }
@@ -438,6 +441,7 @@ impl<'a> Arguments<'a> {
438441
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
439442
#[must_use]
440443
#[inline]
444+
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
441445
pub const fn as_str(&self) -> Option<&'static str> {
442446
match (self.pieces, self.args) {
443447
([], []) => Some(""),

core/src/hint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ pub const fn black_box<T>(dummy: T) -> T {
506506
/// # }
507507
/// ```
508508
#[unstable(feature = "hint_must_use", issue = "94745")]
509-
#[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
509+
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "hint_must_use", issue = "94745"))]
510510
#[must_use] // <-- :)
511511
#[inline(always)]
512512
pub const fn must_use<T>(value: T) -> T {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy