about summary refs log tree commit diff
diff options
context:
space:
mode:
authorltdk <usr@ltdk.xyz>2024-08-18 19:50:41 -0400
committerltdk <usr@ltdk.xyz>2025-01-11 23:57:00 -0500
commite37daf0c868efc016dd8039d59d53a03303c9c07 (patch)
treeee333b0724e17a36f94ea7047a5251a9bc20a957
parent12445e0b2c532e389b8293924ed7c2b6fad5238f (diff)
downloadrust-e37daf0c868efc016dd8039d59d53a03303c9c07.tar.gz
rust-e37daf0c868efc016dd8039d59d53a03303c9c07.zip
Add inherent versions of MaybeUninit methods for slices
-rw-r--r--compiler/rustc_arena/src/lib.rs2
-rw-r--r--library/alloc/src/collections/btree/node.rs4
-rw-r--r--library/core/src/array/iter.rs8
-rw-r--r--library/core/src/array/mod.rs4
-rw-r--r--library/core/src/io/borrowed_buf.rs14
-rw-r--r--library/core/src/iter/adapters/filter_map.rs4
-rw-r--r--library/core/src/mem/maybe_uninit.rs564
-rw-r--r--library/core/src/net/display_buffer.rs4
-rw-r--r--library/core/src/num/flt2dec/mod.rs48
-rw-r--r--library/core/src/num/flt2dec/strategy/dragon.rs10
-rw-r--r--library/core/src/num/flt2dec/strategy/grisu.rs10
-rw-r--r--library/core/tests/mem.rs32
-rw-r--r--library/proc_macro/src/bridge/arena.rs2
-rw-r--r--library/std/src/ffi/os_str/tests.rs2
-rw-r--r--library/std/src/io/buffered/bufreader/buffer.rs2
-rw-r--r--library/std/src/path/tests.rs4
-rw-r--r--library/std/src/sys/pal/windows/mod.rs2
-rw-r--r--library/std/src/sys/pal/windows/stdio.rs6
18 files changed, 412 insertions, 310 deletions
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 4d8525989cc..b21ccba93bb 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -78,7 +78,7 @@ impl<T> ArenaChunk<T> {
             // been initialized.
             unsafe {
                 let slice = self.storage.as_mut();
-                ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
+                slice[..len].assume_init_drop();
             }
         }
     }
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index 0c93eff0d20..4057657632b 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -383,9 +383,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
     /// Borrows a view into the keys stored in the node.
     pub fn keys(&self) -> &[K] {
         let leaf = self.into_leaf();
-        unsafe {
-            MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len)))
-        }
+        unsafe { leaf.keys.get_unchecked(..usize::from(leaf.len)).assume_init_ref() }
     }
 }
 
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 9ce0eb61e08..1edade41597 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -214,7 +214,7 @@ impl<T, const N: usize> IntoIter<T, N> {
         // SAFETY: We know that all elements within `alive` are properly initialized.
         unsafe {
             let slice = self.data.get_unchecked(self.alive.clone());
-            MaybeUninit::slice_assume_init_ref(slice)
+            slice.assume_init_ref()
         }
     }
 
@@ -224,7 +224,7 @@ impl<T, const N: usize> IntoIter<T, N> {
         // SAFETY: We know that all elements within `alive` are properly initialized.
         unsafe {
             let slice = self.data.get_unchecked_mut(self.alive.clone());
-            MaybeUninit::slice_assume_init_mut(slice)
+            slice.assume_init_mut()
         }
     }
 }
@@ -285,7 +285,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
         // SAFETY: These elements are currently initialized, so it's fine to drop them.
         unsafe {
             let slice = self.data.get_unchecked_mut(range_to_drop);
-            ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
+            slice.assume_init_drop();
         }
 
         NonZero::new(remaining).map_or(Ok(()), Err)
@@ -340,7 +340,7 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
         // SAFETY: These elements are currently initialized, so it's fine to drop them.
         unsafe {
             let slice = self.data.get_unchecked_mut(range_to_drop);
-            ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
+            slice.assume_init_drop();
         }
 
         NonZero::new(remaining).map_or(Ok(()), Err)
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 95c1eb460cd..2ae5ded1fd5 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -911,9 +911,7 @@ impl<T> Drop for Guard<'_, T> {
 
         // SAFETY: this slice will contain only initialized objects.
         unsafe {
-            crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
-                self.array_mut.get_unchecked_mut(..self.initialized),
-            ));
+            self.array_mut.get_unchecked_mut(..self.initialized).assume_init_drop();
         }
     }
 }
diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs
index 4227e503ba7..f86abf7f1e9 100644
--- a/library/core/src/io/borrowed_buf.rs
+++ b/library/core/src/io/borrowed_buf.rs
@@ -94,7 +94,7 @@ impl<'data> BorrowedBuf<'data> {
         // SAFETY: We only slice the filled part of the buffer, which is always valid
         unsafe {
             let buf = self.buf.get_unchecked(..self.filled);
-            MaybeUninit::slice_assume_init_ref(buf)
+            buf.assume_init_ref()
         }
     }
 
@@ -104,7 +104,7 @@ impl<'data> BorrowedBuf<'data> {
         // SAFETY: We only slice the filled part of the buffer, which is always valid
         unsafe {
             let buf = self.buf.get_unchecked_mut(..self.filled);
-            MaybeUninit::slice_assume_init_mut(buf)
+            buf.assume_init_mut()
         }
     }
 
@@ -114,7 +114,7 @@ impl<'data> BorrowedBuf<'data> {
         // SAFETY: We only slice the filled part of the buffer, which is always valid
         unsafe {
             let buf = self.buf.get_unchecked(..self.filled);
-            MaybeUninit::slice_assume_init_ref(buf)
+            buf.assume_init_ref()
         }
     }
 
@@ -124,7 +124,7 @@ impl<'data> BorrowedBuf<'data> {
         // SAFETY: We only slice the filled part of the buffer, which is always valid
         unsafe {
             let buf = self.buf.get_unchecked_mut(..self.filled);
-            MaybeUninit::slice_assume_init_mut(buf)
+            buf.assume_init_mut()
         }
     }
 
@@ -233,7 +233,7 @@ impl<'a> BorrowedCursor<'a> {
         // SAFETY: We only slice the initialized part of the buffer, which is always valid
         unsafe {
             let buf = self.buf.buf.get_unchecked(self.buf.filled..self.buf.init);
-            MaybeUninit::slice_assume_init_ref(buf)
+            buf.assume_init_ref()
         }
     }
 
@@ -243,7 +243,7 @@ impl<'a> BorrowedCursor<'a> {
         // SAFETY: We only slice the initialized part of the buffer, which is always valid
         unsafe {
             let buf = self.buf.buf.get_unchecked_mut(self.buf.filled..self.buf.init);
-            MaybeUninit::slice_assume_init_mut(buf)
+            buf.assume_init_mut()
         }
     }
 
