Skip to content

Commit

Permalink
Replace casts of slices (unsized types) with slice::from_raw_parts[_m…
Browse files Browse the repository at this point in the history
…ut]().

libcore/libstd is allowed to make assumptions avoid the validity about casts
that extern code in general cannot. In particular it isn't clear that casting
`[T]` to `[MaybeUninit<T>]` or vice-versa is guaranteed to be sound. Avoid the
issue by using an alternative to casts.
  • Loading branch information
briansmith committed May 22, 2024
1 parent bcbadc1 commit a8d3c6c
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#![allow(dead_code)]
use core::{mem::MaybeUninit, ptr};
use core::{mem::MaybeUninit, ptr, slice};

/// Polyfill for `maybe_uninit_slice` feature's
/// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have
/// been initialized.
#[inline(always)]
pub unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
&mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
// The caller promises that every element of `slice` has been initialized.
slice::from_raw_parts_mut(slice.as_mut_ptr().cast::<T>(), slice.len())
}

#[inline]
Expand All @@ -21,7 +22,7 @@ pub fn slice_as_uninit<T>(slice: &[T]) -> &[MaybeUninit<T>] {
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
// There is no risk of writing a `MaybeUninit<T>` into the result since
// the result isn't mutable.
unsafe { &*(slice as *const [T] as *const [MaybeUninit<T>]) }
unsafe { slice::from_raw_parts(slice.as_ptr().cast::<MaybeUninit<T>>(), slice.len()) }
}

/// View an mutable initialized array as potentially-uninitialized.
Expand All @@ -31,5 +32,5 @@ pub fn slice_as_uninit<T>(slice: &[T]) -> &[MaybeUninit<T>] {
#[inline(always)]
pub unsafe fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
&mut *(slice as *mut [T] as *mut [MaybeUninit<T>])
slice::from_raw_parts_mut(slice.as_mut_ptr().cast::<MaybeUninit<T>>(), slice.len())
}

0 comments on commit a8d3c6c

Please sign in to comment.