Add inherent versions of MaybeUninit methods for slices

This commit is contained in:
ltdk 2024-08-18 19:50:41 -04:00
parent 12445e0b2c
commit e37daf0c86
18 changed files with 543 additions and 441 deletions

View file

@ -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();
}
}
}

View file

@ -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() }
}
}

View file

@ -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)

View file

@ -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();
}
}
}

View file

@ -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.

View file

@ -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();
}
}
}

View file

@ -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,339 +981,6 @@ impl<T> MaybeUninit<T> {
}
}
/// Assuming all the elements are initialized, get a slice to them.
///
/// # Safety
///
/// 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.
///
/// See [`assume_init_ref`] for more details and examples.
///
/// [`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]) }
}
/// Assuming all the elements are initialized, get a mutable slice to them.
///
/// # Safety
///
/// 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.
///
/// See [`assume_init_mut`] for more details and examples.
///
/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
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]) }
}
/// Gets a pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
this.as_ptr() as *const T
}
/// Gets a mutable pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut 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
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
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) }
}
/// 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
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
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) }
}
/// Fills `this` with elements by cloning `value`, returning a mutable reference to the now
/// initialized contents of `this`.
/// Any previously initialized elements will not be dropped.
///
/// This is similar to [`slice::fill`].
///
/// # Panics
///
/// This function will panic if any call to `Clone` panics.
///
/// If such a panic occurs, any elements previously initialized during this operation will be
/// dropped.
///
/// # 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);
/// 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]
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) }
}
/// Fills `this` 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
/// pass [`Default::default`] as the argument.
///
/// # Panics
///
/// This function will panic if any call to the provided closure panics.
///
/// If such a panic occurs, any elements previously initialized during this operation will be
/// dropped.
///
/// # 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);
/// 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]
where
F: FnMut() -> T,
{
let mut guard = Guard { slice: this, initialized: 0 };
for element in guard.slice.iter_mut() {
element.write(f());
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) }
}
/// Fills `this` 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.
/// The second slice is the still-uninitialized remainder of the original slice.
///
/// # Panics
///
/// This function panics if the iterator's `next` function panics.
///
/// If such a panic occurs, any elements previously initialized during this operation will be
/// dropped.
///
/// # Examples
///
/// Fill an uninit vec with a cycling iterator.
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// let mut buf = vec![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());
/// ```
///
/// Fill an uninit vec, but not completely.
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// let mut buf = vec![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);
/// ```
#[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>])
where
I: IntoIterator<Item = T>,
{
let iter = it.into_iter();
let mut guard = Guard { slice: this, initialized: 0 };
for (element, val) in guard.slice.iter_mut().zip(iter) {
element.write(val);
guard.initialized += 1;
}
let initialized_len = guard.initialized;
super::forget(guard);
// SAFETY: guard.initialized <= this.len()
let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) };
// SAFETY: Valid elements have just been written into `init`, so that portion
// of `this` is initialized.
(unsafe { MaybeUninit::slice_assume_init_mut(initted) }, remainder)
}
/// 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
@ -1329,14 +995,14 @@ impl<T> MaybeUninit<T> {
/// 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) };
/// let bytes = unsafe { uninit_bytes.assume_init_ref() };
/// assert_eq!(bytes, val.to_ne_bytes());
/// ```
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
pub fn as_bytes(&self) -> &[MaybeUninit<u8>] {
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() as *const MaybeUninit<u8>, mem::size_of::<T>())
slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), super::size_of::<T>())
}
}
@ -1364,18 +1030,397 @@ impl<T> MaybeUninit<T> {
/// assert_eq!(val2, 0x123456cd);
/// ```
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
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() as *mut MaybeUninit<u8>,
mem::size_of::<T>(),
self.as_mut_ptr().cast::<MaybeUninit<u8>>(),
super::size_of::<T>(),
)
}
}
/// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized
/// bytes.
/// Deprecated version of [`slice::assume_init_ref`].
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[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: Same for both methods.
unsafe { slice.assume_init_mut() }
}
/// Gets a pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
this.as_ptr() as *const T
}
/// Gets a mutable pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
this.as_mut_ptr() as *mut T
}
/// 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,
{
this.write_copy_of_slice(src)
}
/// 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,
{
this.write_clone_of_slice(src)
}
/// 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`].
///
/// # Panics
///
/// This function will panic if any call to `Clone` panics.
///
/// If such a panic occurs, any elements previously initialized during this operation will be
/// dropped.
///
/// # Examples
///
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// 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(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 { this.assume_init_mut() }
}
/// 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
/// pass [`Default::default`] as the argument.
///
/// # Panics
///
/// This function will panic if any call to the provided closure panics.
///
/// If such a panic occurs, any elements previously initialized during this operation will be
/// dropped.
///
/// # Examples
///
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// 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<F>(this: &mut [MaybeUninit<T>], mut f: F) -> &mut [T]
where
F: FnMut() -> T,
{
let mut guard = Guard { slice: this, initialized: 0 };
for element in guard.slice.iter_mut() {
element.write(f());
guard.initialized += 1;
}
super::forget(guard);
// SAFETY: Valid elements have just been written into `this` so it is initialized
unsafe { this.assume_init_mut() }
}
/// 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.
/// The second slice is the still-uninitialized remainder of the original slice.
///
/// # Panics
///
/// This function panics if the iterator's `next` function panics.
///
/// If such a panic occurs, any elements previously initialized during this operation will be
/// dropped.
///
/// # Examples
///
/// Completely filling the slice:
///
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// 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!(remainder.len(), 0);
/// ```
///
/// Partially filling the slice:
///
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// 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<I>(this: &mut [MaybeUninit<T>], it: I) -> (&mut [T], &mut [MaybeUninit<T>])
where
I: IntoIterator<Item = T>,
{
let iter = it.into_iter();
let mut guard = Guard { slice: this, initialized: 0 };
for (element, val) in guard.slice.iter_mut().zip(iter) {
element.write(val);
guard.initialized += 1;
}
let initialized_len = guard.initialized;
super::forget(guard);
// SAFETY: guard.initialized <= this.len()
let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) };
// SAFETY: Valid elements have just been written into `init`, so that portion
// of `this` is initialized.
(unsafe { initted.assume_init_mut() }, remainder)
}
/// 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`.
///
/// 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_write_slice)]
/// use std::mem::MaybeUninit;
///
/// let mut dst = [MaybeUninit::uninit(); 32];
/// let src = [0; 32];
///
/// let init = dst.write_copy_of_slice(&src);
///
/// assert_eq!(init, src);
/// ```
///
/// ```
/// #![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() }
}
/// 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.
///
/// 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_write_slice)]
/// use std::mem::MaybeUninit;
///
/// 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());
/// }
///
/// assert_eq!(vec, src);
/// ```
///
/// [`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 `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();
}
}
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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)
}

View file

@ -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

View file

@ -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);
}

View file

@ -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`.

View file

@ -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));

View file

@ -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]

View file

@ -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));

View file

@ -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));
}
}

View file

@ -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),