@@ -344,7 +344,7 @@ impl<'a> BorrowedCursor<'a> {
 
         // SAFETY: we do not de-initialize any of the elements of the slice
         unsafe {
-            MaybeUninit::copy_from_slice(&mut self.as_mut()[..buf.len()], buf);
+            self.as_mut()[..buf.len()].write_copy_of_slice(buf);
         }
 
         // SAFETY: We just added the entire contents of buf to the filled section.
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index cc64ceb13f7..24ec6b1741c 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -81,9 +81,7 @@ where
                 if const { crate::mem::needs_drop::<T>() } {
                     // SAFETY: self.initialized is always <= N, which also is the length of the array.
                     unsafe {
-                        core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
-                            self.array.get_unchecked_mut(..self.initialized),
-                        ));
+                        self.array.get_unchecked_mut(..self.initialized).assume_init_drop();
                     }
                 }
             }
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 284a58c7278..ac5307a671d 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -1,5 +1,5 @@
 use crate::any::type_name;
-use crate::mem::{self, ManuallyDrop};
+use crate::mem::ManuallyDrop;
 use crate::{fmt, intrinsics, ptr, slice};
 
 /// A wrapper type to construct uninitialized instances of `T`.
@@ -354,7 +354,7 @@ impl<T> MaybeUninit<T> {
     /// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] {
     ///     unsafe {
     ///         let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len());
-    ///         MaybeUninit::slice_assume_init_ref(&buf[..len])
+    ///         buf[..len].assume_init_ref()
     ///     }
     /// }
     ///
@@ -740,7 +740,7 @@ impl<T> MaybeUninit<T> {
     ///
     /// On top of that, all additional invariants of the type `T` must be
     /// satisfied, as the `Drop` implementation of `T` (or its members) may
-    /// rely on this. For example, setting a [`Vec<T>`] to an invalid but
+    /// rely on this. For example, setting a `Vec<T>` to an invalid but
     /// non-null address makes it initialized (under the current implementation;
     /// this does not constitute a stable guarantee), because the only
     /// requirement the compiler knows about it is that the data pointer must be
@@ -748,7 +748,6 @@ impl<T> MaybeUninit<T> {
     /// behavior.
     ///
     /// [`assume_init`]: MaybeUninit::assume_init
-    /// [`Vec<T>`]: ../../std/vec/struct.Vec.html
     #[stable(feature = "maybe_uninit_extra", since = "1.60.0")]
     pub unsafe fn assume_init_drop(&mut self) {
         // SAFETY: the caller must guarantee that `self` is initialized and
@@ -982,44 +981,87 @@ impl<T> MaybeUninit<T> {
         }
     }
 
-    /// Assuming all the elements are initialized, get a slice to them.
+    /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
     ///
-    /// # Safety
+    /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
+    /// contain padding bytes which are left uninitialized.
     ///
-    /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
-    /// really are in an initialized state.
-    /// Calling this when the content is not yet fully initialized causes undefined behavior.
+    /// # Examples
     ///
-    /// See [`assume_init_ref`] for more details and examples.
+    /// ```
+    /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)]
+    /// use std::mem::MaybeUninit;
     ///
-    /// [`assume_init_ref`]: MaybeUninit::assume_init_ref
-    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
-    #[inline(always)]
-    pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
-        // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that
-        // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`.
-        // The pointer obtained is valid since it refers to memory owned by `slice` which is a
-        // reference and thus guaranteed to be valid for reads.
-        unsafe { &*(slice as *const [Self] as *const [T]) }
+    /// let val = 0x12345678_i32;
+    /// let uninit = MaybeUninit::new(val);
+    /// let uninit_bytes = uninit.as_bytes();
+    /// let bytes = unsafe { uninit_bytes.assume_init_ref() };
+    /// assert_eq!(bytes, val.to_ne_bytes());
+    /// ```
+    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
+    pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] {
+        // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
+        unsafe {
+            slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), super::size_of::<T>())
+        }
     }
 
-    /// Assuming all the elements are initialized, get a mutable slice to them.
+    /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized
+    /// bytes.
     ///
-    /// # Safety
+    /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
+    /// contain padding bytes which are left uninitialized.
     ///
-    /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
-    /// really are in an initialized state.
-    /// Calling this when the content is not yet fully initialized causes undefined behavior.
+    /// # Examples
     ///
-    /// See [`assume_init_mut`] for more details and examples.
+    /// ```
+    /// #![feature(maybe_uninit_as_bytes)]
+    /// use std::mem::MaybeUninit;
     ///
-    /// [`assume_init_mut`]: MaybeUninit::assume_init_mut
+    /// let val = 0x12345678_i32;
+    /// let mut uninit = MaybeUninit::new(val);
+    /// let uninit_bytes = uninit.as_bytes_mut();
+    /// if cfg!(target_endian = "little") {
+    ///     uninit_bytes[0].write(0xcd);
+    /// } else {
+    ///     uninit_bytes[3].write(0xcd);
+    /// }
+    /// let val2 = unsafe { uninit.assume_init() };
+    /// assert_eq!(val2, 0x123456cd);
+    /// ```
+    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
+    pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
+        // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
+        unsafe {
+            slice::from_raw_parts_mut(
+                self.as_mut_ptr().cast::<MaybeUninit<u8>>(),
+                super::size_of::<T>(),
+            )
+        }
+    }
+
+    /// Deprecated version of [`slice::assume_init_ref`].
     #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
-    #[inline(always)]
+    #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
+    #[deprecated(
+        note = "replaced by inherent assume_init_ref method; will eventually be removed",
+        since = "1.83.0"
+    )]
+    pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
+        // SAFETY: Same for both methods.
+        unsafe { slice.assume_init_ref() }
+    }
+
+    /// Deprecated version of [`slice::assume_init_mut`].
+    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
+    #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
+    #[deprecated(
+        note = "replaced by inherent assume_init_mut method; will eventually be removed",
+        since = "1.83.0"
+    )]
     pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
-        // SAFETY: similar to safety notes for `slice_get_ref`, but we have a
-        // mutable reference which is also guaranteed to be valid for writes.
-        unsafe { &mut *(slice as *mut [Self] as *mut [T]) }
+        // SAFETY: Same for both methods.
+        unsafe { slice.assume_init_mut() }
     }
 
     /// Gets a pointer to the first element of the array.
@@ -1036,142 +1078,34 @@ impl<T> MaybeUninit<T> {
         this.as_mut_ptr() as *mut T
     }
 
