Skip to content

Commit 0afee65

Browse files
authored
Clarify safety properties of casts between [MaybeUninit<T>] <-> [T]. (#431)
Reduce the scope of the `unsafe` blocks to the unsafe operations.
1 parent 1390386 commit 0afee65

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

src/util.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ use core::{mem::MaybeUninit, ptr};
55
/// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have
66
/// been initialized.
77
#[inline(always)]
8+
#[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this.
89
pub unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
10+
let ptr = ptr_from_mut::<[MaybeUninit<T>]>(slice) as *mut [T];
911
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
10-
&mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
12+
unsafe { &mut *ptr }
1113
}
1214

1315
#[inline]
@@ -18,18 +20,29 @@ pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
1820

1921
#[inline(always)]
2022
pub fn slice_as_uninit<T>(slice: &[T]) -> &[MaybeUninit<T>] {
23+
let ptr = ptr_from_ref::<[T]>(slice) as *const [MaybeUninit<T>];
2124
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
22-
// There is no risk of writing a `MaybeUninit<T>` into the result since
23-
// the result isn't mutable.
24-
unsafe { &*(slice as *const [T] as *const [MaybeUninit<T>]) }
25+
unsafe { &*ptr }
2526
}
2627

2728
/// View an mutable initialized array as potentially-uninitialized.
2829
///
2930
/// This is unsafe because it allows assigning uninitialized values into
3031
/// `slice`, which would be undefined behavior.
3132
#[inline(always)]
33+
#[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this.
3234
pub unsafe fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
35+
let ptr = ptr_from_mut::<[T]>(slice) as *mut [MaybeUninit<T>];
3336
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
34-
&mut *(slice as *mut [T] as *mut [MaybeUninit<T>])
37+
unsafe { &mut *ptr }
38+
}
39+
40+
// TODO: MSRV(1.76.0): Replace with `core::ptr::from_mut`.
41+
fn ptr_from_mut<T: ?Sized>(r: &mut T) -> *mut T {
42+
r
43+
}
44+
45+
// TODO: MSRV(1.76.0): Replace with `core::ptr::from_ref`.
46+
fn ptr_from_ref<T: ?Sized>(r: &T) -> *const T {
47+
r
3548
}

0 commit comments

Comments
 (0)