Skip to content

Commit 970db09

Browse files
committed
Add slice::align_to_uninit_mut
1 parent 2a06022 commit 970db09

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

library/core/src/slice/mod.rs

+47-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;
@@ -4589,7 +4589,7 @@ impl<T> [T] {
45894589
// or generate worse code otherwise. This is also why we need to go
45904590
// through a raw pointer here.
45914591
let slice: *mut [T] = self;
4592-
let mut arr: mem::MaybeUninit<[&mut I::Output; N]> = mem::MaybeUninit::uninit();
4592+
let mut arr: MaybeUninit<[&mut I::Output; N]> = MaybeUninit::uninit();
45934593
let arr_ptr = arr.as_mut_ptr();
45944594

45954595
// SAFETY: We expect `indices` to contain disjunct values that are
@@ -4774,6 +4774,51 @@ impl<T> [T] {
47744774
}
47754775
}
47764776

4777+
impl<T> [MaybeUninit<T>] {
4778+
/// Transmutes the mutable uninitialized slice to a mutable uninitialized slice of
4779+
/// another type, ensuring alignment of the types is maintained.
4780+
///
4781+
/// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same
4782+
/// guarantees as that method.
4783+
///
4784+
/// # Examples
4785+
///
4786+
/// ```
4787+
/// #![feature(align_to_uninit_mut)]
4788+
/// use std::mem::MaybeUninit;
4789+
///
4790+
/// pub struct BumpAllocator<'scope> {
4791+
/// memory: &'scope mut [MaybeUninit<u8>],
4792+
/// }
4793+
///
4794+
/// impl<'scope> BumpAllocator<'scope> {
4795+
/// pub fn new(memory: &'scope mut [MaybeUninit<u8>]) -> Self {
4796+
/// Self { memory }
4797+
/// }
4798+
/// pub fn try_alloc_uninit<T>(&mut self) -> Option<&'scope mut MaybeUninit<T>> {
4799+
/// let first_end = self.memory.as_ptr().align_offset(align_of::<T>()) + size_of::<T>();
4800+
/// let prefix = self.memory.split_off_mut(..first_end)?;
4801+
/// Some(&mut prefix.align_to_uninit_mut::<T>().1[0])
4802+
/// }
4803+
/// pub fn try_alloc_u32(&mut self, value: u32) -> Option<&'scope mut u32> {
4804+
/// let uninit = self.try_alloc_uninit()?;
4805+
/// Some(uninit.write(value))
4806+
/// }
4807+
/// }
4808+
///
4809+
/// let mut memory = [MaybeUninit::<u8>::uninit(); 10];
4810+
/// let mut allocator = BumpAllocator::new(&mut memory);
4811+
/// let v = allocator.try_alloc_u32(42);
4812+
/// assert_eq!(v, Some(&mut 42));
4813+
/// ```
4814+
#[unstable(feature = "align_to_uninit_mut", issue = "139062")]
4815+
#[inline]
4816+
#[must_use]
4817+
pub fn align_to_uninit_mut<U>(&mut self) -> (&mut Self, &mut [MaybeUninit<U>], &mut Self) {
4818+
unsafe { self.align_to_mut() }
4819+
}
4820+
}
4821+
47774822
impl<T, const N: usize> [[T; N]] {
47784823
/// Takes a `&[[T; N]]`, and flattens it to a `&[T]`.
47794824
///

0 commit comments

Comments
 (0)