-    /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
-    ///
-    /// If `T` does not implement `Copy`, use [`clone_from_slice`]
-    ///
-    /// This is similar to [`slice::copy_from_slice`].
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(maybe_uninit_write_slice)]
-    /// use std::mem::MaybeUninit;
-    ///
-    /// let mut dst = [MaybeUninit::uninit(); 32];
-    /// let src = [0; 32];
-    ///
-    /// let init = MaybeUninit::copy_from_slice(&mut dst, &src);
-    ///
-    /// assert_eq!(init, src);
-    /// ```
-    ///
-    /// ```
-    /// #![feature(maybe_uninit_write_slice)]
-    /// use std::mem::MaybeUninit;
-    ///
-    /// let mut vec = Vec::with_capacity(32);
-    /// let src = [0; 16];
-    ///
-    /// MaybeUninit::copy_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src);
-    ///
-    /// // SAFETY: we have just copied all the elements of len into the spare capacity
-    /// // the first src.len() elements of the vec are valid now.
-    /// unsafe {
-    ///     vec.set_len(src.len());
-    /// }
-    ///
-    /// assert_eq!(vec, src);
-    /// ```
-    ///
-    /// [`clone_from_slice`]: MaybeUninit::clone_from_slice
+    /// Deprecated version of [`slice::write_copy_of_slice`].
     #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
+    #[deprecated(
+        note = "replaced by inherent write_copy_of_slice method; will eventually be removed",
+        since = "1.83.0"
+    )]
     pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
     where
         T: Copy,
     {
-        // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
-        let uninit_src: &[MaybeUninit<T>] = unsafe { super::transmute(src) };
-
-        this.copy_from_slice(uninit_src);
-
-        // SAFETY: Valid elements have just been copied into `this` so it is initialized
-        unsafe { MaybeUninit::slice_assume_init_mut(this) }
+        this.write_copy_of_slice(src)
     }
 
-    /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
-    /// Any already initialized elements will not be dropped.
-    ///
-    /// If `T` implements `Copy`, use [`copy_from_slice`]
-    ///
-    /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
-    ///
-    /// If there is a panic, the already cloned elements will be dropped.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(maybe_uninit_write_slice)]
-    /// use std::mem::MaybeUninit;
-    ///
-    /// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()];
-    /// let src = ["wibbly".to_string(), "wobbly".to_string(), "timey".to_string(), "wimey".to_string(), "stuff".to_string()];
-    ///
-    /// let init = MaybeUninit::clone_from_slice(&mut dst, &src);
-    ///
-    /// assert_eq!(init, src);
-    /// # // Prevent leaks for Miri
-    /// # unsafe { std::ptr::drop_in_place(init); }
-    /// ```
-    ///
-    /// ```
-    /// #![feature(maybe_uninit_write_slice)]
-    /// use std::mem::MaybeUninit;
-    ///
-    /// let mut vec = Vec::with_capacity(32);
-    /// let src = ["rust", "is", "a", "pretty", "cool", "language"];
-    ///
-    /// MaybeUninit::clone_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src);
-    ///
-    /// // SAFETY: we have just cloned all the elements of len into the spare capacity
-    /// // the first src.len() elements of the vec are valid now.
-    /// unsafe {
-    ///     vec.set_len(src.len());
-    /// }
-    ///
-    /// assert_eq!(vec, src);
-    /// ```
-    ///
-    /// [`copy_from_slice`]: MaybeUninit::copy_from_slice
+    /// Deprecated version of [`slice::write_clone_of_slice`].
     #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
+    #[deprecated(
+        note = "replaced by inherent write_clone_of_slice method; will eventually be removed",
+        since = "1.83.0"
+    )]
     pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
     where
         T: Clone,
     {
-        // unlike copy_from_slice this does not call clone_from_slice on the slice
-        // this is because `MaybeUninit<T: Clone>` does not implement Clone.
-
-        assert_eq!(this.len(), src.len(), "destination and source slices have different lengths");
-        // NOTE: We need to explicitly slice them to the same length
-        // for bounds checking to be elided, and the optimizer will
-        // generate memcpy for simple cases (for example T = u8).
-        let len = this.len();
-        let src = &src[..len];
-
-        // guard is needed b/c panic might happen during a clone
-        let mut guard = Guard { slice: this, initialized: 0 };
-
-        for i in 0..len {
-            guard.slice[i].write(src[i].clone());
-            guard.initialized += 1;
-        }
-
-        super::forget(guard);
-
-        // SAFETY: Valid elements have just been written into `this` so it is initialized
-        unsafe { MaybeUninit::slice_assume_init_mut(this) }
+        this.write_clone_of_slice(src)
     }
 
-    /// Fills `this` with elements by cloning `value`, returning a mutable reference to the now
-    /// initialized contents of `this`.
+    /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now
+    /// initialized contents of the slice.
     /// Any previously initialized elements will not be dropped.
     ///
     /// This is similar to [`slice::fill`].
@@ -1185,27 +1119,26 @@ impl<T> MaybeUninit<T> {
     ///
     /// # Examples
     ///
-    /// Fill an uninit vec with 1.
     /// ```
     /// #![feature(maybe_uninit_fill)]
     /// use std::mem::MaybeUninit;
     ///
-    /// let mut buf = vec![MaybeUninit::uninit(); 10];
-    /// let initialized = MaybeUninit::fill(buf.as_mut_slice(), 1);
+    /// let mut buf = [const { MaybeUninit::uninit() }; 10];
+    /// let initialized = MaybeUninit::fill(&mut buf, 1);
     /// assert_eq!(initialized, &mut [1; 10]);
     /// ```
     #[doc(alias = "memset")]
     #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
-    pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], value: T) -> &'a mut [T]
+    pub fn fill(this: &mut [MaybeUninit<T>], value: T) -> &mut [T]
     where
         T: Clone,
     {
         SpecFill::spec_fill(this, value);
         // SAFETY: Valid elements have just been filled into `this` so it is initialized
-        unsafe { MaybeUninit::slice_assume_init_mut(this) }
+        unsafe { this.assume_init_mut() }
     }
 
-    /// Fills `this` with elements returned by calling a closure repeatedly.
+    /// Fills a slice with elements returned by calling a closure repeatedly.
     ///
     /// This method uses a closure to create new values.  If you'd rather `Clone` a given value, use
     /// [`MaybeUninit::fill`].  If you want to use the `Default` trait to generate values, you can
