Skip to content

Commit d1da78b

Browse files
Rollup merge of rust-lang#139072 - nickkuk:align_to_uninit_mut, r=Mark-Simulacrum
Add `slice::align_to_uninit_mut` Add new `slice::align_to_uninit_mut` method. Tracking issue: rust-lang#139062 ACP: rust-lang/libs-team#564
2 parents 962fa98 + ed35b9b commit d1da78b

File tree

1 file changed

+51
-2
lines changed

1 file changed

+51
-2
lines changed

Diff for: library/core/src/slice/mod.rs

+51-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
use crate::cmp::Ordering::{self, Equal, Greater, Less};
1010
use crate::intrinsics::{exact_div, unchecked_sub};
11-
use crate::mem::{self, SizedTypeProperties};
11+
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
1212
use crate::num::NonZero;
1313
use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive};
1414
use crate::panic::const_panic;
@@ -4579,7 +4579,7 @@ impl<T> [T] {
45794579
// or generate worse code otherwise. This is also why we need to go
45804580
// through a raw pointer here.
45814581
let slice: *mut [T] = self;
4582-
let mut arr: mem::MaybeUninit<[&mut I::Output; N]> = mem::MaybeUninit::uninit();
4582+
let mut arr: MaybeUninit<[&mut I::Output; N]> = MaybeUninit::uninit();
45834583
let arr_ptr = arr.as_mut_ptr();
45844584

45854585
// SAFETY: We expect `indices` to contain disjunct values that are
@@ -4764,6 +4764,55 @@ impl<T> [T] {
47644764
}
47654765
}
47664766

4767+
impl<T> [MaybeUninit<T>] {
4768+
/// Transmutes the mutable uninitialized slice to a mutable uninitialized slice of
4769+
/// another type, ensuring alignment of the types is maintained.
4770+
///
4771+
/// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same
4772+
/// guarantees as that method.
4773+
///
4774+
/// # Examples
4775+
///
4776+
/// ```
4777+
/// #![feature(align_to_uninit_mut)]
4778+
/// use std::mem::MaybeUninit;
4779+
///
4780+
/// pub struct BumpAllocator<'scope> {
4781+
/// memory: &'scope mut [MaybeUninit<u8>],
4782+
/// }
4783+
///
4784+
/// impl<'scope> BumpAllocator<'scope> {
4785+
/// pub fn new(memory: &'scope mut [MaybeUninit<u8>]) -> Self {
4786+
/// Self { memory }
4787+
/// }
4788+
/// pub fn try_alloc_uninit<T>(&mut self) -> Option<&'scope mut MaybeUninit<T>> {
4789+
/// let first_end = self.memory.as_ptr().align_offset(align_of::<T>()) + size_of::<T>();
4790+
/// let prefix = self.memory.split_off_mut(..first_end)?;
4791+
/// Some(&mut prefix.align_to_uninit_mut::<T>().1[0])
4792+
/// }
4793+
/// pub fn try_alloc_u32(&mut self, value: u32) -> Option<&'scope mut u32> {
4794+
/// let uninit = self.try_alloc_uninit()?;
4795+
/// Some(uninit.write(value))
4796+
/// }
4797+
/// }
4798+
///
4799+
/// let mut memory = [MaybeUninit::<u8>::uninit(); 10];
4800+
/// let mut allocator = BumpAllocator::new(&mut memory);
4801+
/// let v = allocator.try_alloc_u32(42);
4802+
/// assert_eq!(v, Some(&mut 42));
4803+
/// ```
4804+
#[unstable(feature = "align_to_uninit_mut", issue = "139062")]
4805+
#[inline]
4806+
#[must_use]
4807+
pub fn align_to_uninit_mut<U>(&mut self) -> (&mut Self, &mut [MaybeUninit<U>], &mut Self) {
4808+
// SAFETY: `MaybeUninit` is transparent. Correct size and alignment are guaranteed by
4809+
// `align_to_mut` itself. Therefore the only thing that we have to ensure for a safe
4810+
// `transmute` is that the values are valid for the types involved. But for `MaybeUninit`
4811+
// any values are valid, so this operation is safe.
4812+
unsafe { self.align_to_mut() }
4813+
}
4814+
}
4815+
47674816
impl<T, const N: usize> [[T; N]] {
47684817
/// Takes a `&[[T; N]]`, and flattens it to a `&[T]`.
47694818
///

0 commit comments

Comments
 (0)