Skip to content

Commit

Permalink
Unrolled build for rust-lang#129259
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#129259 - clarfonthey:maybe_uninit_slices, r=tgross35

Add inherent versions of MaybeUninit methods for slices

This is my attempt to un-stall rust-lang#63569 and rust-lang#79995, by creating methods that mirror the existing `MaybeUninit` API:

```rust
impl<T> MaybeUninit<T> {
    pub fn write(&mut self, value: T) -> &mut T;
    pub fn as_bytes(&self) -> &[MaybeUninit<u8>];
    pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>];
    pub unsafe fn assume_init_drop(&mut self);
    pub unsafe fn assume_init_ref(&self) -> &T;
    pub unsafe fn assume_init_mut(&mut self) -> &mut T;
}
```

Adding these APIs:

```rust
impl<T> [MaybeUninit<T>] {
    // replacing copy_from_slice; renamed to avoid conflict
    pub fn write_copy_of_slice(&mut self, value: &[T]) -> &mut [T] where T: Copy;

    // replacing clone_from_slice; renamed to avoid conflict
    pub fn write_clone_of_slice(&mut self, value: &[T]) -> &mut [T] where T: Clone;

    // identical to non-slice versions; no conflict
    pub fn as_bytes(&self) -> &[MaybeUninit<u8>];
    pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>];
    pub unsafe fn assume_init_drop(&mut self);
    pub unsafe fn assume_init_ref(&self) -> &[T];
    pub unsafe fn assume_init_mut(&mut self) -> &mut [T];
}
```

Since the `assume_init` methods are identical to those on non-slices, they feel pretty natural. The main issue with the write methods is naming, as discussed in rust-lang#79995 among other places. My rationale:

* The term "write" should be in them somewhere, to mirror the other API, and this pretty much automatically makes them not collide with any other inherent slice methods.
* I chose `write_clone_of_slice` and `write_copy_of_slice` since `clone` and `copy` are being used as objects here, whereas they're being used as actions in `clone_from_slice` and `copy_from_slice`.

The final "weird" thing I've done in this PR is remove a link to `Vec<T>` from `assume_init_drop` (both copies, since they're effectively copied docs), since there's no good way to link to `Vec` for something that can occur both on the page for `std/primitive.slice.html` and `std/vec/struct.Vec.html`, since the code here lives in libcore and can't use intra-doc-linking to mention `Vec`. (see: rust-lang#121436)

The reason why this method shows up both on `Vec<T>` and `[T]` is because the `[T]` docs are automatically inlined on `Vec<T>`'s page, since it implements `Deref`. It's unfortunate that rustdoc doesn't have a way of dealing with this at the moment, but it is what it is, and it's a reasonable compromise for now.
  • Loading branch information
rust-timer authored Jan 12, 2025
2 parents c0f6a1c + e37daf0 commit 9be56ee
Show file tree
Hide file tree
Showing 18 changed files with 412 additions and 310 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 @@ -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();
}
}
}
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 @@ -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() }
}
}

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

Expand All @@ -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()
}
}
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 1 addition & 3 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions library/core/src/io/borrowed_buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}

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

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

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

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

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

Expand Down Expand Up @@ -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.
Expand Down
4 changes: 1 addition & 3 deletions library/core/src/iter/adapters/filter_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Expand Down
Loading

0 comments on commit 9be56ee

Please sign in to comment.