@@ -1220,17 +1153,16 @@ impl<T> MaybeUninit<T> {
     ///
     /// # Examples
     ///
-    /// Fill an uninit vec with the default value.
     /// ```
     /// #![feature(maybe_uninit_fill)]
     /// use std::mem::MaybeUninit;
     ///
-    /// let mut buf = vec![MaybeUninit::<i32>::uninit(); 10];
-    /// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default);
+    /// let mut buf = [const { MaybeUninit::<i32>::uninit() }; 10];
+    /// let initialized = MaybeUninit::fill_with(&mut buf, Default::default);
     /// assert_eq!(initialized, &mut [0; 10]);
     /// ```
     #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
-    pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], mut f: F) -> &'a mut [T]
+    pub fn fill_with<F>(this: &mut [MaybeUninit<T>], mut f: F) -> &mut [T]
     where
         F: FnMut() -> T,
     {
@@ -1244,13 +1176,13 @@ impl<T> MaybeUninit<T> {
         super::forget(guard);
 
         // SAFETY: Valid elements have just been written into `this` so it is initialized
-        unsafe { MaybeUninit::slice_assume_init_mut(this) }
+        unsafe { this.assume_init_mut() }
     }
 
-    /// Fills `this` with elements yielded by an iterator until either all elements have been
+    /// Fills a slice with elements yielded by an iterator until either all elements have been
     /// initialized or the iterator is empty.
     ///
-    /// Returns two slices.  The first slice contains the initialized portion of the original slice.
+    /// Returns two slices. The first slice contains the initialized portion of the original slice.
     /// The second slice is the still-uninitialized remainder of the original slice.
     ///
     /// # Panics
@@ -1262,37 +1194,51 @@ impl<T> MaybeUninit<T> {
     ///
     /// # Examples
     ///
-    /// Fill an uninit vec with a cycling iterator.
+    /// Completely filling the slice:
+    ///
     /// ```
     /// #![feature(maybe_uninit_fill)]
     /// use std::mem::MaybeUninit;
     ///
-    /// let mut buf = vec![MaybeUninit::uninit(); 5];
+    /// let mut buf = [const { MaybeUninit::uninit() }; 5];
     ///
     /// let iter = [1, 2, 3].into_iter().cycle();
     /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter);
     ///
     /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]);
-    /// assert_eq!(0, remainder.len());
+    /// assert_eq!(remainder.len(), 0);
     /// ```
     ///
-    /// Fill an uninit vec, but not completely.
+    /// Partially filling the slice:
+    ///
     /// ```
     /// #![feature(maybe_uninit_fill)]
     /// use std::mem::MaybeUninit;
     ///
-    /// let mut buf = vec![MaybeUninit::uninit(); 5];
+    /// let mut buf = [const { MaybeUninit::uninit() }; 5];
     /// let iter = [1, 2];
     /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter);
     ///
     /// assert_eq!(initialized, &mut [1, 2]);
     /// assert_eq!(remainder.len(), 3);
     /// ```
+    ///
+    /// Checking an iterator after filling a slice:
+    ///
+    /// ```
+    /// #![feature(maybe_uninit_fill)]
+    /// use std::mem::MaybeUninit;
+    ///
+    /// let mut buf = [const { MaybeUninit::uninit() }; 3];
+    /// let mut iter = [1, 2, 3, 4, 5].into_iter();
+    /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter.by_ref());
+    ///
+    /// assert_eq!(initialized, &mut [1, 2, 3]);
+    /// assert_eq!(remainder.len(), 0);
+    /// assert_eq!(iter.as_slice(), &[4, 5]);
+    /// ```
     #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
-    pub fn fill_from<'a, I>(
-        this: &'a mut [MaybeUninit<T>],
-        it: I,
-    ) -> (&'a mut [T], &'a mut [MaybeUninit<T>])
+    pub fn fill_from<I>(this: &mut [MaybeUninit<T>], it: I) -> (&mut [T], &mut [MaybeUninit<T>])
     where
         I: IntoIterator<Item = T>,
     {
@@ -1312,70 +1258,169 @@ impl<T> MaybeUninit<T> {
 
         // SAFETY: Valid elements have just been written into `init`, so that portion
         // of `this` is initialized.
-        (unsafe { MaybeUninit::slice_assume_init_mut(initted) }, remainder)
+        (unsafe { initted.assume_init_mut() }, remainder)
     }
 
-    /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
+    /// Deprecated version of [`slice::as_bytes`].
+    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
+    #[deprecated(
+        note = "replaced by inherent as_bytes method; will eventually be removed",
+        since = "1.83.0"
+    )]
+    pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
+        this.as_bytes()
+    }
+
+    /// Deprecated version of [`slice::as_bytes_mut`].
+    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
+    #[deprecated(
+        note = "replaced by inherent as_bytes_mut method; will eventually be removed",
+        since = "1.83.0"
+    )]
+    pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
+        this.as_bytes_mut()
+    }
+}
+
+impl<T> [MaybeUninit<T>] {
+    /// Copies the elements from `src` to `self`,
+    /// returning a mutable reference to the now initialized contents of `self`.
     ///
-    /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
-    /// contain padding bytes which are left uninitialized.
+    /// If `T` does not implement `Copy`, use [`write_clone_of_slice`] instead.
+    ///
+    /// This is similar to [`slice::copy_from_slice`].
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)]
+    /// #![feature(maybe_uninit_write_slice)]
     /// use std::mem::MaybeUninit;
     ///
-    /// let val = 0x12345678_i32;
-    /// let uninit = MaybeUninit::new(val);
-    /// let uninit_bytes = uninit.as_bytes();
-    /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) };
-    /// assert_eq!(bytes, val.to_ne_bytes());
+    /// let mut dst = [MaybeUninit::uninit(); 32];
+    /// let src = [0; 32];
+    ///
+    /// let init = dst.write_copy_of_slice(&src);
+    ///
+    /// assert_eq!(init, src);
     /// ```
