about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2023-09-28 01:57:01 -0400
committerTrevor Gross <tmgross@umich.edu>2023-11-04 15:27:25 -0400
commitf6ce646d3f840181dcc3f5d9edc4e4cff0051b78 (patch)
tree6a4a134859db156b7edadce12e8f5256d2f17461
parent2ba4eb2d49e774b5fbc2a06258ac7b0f60b92b7e (diff)
downloadrust-f6ce646d3f840181dcc3f5d9edc4e4cff0051b78.tar.gz
rust-f6ce646d3f840181dcc3f5d9edc4e4cff0051b78.zip
Stabilize `const_maybe_uninit_zeroed`
Make `MaybeUninit::zeroed` const stable. Newly stable API:

    // core::mem
    impl<T> MaybeUninit<T> {
        pub const fn zeroed() -> MaybeUninit<T>;
    }

Use of `const_mut_refs` should be acceptable since we do not leak the
mutability.

Tracking issue: #91850
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/core/src/mem/maybe_uninit.rs17
-rw-r--r--library/core/tests/mem.rs21
3 files changed, 32 insertions, 7 deletions
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index f435f503fc1..5b7062dec7a 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -113,7 +113,6 @@
 #![feature(const_eval_select)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_write)]
-#![feature(const_maybe_uninit_zeroed)]
 #![feature(const_pin)]
 #![feature(const_refs_to_cell)]
 #![feature(const_size_of_val)]
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index d09a24b4b1d..a86ccaeb839 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -374,6 +374,9 @@ impl<T> MaybeUninit<T> {
     /// assert_eq!(x, (0, false));
     /// ```
     ///
+    /// This can be used in const contexts, such as to indicate the end of static arrays for
+    /// plugin registration.
+    ///
     /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()`
     /// when `0` is not a valid bit-pattern for the type:
     ///
@@ -387,17 +390,19 @@ impl<T> MaybeUninit<T> {
     /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
     /// // This is undefined behavior. ⚠️
     /// ```
-    #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_zeroed", issue = "91850")]
-    #[must_use]
     #[inline]
+    #[must_use]
     #[rustc_diagnostic_item = "maybe_uninit_zeroed"]
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
+    // These are OK to allow since we do not leak &mut to user-visible API
+    #[rustc_allow_const_fn_unstable(const_mut_refs)]
+    #[rustc_allow_const_fn_unstable(const_ptr_write)]
+    #[rustc_allow_const_fn_unstable(const_maybe_uninit_as_mut_ptr)]
+    #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "CURRENT_RUSTC_VERSION")]
     pub const fn zeroed() -> MaybeUninit<T> {
         let mut u = MaybeUninit::<T>::uninit();
         // SAFETY: `u.as_mut_ptr()` points to allocated memory.
-        unsafe {
-            u.as_mut_ptr().write_bytes(0u8, 1);
-        }
+        unsafe { u.as_mut_ptr().write_bytes(0u8, 1) };
         u
     }
 
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 5c2e18745ea..20498b16cb2 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -565,3 +565,24 @@ fn offset_of_addr() {
     assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
     assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
 }
+
+#[test]
+fn const_maybe_uninit_zeroed() {
+    // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term)
+    #[repr(C)]
+    struct Foo {
+        a: Option<&'static str>,
+        b: Bar,
+        c: f32,
+        d: *const u8,
+    }
+    #[repr(C)]
+    struct Bar(usize);
+    struct FooPtr(*const Foo);
+    unsafe impl Sync for FooPtr {}
+
+    static UNINIT: FooPtr = FooPtr([unsafe { MaybeUninit::zeroed().assume_init() }].as_ptr());
+    const SIZE: usize = size_of::<Foo>();
+
+    assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]);
+}