Skip to content

Commit

Permalink
Tidy up maybe_uninit_slice API
Browse files Browse the repository at this point in the history
- Move methods to extensions

Signed-off-by: Alex Saveau <[email protected]>
  • Loading branch information
SUPERCILEX committed Oct 17, 2022
1 parent 8be3ce9 commit eb667be
Show file tree
Hide file tree
Showing 17 changed files with 122 additions and 132 deletions.
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

0 comments on commit eb667be

Please sign in to comment.