-    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
-    pub fn as_bytes(&self) -> &[MaybeUninit<u8>] {
-        // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
-        unsafe {
-            slice::from_raw_parts(self.as_ptr() as *const MaybeUninit<u8>, mem::size_of::<T>())
-        }
+    ///
+    /// ```
+    /// #![feature(maybe_uninit_write_slice)]
+    ///
+    /// let mut vec = Vec::with_capacity(32);
+    /// let src = [0; 16];
+    ///
+    /// vec.spare_capacity_mut()[..src.len()].write_copy_of_slice(&src);
+    ///
+    /// // SAFETY: we have just copied all the elements of len into the spare capacity
+    /// // the first src.len() elements of the vec are valid now.
+    /// unsafe {
+    ///     vec.set_len(src.len());
+    /// }
+    ///
+    /// assert_eq!(vec, src);
+    /// ```
+    ///
+    /// [`write_clone_of_slice`]: slice::write_clone_of_slice
+    #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
+    #[rustc_const_unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
+    pub const fn write_copy_of_slice(&mut self, src: &[T]) -> &mut [T]
+    where
+        T: Copy,
+    {
+        // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
+        let uninit_src: &[MaybeUninit<T>] = unsafe { super::transmute(src) };
+
+        self.copy_from_slice(uninit_src);
+
+        // SAFETY: Valid elements have just been copied into `self` so it is initialized
+        unsafe { self.assume_init_mut() }
     }
 
-    /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized
-    /// bytes.
+    /// Clones the elements from `src` to `self`,
+    /// returning a mutable reference to the now initialized contents of `self`.
+    /// Any already initialized elements will not be dropped.
     ///
-    /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
-    /// contain padding bytes which are left uninitialized.
+    /// If `T` implements `Copy`, use [`write_copy_of_slice`] instead.
+    ///
+    /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
+    ///
+    /// If there is a panic, the already cloned elements will be dropped.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(maybe_uninit_as_bytes)]
+    /// #![feature(maybe_uninit_write_slice)]
     /// use std::mem::MaybeUninit;
     ///
-    /// let val = 0x12345678_i32;
-    /// let mut uninit = MaybeUninit::new(val);
-    /// let uninit_bytes = uninit.as_bytes_mut();
-    /// if cfg!(target_endian = "little") {
-    ///     uninit_bytes[0].write(0xcd);
-    /// } else {
-    ///     uninit_bytes[3].write(0xcd);
+    /// let mut dst = [const { MaybeUninit::uninit() }; 5];
+    /// let src = ["wibbly", "wobbly", "timey", "wimey", "stuff"].map(|s| s.to_string());
+    ///
+    /// let init = dst.write_clone_of_slice(&src);
+    ///
+    /// assert_eq!(init, src);
+    ///
+    /// # // Prevent leaks for Miri
+    /// # unsafe { std::ptr::drop_in_place(init); }
+    /// ```
+    ///
+    /// ```
+    /// #![feature(maybe_uninit_write_slice)]
+    ///
+    /// let mut vec = Vec::with_capacity(32);
+    /// let src = ["rust", "is", "a", "pretty", "cool", "language"].map(|s| s.to_string());
+    ///
+    /// vec.spare_capacity_mut()[..src.len()].write_clone_of_slice(&src);
+    ///
+    /// // SAFETY: we have just cloned all the elements of len into the spare capacity
+    /// // the first src.len() elements of the vec are valid now.
+    /// unsafe {
+    ///     vec.set_len(src.len());
     /// }
-    /// let val2 = unsafe { uninit.assume_init() };
-    /// assert_eq!(val2, 0x123456cd);
+    ///
+    /// assert_eq!(vec, src);
     /// ```
-    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
-    pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
-        // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
-        unsafe {
-            slice::from_raw_parts_mut(
-                self.as_mut_ptr() as *mut MaybeUninit<u8>,
-                mem::size_of::<T>(),
-            )
+    ///
+    /// [`write_copy_of_slice`]: slice::write_copy_of_slice
+    #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
+    pub fn write_clone_of_slice(&mut self, src: &[T]) -> &mut [T]
+    where
+        T: Clone,
+    {
+        // unlike copy_from_slice this does not call clone_from_slice on the slice
+        // this is because `MaybeUninit<T: Clone>` does not implement Clone.
+
+        assert_eq!(self.len(), src.len(), "destination and source slices have different lengths");
+
+        // NOTE: We need to explicitly slice them to the same length
+        // for bounds checking to be elided, and the optimizer will
+        // generate memcpy for simple cases (for example T = u8).
+        let len = self.len();
+        let src = &src[..len];
+
+        // guard is needed b/c panic might happen during a clone
+        let mut guard = Guard { slice: self, initialized: 0 };
+
+        for i in 0..len {
+            guard.slice[i].write(src[i].clone());
+            guard.initialized += 1;
         }
+
+        super::forget(guard);
+
+        // SAFETY: Valid elements have just been written into `self` so it is initialized
+        unsafe { self.assume_init_mut() }
     }
 
-    /// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized
-    /// bytes.
+    /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
     ///
     /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
     /// contain padding bytes which are left uninitialized.
@@ -1387,21 +1432,22 @@ impl<T> MaybeUninit<T> {
     /// use std::mem::MaybeUninit;
     ///
     /// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)];
-    /// let uninit_bytes = MaybeUninit::slice_as_bytes(&uninit);
-    /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(&uninit_bytes) };
+    /// let uninit_bytes = uninit.as_bytes();
+    /// let bytes = unsafe { uninit_bytes.assume_init_ref() };
     /// let val1 = u16::from_ne_bytes(bytes[0..2].try_into().unwrap());
     /// let val2 = u16::from_ne_bytes(bytes[2..4].try_into().unwrap());
     /// assert_eq!(&[val1, val2], &[0x1234u16, 0x5678u16]);
     /// ```
     #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
-    pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
-        let bytes = mem::size_of_val(this);
+    pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] {
         // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
-        unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit<u8>, bytes) }
+        unsafe {
+            slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), super::size_of_val(self))
+        }
     }
 
-    /// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of
-    /// potentially uninitialized bytes.
+    /// Returns the contents of this `MaybeUninit` slice as a mutable slice of potentially
+    /// uninitialized bytes.
     ///
     /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
     /// contain padding bytes which are left uninitialized.
@@ -1414,8 +1460,8 @@ impl<T> MaybeUninit<T> {
     ///
     /// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
     /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
-    /// MaybeUninit::copy_from_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]);
-    /// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) };
+    /// uninit_bytes.write_copy_of_slice(&[0x12, 0x34, 0x56, 0x78]);
+    /// let vals = unsafe { uninit.assume_init_ref() };
     /// if cfg!(target_endian = "little") {
     ///     assert_eq!(vals, &[0x3412u16, 0x7856u16]);
     /// } else {
@@ -1423,10 +1469,74 @@ impl<T> MaybeUninit<T> {
     /// }
     /// ```
     #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
-    pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
-        let bytes = mem::size_of_val(this);
+    pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
         // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
-        unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit<u8>, bytes) }
+        unsafe {
+            slice::from_raw_parts_mut(
+                self.as_mut_ptr() as *mut MaybeUninit<u8>,
+                super::size_of_val(self),
+            )
+        }
+    }
+
+    /// Drops the contained values in place.
+    ///
+    /// # Safety
+    ///
+    /// It is up to the caller to guarantee that every `MaybeUninit<T>` in the slice
+    /// really is in an initialized state. Calling this when the content is not yet
+    /// fully initialized causes undefined behavior.
+    ///
+    /// On top of that, all additional invariants of the type `T` must be
+    /// satisfied, as the `Drop` implementation of `T` (or its members) may
+    /// rely on this. For example, setting a `Vec<T>` to an invalid but
+    /// non-null address makes it initialized (under the current implementation;
+    /// this does not constitute a stable guarantee), because the only
+    /// requirement the compiler knows about it is that the data pointer must be
+    /// non-null. Dropping such a `Vec<T>` however will cause undefined
+    /// behaviour.
+    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
+    #[inline(always)]
+    pub unsafe fn assume_init_drop(&mut self) {
+        if !self.is_empty() {
+            // SAFETY: the caller must guarantee that every element of `self`
+            // is initialized and satisfies all invariants of `T`.
+            // Dropping the value in place is safe if that is the case.
+            unsafe { ptr::drop_in_place(self as *mut [MaybeUninit<T>] as *mut [T]) }
+        }
+    }
+
+    /// Gets a shared reference to the contained value.
+    ///
+    /// # Safety
+    ///
+    /// Calling this when the content is not yet fully initialized causes undefined
+    /// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in
+    /// the slice really is in an initialized state.
+    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
+    #[inline(always)]
+    pub const unsafe fn assume_init_ref(&self) -> &[T] {
+        // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that
+        // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`.
+        // The pointer obtained is valid since it refers to memory owned by `slice` which is a
+        // reference and thus guaranteed to be valid for reads.
+        unsafe { &*(self as *const Self as *const [T]) }
+    }
+
+    /// Gets a mutable (unique) reference to the contained value.
+    ///
+    /// # Safety
+    ///
+    /// Calling this when the content is not yet fully initialized causes undefined
+    /// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in the
+    /// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot
+    /// be used to initialize a `MaybeUninit` slice.
+    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
+    #[inline(always)]
+    pub const unsafe fn assume_init_mut(&mut self) -> &mut [T] {
+        // SAFETY: similar to safety notes for `slice_get_ref`, but we have a
+        // mutable reference which is also guaranteed to be valid for writes.
+        unsafe { &mut *(self as *mut Self as *mut [T]) }
     }
 }
 
