Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tidy up maybe_uninit_slice API #103131

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<T> ArenaChunk<T> {
// Without the branch, dropping TypedArena<u8> takes linear time.
if mem::needs_drop::<T>() {
let slice = &mut *(self.storage.as_mut());
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
ptr::drop_in_place(slice[..len].assume_init_mut());
}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_serialize/src/leb128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ macro_rules! impl_write_unsigned_leb128 {
}
}

unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
unsafe { out.get_unchecked(..i).assume_init_ref() }
}
};
}
Expand Down Expand Up @@ -116,7 +116,7 @@ macro_rules! impl_write_signed_leb128 {
}
}

unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) }
unsafe { out.get_unchecked(..i).assume_init_ref() }
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_serialize/src/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ impl FileEncoder {
}

let mut guard = BufGuard::new(
unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[..self.buffered]) },
unsafe { self.buf[..self.buffered].assume_init_mut() },
&mut self.buffered,
&mut self.flushed,
);
Expand Down
4 changes: 1 addition & 3 deletions library/alloc/src/collections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,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() }
}
}

Expand Down
28 changes: 12 additions & 16 deletions library/alloc/src/collections/vec_deque/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
// - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
unsafe {
f.debug_tuple("Iter")
.field(&MaybeUninit::slice_assume_init_ref(front))
.field(&MaybeUninit::slice_assume_init_ref(back))
.field(&front.assume_init_ref())
.field(&back.assume_init_ref())
.finish()
}
}
Expand Down Expand Up @@ -80,8 +80,8 @@ impl<'a, T> Iterator for Iter<'a, T> {
// - `self.head` and `self.tail` in a ring buffer are always valid indices.
// - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
unsafe {
accum = MaybeUninit::slice_assume_init_ref(front).iter().fold(accum, &mut f);
MaybeUninit::slice_assume_init_ref(back).iter().fold(accum, &mut f)
accum = front.assume_init_ref().iter().fold(accum, &mut f);
back.assume_init_ref().iter().fold(accum, &mut f)
}
}

Expand All @@ -94,18 +94,17 @@ impl<'a, T> Iterator for Iter<'a, T> {
let (mut iter, final_res);
if self.tail <= self.head {
// Safety: single slice self.ring[self.tail..self.head] is initialized.
iter = unsafe { MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]) }
.iter();
iter = unsafe { self.ring[self.tail..self.head].assume_init_ref() }.iter();
final_res = iter.try_fold(init, &mut f);
} else {
// Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
let (front, back) = self.ring.split_at(self.tail);

let mut back_iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() };
let mut back_iter = unsafe { back.assume_init_ref().iter() };
let res = back_iter.try_fold(init, &mut f);
let len = self.ring.len();
self.tail = (self.ring.len() - back_iter.len()) & (len - 1);
iter = unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() };
iter = unsafe { front[..self.head].assume_init_ref().iter() };
final_res = iter.try_fold(res?, &mut f);
}
self.tail = self.head - iter.len();
Expand Down Expand Up @@ -161,8 +160,8 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
// - `self.head` and `self.tail` in a ring buffer are always valid indices.
// - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
unsafe {
accum = MaybeUninit::slice_assume_init_ref(back).iter().rfold(accum, &mut f);
MaybeUninit::slice_assume_init_ref(front).iter().rfold(accum, &mut f)
accum = back.assume_init_ref().iter().rfold(accum, &mut f);
front.assume_init_ref().iter().rfold(accum, &mut f)
}
}

Expand All @@ -175,19 +174,16 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
let (mut iter, final_res);
if self.tail <= self.head {
// Safety: single slice self.ring[self.tail..self.head] is initialized.
iter = unsafe {
MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]).iter()
};
iter = unsafe { self.ring[self.tail..self.head].assume_init_ref().iter() };
final_res = iter.try_rfold(init, &mut f);
} else {
// Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
let (front, back) = self.ring.split_at(self.tail);

let mut front_iter =
unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() };
let mut front_iter = unsafe { front[..self.head].assume_init_ref().iter() };
let res = front_iter.try_rfold(init, &mut f);
self.head = front_iter.len();
iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() };
iter = unsafe { back.assume_init_ref().iter() };
final_res = iter.try_rfold(res?, &mut f);
}
self.head = self.tail + iter.len();
Expand Down
12 changes: 4 additions & 8 deletions library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
unsafe {
let buf = self.buffer_as_slice();
let (front, back) = RingSlices::ring_slices(buf, self.head, self.tail);
(MaybeUninit::slice_assume_init_ref(front), MaybeUninit::slice_assume_init_ref(back))
(front.assume_init_ref(), back.assume_init_ref())
}
}

