From 534fd6855c7b232358f2dabbb2620ca765fd4b8e Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 22 May 2024 13:35:53 -0700 Subject: [PATCH] Clarify safety properties of casts between `[MaybeUninit]` <-> `[T]`. Reduce the scope of the `unsafe` blocks to the unsafe operations. --- src/util.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/util.rs b/src/util.rs index 1c4e70ba4..9eeba9a7f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -5,9 +5,11 @@ use core::{mem::MaybeUninit, ptr}; /// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have /// been initialized. #[inline(always)] +#[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this. pub unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit]) -> &mut [T] { + let ptr = ptr_from_mut::<[MaybeUninit]>(slice) as *mut [T]; // SAFETY: `MaybeUninit` is guaranteed to be layout-compatible with `T`. - &mut *(slice as *mut [MaybeUninit] as *mut [T]) + unsafe { &mut *ptr } } #[inline] @@ -18,10 +20,9 @@ pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit]) -> &mut [u8] { #[inline(always)] pub fn slice_as_uninit(slice: &[T]) -> &[MaybeUninit] { + let ptr = ptr_from_ref::<[T]>(slice) as *const [MaybeUninit]; // SAFETY: `MaybeUninit` is guaranteed to be layout-compatible with `T`. - // There is no risk of writing a `MaybeUninit` into the result since - // the result isn't mutable. - unsafe { &*(slice as *const [T] as *const [MaybeUninit]) } + unsafe { &*ptr } } /// View an mutable initialized array as potentially-uninitialized. @@ -29,7 +30,19 @@ pub fn slice_as_uninit(slice: &[T]) -> &[MaybeUninit] { /// This is unsafe because it allows assigning uninitialized values into /// `slice`, which would be undefined behavior. #[inline(always)] +#[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this. pub unsafe fn slice_as_uninit_mut(slice: &mut [T]) -> &mut [MaybeUninit] { + let ptr = ptr_from_mut::<[T]>(slice) as *mut [MaybeUninit]; // SAFETY: `MaybeUninit` is guaranteed to be layout-compatible with `T`. - &mut *(slice as *mut [T] as *mut [MaybeUninit]) + unsafe { &mut *ptr } +} + +// TODO: MSRV(1.76.0): Replace with `core::ptr::from_mut`. +fn ptr_from_mut(r: &mut T) -> *mut T { + r +} + +// TODO: MSRV(1.76.0): Replace with `core::ptr::from_ref`. +fn ptr_from_ref(r: &T) -> *const T { + r }