@@ -1479,7 +1589,7 @@ impl<'a, T> Drop for Guard<'a, T> {
         let initialized_part = &mut self.slice[..self.initialized];
         // SAFETY: this raw sub-slice will contain only initialized objects.
         unsafe {
-            crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part));
+            initialized_part.assume_init_drop();
         }
     }
 }
diff --git a/library/core/src/net/display_buffer.rs b/library/core/src/net/display_buffer.rs
index bab84a97308..a7d12217081 100644
--- a/library/core/src/net/display_buffer.rs
+++ b/library/core/src/net/display_buffer.rs
@@ -18,7 +18,7 @@ impl<const SIZE: usize> DisplayBuffer<SIZE> {
         // SAFETY: `buf` is only written to by the `fmt::Write::write_str` implementation
         // which writes a valid UTF-8 string to `buf` and correctly sets `len`.
         unsafe {
-            let s = MaybeUninit::slice_assume_init_ref(&self.buf[..self.len]);
+            let s = self.buf[..self.len].assume_init_ref();
             str::from_utf8_unchecked(s)
         }
     }
@@ -29,7 +29,7 @@ impl<const SIZE: usize> fmt::Write for DisplayBuffer<SIZE> {
         let bytes = s.as_bytes();
 
         if let Some(buf) = self.buf.get_mut(self.len..(self.len + bytes.len())) {
-            MaybeUninit::copy_from_slice(buf, bytes);
+            buf.write_copy_of_slice(bytes);
             self.len += bytes.len();
             Ok(())
         } else {
diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs
index d6413fadc33..7601e3e2c58 100644
--- a/library/core/src/num/flt2dec/mod.rs
+++ b/library/core/src/num/flt2dec/mod.rs
@@ -210,10 +210,10 @@ fn digits_to_dec_str<'a>(
         if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp {
             parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp));
             // SAFETY: we just initialized the elements `..4`.
-            unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
+            unsafe { parts[..4].assume_init_ref() }
         } else {
             // SAFETY: we just initialized the elements `..3`.
-            unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
+            unsafe { parts[..3].assume_init_ref() }
         }
     } else {
         let exp = exp as usize;
@@ -225,10 +225,10 @@ fn digits_to_dec_str<'a>(
             if frac_digits > buf.len() - exp {
                 parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp)));
                 // SAFETY: we just initialized the elements `..4`.
-                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
+                unsafe { parts[..4].assume_init_ref() }
             } else {
                 // SAFETY: we just initialized the elements `..3`.
-                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
+                unsafe { parts[..3].assume_init_ref() }
             }
         } else {
             // the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__].
@@ -238,10 +238,10 @@ fn digits_to_dec_str<'a>(
                 parts[2] = MaybeUninit::new(Part::Copy(b"."));
                 parts[3] = MaybeUninit::new(Part::Zero(frac_digits));
                 // SAFETY: we just initialized the elements `..4`.
-                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
+                unsafe { parts[..4].assume_init_ref() }
             } else {
                 // SAFETY: we just initialized the elements `..2`.
-                unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }
+                unsafe { parts[..2].assume_init_ref() }
             }
         }
     }
@@ -292,7 +292,7 @@ fn digits_to_exp_str<'a>(
         parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16));
     }
     // SAFETY: we just initialized the elements `..n + 2`.
-    unsafe { MaybeUninit::slice_assume_init_ref(&parts[..n + 2]) }
+    unsafe { parts[..n + 2].assume_init_ref() }
 }
 
 /// Sign formatting options.
@@ -366,12 +366,12 @@ where
         FullDecoded::Nan => {
             parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Infinite => {
             parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Zero => {
             if frac_digits > 0 {
@@ -381,14 +381,14 @@ where
                 Formatted {
                     sign,
                     // SAFETY: we just initialized the elements `..2`.
-                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
+                    parts: unsafe { parts[..2].assume_init_ref() },
                 }
             } else {
                 parts[0] = MaybeUninit::new(Part::Copy(b"0"));
                 Formatted {
                     sign,
                     // SAFETY: we just initialized the elements `..1`.
-                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
+                    parts: unsafe { parts[..1].assume_init_ref() },
                 }
             }
         }
@@ -442,12 +442,12 @@ where
         FullDecoded::Nan => {
             parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Infinite => {
             parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Zero => {
             parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 {
@@ -456,7 +456,7 @@ where
                 MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }))
             };
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Finite(ref decoded) => {
             let (buf, exp) = format_shortest(decoded, buf);
@@ -533,12 +533,12 @@ where
         FullDecoded::Nan => {
             parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Infinite => {
             parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Zero => {
             if ndigits > 1 {
@@ -549,14 +549,14 @@ where
                 Formatted {
                     sign,
                     // SAFETY: we just initialized the elements `..3`.
-                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) },
+                    parts: unsafe { parts[..3].assume_init_ref() },
                 }
             } else {
                 parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }));
                 Formatted {
                     sign,
                     // SAFETY: we just initialized the elements `..1`.
-                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
+                    parts: unsafe { parts[..1].assume_init_ref() },
                 }
             }
         }