Expand Down Expand Up @@ -1143,7 +1143,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
let tail = self.tail;
let buf = self.buffer_as_mut_slice();
let (front, back) = RingSlices::ring_slices(buf, head, tail);
(MaybeUninit::slice_assume_init_mut(front), MaybeUninit::slice_assume_init_mut(back))
(front.assume_init_mut(), back.assume_init_mut())
}
}

Expand Down Expand Up @@ -2379,9 +2379,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
// - `self.head` and `self.tail` in a ring buffer are always valid indices.
// - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
return unsafe {
MaybeUninit::slice_assume_init_mut(
RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0,
)
RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0.assume_init_mut()
};
}

Expand Down Expand Up @@ -2472,9 +2470,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
// - `self.head` and `self.tail` in a ring buffer are always valid indices.
// - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
unsafe {
MaybeUninit::slice_assume_init_mut(
RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0,
)
RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0.assume_init_mut()
}
}

Expand Down
8 changes: 4 additions & 4 deletions library/core/src/array/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,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()
}
}

Expand All @@ -233,7 +233,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()
}
}
}
Expand Down Expand Up @@ -295,7 +295,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));
ptr::drop_in_place(slice.assume_init_mut());
}

if n > original_len { Err(original_len) } else { Ok(()) }
Expand Down Expand Up @@ -345,7 +345,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));
ptr::drop_in_place(slice.assume_init_mut());
}

if n > original_len { Err(original_len) } else { Ok(()) }
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -872,9 +872,9 @@ where

// SAFETY: this slice will contain only initialized objects.
unsafe {
crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
&mut self.array_mut.get_unchecked_mut(..self.initialized),
));
crate::ptr::drop_in_place(
self.array_mut.get_unchecked_mut(..self.initialized).assume_init_mut(),
);
}
}
}
Expand Down
100 changes: 51 additions & 49 deletions library/core/src/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,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()
/// }
/// }
///
Expand Down Expand Up @@ -956,48 +956,6 @@ impl<T> MaybeUninit<T> {
ret
}

/// 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")]
#[rustc_const_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")]
#[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
#[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")]
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
Expand Down Expand Up @@ -1068,7 +1026,7 @@ impl<T> MaybeUninit<T> {
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) }
unsafe { this.assume_init_mut() }
}

/// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
Expand Down Expand Up @@ -1136,7 +1094,7 @@ impl<T> MaybeUninit<T> {
// SAFETY: this raw slice will contain only initialized objects
// that's why, it is allowed to drop it.
unsafe {
crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part));
crate::ptr::drop_in_place(initialized_part.assume_init_mut());
}
}
}
Expand All @@ -1159,7 +1117,7 @@ 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() }
}

/// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
Expand All @@ -1176,7 +1134,7 @@ impl<T> MaybeUninit<T> {
/// let val = 0x12345678i32;
/// 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")]
Expand Down Expand Up @@ -1235,7 +1193,7 @@ impl<T> MaybeUninit<T> {
///
/// 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 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]);
Expand Down Expand Up @@ -1266,7 +1224,7 @@ impl<T> MaybeUninit<T> {
/// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
/// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
/// MaybeUninit::write_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]);
/// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) };
/// let vals = unsafe { uninit.assume_init_ref() };
/// if cfg!(target_endian = "little") {
/// assert_eq!(vals, &[0x3412u16, 0x7856u16]);
/// } else {
Expand Down Expand Up @@ -1321,3 +1279,47 @@ impl<T, const N: usize> [MaybeUninit<T>; N] {
unsafe { super::transmute_copy(&ManuallyDrop::new(self)) }
}
}

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")]
#[rustc_const_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 [MaybeUninit<T>] 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")]
#[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
#[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 [MaybeUninit<T>] as *mut [T]) }
}
}
Loading