binius_utils/mem.rs
1// Copyright 2025 Irreducible Inc.
2
3use std::mem::MaybeUninit;
4
5/// Turn a given slice of `T` into a slice of `MaybeUninit<T>`.
6///
7/// # Panics
8///
9/// This function is going to panic in case `T` has a destructor.
10pub fn slice_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
11 assert!(!std::mem::needs_drop::<T>());
12 unsafe {
13 // SAFETY:
14 //
15 // The `slice` is a valid mutable reference, so:
16 // - Its pointer is non-null and properly aligned
17 // - It points to `len` consecutive properly initialized values of type T
18 // - The memory region is valid for reads and writes
19 // - The memory belongs to a single allocated object
20 // - The total size is no larger than isize::MAX and doesn't wrap around the address space
21 //
22 // By casting the pointer to `*mut MaybeUninit<T>`, we're essentially forgetting that
23 // the values are initialized. This is safe because:
24 // 1. We've asserted that T doesn't have a destructor, so no cleanup is needed,
25 // 2. `MaybeUninit<T>` has the same memory layout as T,
26 // 3. We maintain the same length.
27 //
28 // The returned slice takes over the lifetime of the input slice making the lifetime
29 // correct.
30 std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut MaybeUninit<T>, slice.len())
31 }
32}