@@ -607,12 +607,12 @@ where
         FullDecoded::Nan => {
             parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Infinite => {
             parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
             // SAFETY: we just initialized the elements `..1`.
-            Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
+            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
         }
         FullDecoded::Zero => {
             if frac_digits > 0 {
@@ -622,14 +622,14 @@ where
                 Formatted {
                     sign,
                     // SAFETY: we just initialized the elements `..2`.
-                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
+                    parts: unsafe { parts[..2].assume_init_ref() },
                 }
             } else {
                 parts[0] = MaybeUninit::new(Part::Copy(b"0"));
                 Formatted {
                     sign,
                     // SAFETY: we just initialized the elements `..1`.
-                    parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
+                    parts: unsafe { parts[..1].assume_init_ref() },
                 }
             }
         }
@@ -654,14 +654,14 @@ where
                     Formatted {
                         sign,
                         // SAFETY: we just initialized the elements `..2`.
-                        parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
+                        parts: unsafe { parts[..2].assume_init_ref() },
                     }
                 } else {
                     parts[0] = MaybeUninit::new(Part::Copy(b"0"));
                     Formatted {
                         sign,
                         // SAFETY: we just initialized the elements `..1`.
-                        parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
+                        parts: unsafe { parts[..1].assume_init_ref() },
                     }
                 }
             } else {
diff --git a/library/core/src/num/flt2dec/strategy/dragon.rs b/library/core/src/num/flt2dec/strategy/dragon.rs
index e801f07b3bc..dd73e4b4846 100644
--- a/library/core/src/num/flt2dec/strategy/dragon.rs
+++ b/library/core/src/num/flt2dec/strategy/dragon.rs
@@ -247,7 +247,7 @@ pub fn format_shortest<'a>(
         // it seems that this condition is very hard to satisfy (possibly impossible),
         // but we are just being safe and consistent here.
         // SAFETY: we initialized that memory above.
-        if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }) {
+        if let Some(c) = round_up(unsafe { buf[..i].assume_init_mut() }) {
             buf[i] = MaybeUninit::new(c);
             i += 1;
             k += 1;
@@ -255,7 +255,7 @@ pub fn format_shortest<'a>(
     }
 
     // SAFETY: we initialized that memory above.
-    (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..i]) }, k)
+    (unsafe { buf[..i].assume_init_ref() }, k)
 }
 
 /// The exact and fixed mode implementation for Dragon.
@@ -333,7 +333,7 @@ pub fn format_exact<'a>(
                     *c = MaybeUninit::new(b'0');
                 }
                 // SAFETY: we initialized that memory above.
-                return (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k);
+                return (unsafe { buf[..len].assume_init_ref() }, k);
             }
 
             let mut d = 0;
@@ -372,7 +372,7 @@ pub fn format_exact<'a>(
         // if rounding up changes the length, the exponent should also change.
         // but we've been requested a fixed number of digits, so do not alter the buffer...
         // SAFETY: we initialized that memory above.
-        if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) {
+        if let Some(c) = round_up(unsafe { buf[..len].assume_init_mut() }) {
             // ...unless we've been requested the fixed precision instead.
             // we also need to check that, if the original buffer was empty,
             // the additional digit can only be added when `k == limit` (edge case).
@@ -385,5 +385,5 @@ pub fn format_exact<'a>(
     }
 
     // SAFETY: we initialized that memory above.
-    (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k)
+    (unsafe { buf[..len].assume_init_ref() }, k)
 }
diff --git a/library/core/src/num/flt2dec/strategy/grisu.rs b/library/core/src/num/flt2dec/strategy/grisu.rs
index bdf544a4133..2816de4c633 100644
--- a/library/core/src/num/flt2dec/strategy/grisu.rs
+++ b/library/core/src/num/flt2dec/strategy/grisu.rs
@@ -275,7 +275,7 @@ pub fn format_shortest_opt<'a>(
             let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent
             return round_and_weed(
                 // SAFETY: we initialized that memory above.
-                unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) },
+                unsafe { buf[..i].assume_init_mut() },
                 exp,
                 plus1rem,
                 delta1,
@@ -324,7 +324,7 @@ pub fn format_shortest_opt<'a>(
             let ten_kappa = 1 << e; // implicit divisor
             return round_and_weed(
                 // SAFETY: we initialized that memory above.
-                unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) },
+                unsafe { buf[..i].assume_init_mut() },
                 exp,
                 r,
                 threshold,
@@ -713,7 +713,7 @@ pub fn format_exact_opt<'a>(
         // `10^kappa` did not overflow after all, the second check is fine.
         if ten_kappa - remainder > remainder && ten_kappa - 2 * remainder >= 2 * ulp {
             // SAFETY: our caller initialized that memory.
-            return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp));
+            return Some((unsafe { buf[..len].assume_init_ref() }, exp));
         }
 
         //   :<------- remainder ------>|   :
@@ -736,7 +736,7 @@ pub fn format_exact_opt<'a>(
         if remainder > ulp && ten_kappa - (remainder - ulp) <= remainder - ulp {
             if let Some(c) =
                 // SAFETY: our caller must have initialized that memory.
-                round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) })
+                round_up(unsafe { buf[..len].assume_init_mut() })
             {
                 // only add an additional digit when we've been requested the fixed precision.
                 // we also need to check that, if the original buffer was empty,
@@ -748,7 +748,7 @@ pub fn format_exact_opt<'a>(
                 }
             }
             // SAFETY: we and our caller initialized that memory.
-            return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp));
+            return Some((unsafe { buf[..len].assume_init_ref() }, exp));
         }
 
         // otherwise we are doomed (i.e., some values between `v - 1 ulp` and `v + 1 ulp` are
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index f3b4387f6a8..1b5c5fc82a6 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -200,60 +200,60 @@ fn uninit_array_assume_init() {
 }
 
 #[test]
-fn uninit_write_slice() {
+fn uninit_write_copy_of_slice() {
     let mut dst = [MaybeUninit::new(255); 64];
     let src = [0; 64];
 
-    assert_eq!(MaybeUninit::copy_from_slice(&mut dst, &src), &src);
+    assert_eq!(dst.write_copy_of_slice(&src), &src);
 }
 
 #[test]
 #[should_panic(expected = "source slice length (32) does not match destination slice length (64)")]
-fn uninit_write_slice_panic_lt() {
+fn uninit_write_copy_of_slice_panic_lt() {
     let mut dst = [MaybeUninit::uninit(); 64];
     let src = [0; 32];
 
-    MaybeUninit::copy_from_slice(&mut dst, &src);
+    dst.write_copy_of_slice(&src);
 }
 
 #[test]
 #[should_panic(expected = "source slice length (128) does not match destination slice length (64)")]
-fn uninit_write_slice_panic_gt() {
+fn uninit_write_copy_of_slice_panic_gt() {
     let mut dst = [MaybeUninit::uninit(); 64];
     let src = [0; 128];
 
-    MaybeUninit::copy_from_slice(&mut dst, &src);
+    dst.write_copy_of_slice(&src);
 }
 
 #[test]
-fn uninit_clone_from_slice() {
+fn uninit_write_clone_of_slice() {
     let mut dst = [MaybeUninit::new(255); 64];
     let src = [0; 64];
 
-    assert_eq!(MaybeUninit::clone_from_slice(&mut dst, &src), &src);
+    assert_eq!(dst.write_clone_of_slice(&src), &src);
 }
 
 #[test]
 #[should_panic(expected = "destination and source slices have different lengths")]
-fn uninit_write_slice_cloned_panic_lt() {
+fn uninit_write_clone_of_slice_panic_lt() {
     let mut dst = [MaybeUninit::uninit(); 64];
     let src = [0; 32];
 
-    MaybeUninit::clone_from_slice(&mut dst, &src);
+    dst.write_clone_of_slice(&src);
 }
 
 #[test]
 #[should_panic(expected = "destination and source slices have different lengths")]
-fn uninit_write_slice_cloned_panic_gt() {
+fn uninit_write_clone_of_slice_panic_gt() {
     let mut dst = [MaybeUninit::uninit(); 64];
     let src = [0; 128];
 
-    MaybeUninit::clone_from_slice(&mut dst, &src);
+    dst.write_clone_of_slice(&src);
 }
 
 #[test]
 #[cfg(panic = "unwind")]
-fn uninit_write_slice_cloned_mid_panic() {
+fn uninit_write_clone_of_slice_mid_panic() {
     use std::panic;
 
     enum IncrementOrPanic {
@@ -289,7 +289,7 @@ fn uninit_write_slice_cloned_mid_panic() {
     ];
 
     let err = panic::catch_unwind(panic::AssertUnwindSafe(|| {
-        MaybeUninit::clone_from_slice(&mut dst, &src);
+        dst.write_clone_of_slice(&src);
     }));
 
     drop(src);
@@ -317,11 +317,11 @@ impl Drop for Bomb {
 }
 
 #[test]
-fn uninit_write_slice_cloned_no_drop() {
+fn uninit_write_clone_of_slice_no_drop() {
     let mut dst = [MaybeUninit::uninit()];
     let src = [Bomb];
 
-    MaybeUninit::clone_from_slice(&mut dst, &src);
+    dst.write_clone_of_slice(&src);
 
     forget(src);
 }
diff --git a/library/proc_macro/src/bridge/arena.rs b/library/proc_macro/src/bridge/arena.rs
index 1d5986093c8..29636e793f6 100644
--- a/library/proc_macro/src/bridge/arena.rs
+++ b/library/proc_macro/src/bridge/arena.rs
@@ -102,7 +102,7 @@ impl Arena {
     #[allow(clippy::mut_from_ref)] // arena allocator
     pub(crate) fn alloc_str<'a>(&'a self, string: &str) -> &'a mut str {
         let alloc = self.alloc_raw(string.len());
-        let bytes = MaybeUninit::copy_from_slice(alloc, string.as_bytes());
+        let bytes = alloc.write_copy_of_slice(string.as_bytes());
 
         // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
         // and immediately convert the clone back to `&str`.
diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs
index cbec44c8626..2572b71fd9a 100644
--- a/library/std/src/ffi/os_str/tests.rs
+++ b/library/std/src/ffi/os_str/tests.rs
@@ -295,7 +295,7 @@ fn clone_to_uninit() {
 
     let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
     unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
-    assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
+    assert_eq!(a.as_encoded_bytes(), unsafe { storage.assume_init_ref() });
 
     let mut b: Box<OsStr> = OsStr::new("world.exe").into();
     assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs
index 17721090db5..5251cc302cb 100644
--- a/library/std/src/io/buffered/bufreader/buffer.rs
+++ b/library/std/src/io/buffered/bufreader/buffer.rs
@@ -50,7 +50,7 @@ impl Buffer {
     pub fn buffer(&self) -> &[u8] {
         // SAFETY: self.pos and self.cap are valid, and self.cap => self.pos, and
         // that region is initialized because those are all invariants of this type.
-        unsafe { MaybeUninit::slice_assume_init_ref(self.buf.get_unchecked(self.pos..self.filled)) }
+        unsafe { self.buf.get_unchecked(self.pos..self.filled).assume_init_ref() }
     }
 
     #[inline]
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index ff3f7151bb8..3f96ac4672a 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -2069,9 +2069,7 @@ fn clone_to_uninit() {
 
     let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
     unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
-    assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
-        MaybeUninit::slice_assume_init_ref(&storage)
-    });
+    assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe { storage.assume_init_ref() });
 
     let mut b: Box<Path> = Path::new("world.exe").into();
     assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index 88e6def7a75..4282dbb5493 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -272,7 +272,7 @@ where
                 unreachable!();
             } else {
                 // Safety: First `k` values are initialized.
-                let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]);
+                let slice: &[u16] = buf[..k].assume_init_ref();
                 return Ok(f2(slice));
             }
         }
diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs
index 1b735e7f0cb..fd3f559ba19 100644
--- a/library/std/src/sys/pal/windows/stdio.rs
+++ b/library/std/src/sys/pal/windows/stdio.rs
@@ -207,7 +207,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
         assert!(result != 0, "Unexpected error in MultiByteToWideChar");
 
         // Safety: MultiByteToWideChar initializes `result` values.
-        MaybeUninit::slice_assume_init_ref(&utf16[..result as usize])
+        utf16[..result as usize].assume_init_ref()
     };
 
     let mut written = write_u16s(handle, utf16)?;
@@ -283,7 +283,7 @@ impl io::Read for Stdin {
             let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, 1, &mut self.surrogate)?;
             // Read bytes, using the (now-empty) self.incomplete_utf8 as extra space.
             let read_bytes = utf16_to_utf8(
-                unsafe { MaybeUninit::slice_assume_init_ref(&utf16_buf[..read]) },
+                unsafe { utf16_buf[..read].assume_init_ref() },
                 &mut self.incomplete_utf8.bytes,
             )?;
 
@@ -303,7 +303,7 @@ impl io::Read for Stdin {
                 read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?;
             // Safety `read_u16s_fixup_surrogates` returns the number of items
             // initialized.
-            let utf16s = unsafe { MaybeUninit::slice_assume_init_ref(&utf16_buf[..read]) };
+            let utf16s = unsafe { utf16_buf[..read].assume_init_ref() };
             match utf16_to_utf8(utf16s, buf) {
                 Ok(value) => return Ok(bytes_copied + value),
                 Err(e) => return Err(e),