Rollup merge of #149110 - Paladynee:acp/ptr_cast_slice, r=jhpratt

Implement `cast_slice` for raw pointer types

Tracking issue: https://github.com/rust-lang/rust/issues/149103

This PR implements the method `cast_slice` that defers to the respective `slice_from_raw_parts` call for `*const T`, `*mut T` and `NonNull<T>`, and copies over their documentation.
```rust
impl<T> *const T {
    pub const fn cast_slice(self, len: usize) -> *const [T];
}
impl<T> *mut T {
    pub const fn cast_slice(self, len: usize) -> *mut [T];
}
impl<T> NonNull<T> {
    pub const fn cast_slice(self, len: usize) -> NonNull<[T]>;
}
```
This commit is contained in:
Stuart Cook 2026-01-29 19:03:31 +11:00 committed by GitHub
commit 034b53c863
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 111 additions and 0 deletions

View file

@ -1386,6 +1386,43 @@ impl<T> *const T {
pub const fn cast_uninit(self) -> *const MaybeUninit<T> {
self as _
}
/// Forms a raw slice from a pointer and a length.
///
/// The `len` argument is the number of **elements**, not the number of bytes.
///
/// This function is safe, but actually using the return value is unsafe.
/// See the documentation of [`slice::from_raw_parts`] for slice safety requirements.
///
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
///
/// # Examples
///
/// ```rust
/// #![feature(ptr_cast_slice)]
/// // create a slice pointer when starting out with a pointer to the first element
/// let x = [5, 6, 7];
/// let raw_pointer = x.as_ptr();
/// let slice = raw_pointer.cast_slice(3);
/// assert_eq!(unsafe { &*slice }[2], 7);
/// ```
///
/// You must ensure that the pointer is valid and not null before dereferencing
/// the raw slice. A slice reference must never have a null pointer, even if it's empty.
///
/// ```rust,should_panic
/// #![feature(ptr_cast_slice)]
/// use std::ptr;
/// let danger: *const [u8] = ptr::null::<u8>().cast_slice(0);
/// unsafe {
/// danger.as_ref().expect("references must not be null");
/// }
/// ```
#[inline]
#[unstable(feature = "ptr_cast_slice", issue = "149103")]
pub const fn cast_slice(self, len: usize) -> *const [T] {
slice_from_raw_parts(self, len)
}
}
impl<T> *const MaybeUninit<T> {
/// Casts from a maybe-uninitialized type to its initialized version.

View file

@ -1655,6 +1655,51 @@ impl<T> *mut T {
pub const fn cast_uninit(self) -> *mut MaybeUninit<T> {
self as _
}
/// Forms a raw mutable slice from a pointer and a length.
///
/// The `len` argument is the number of **elements**, not the number of bytes.
///
/// Performs the same functionality as [`cast_slice`] on a `*const T`, except that a
/// raw mutable slice is returned, as opposed to a raw immutable slice.
///
/// This function is safe, but actually using the return value is unsafe.
/// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements.
///
/// [`slice::from_raw_parts_mut`]: crate::slice::from_raw_parts_mut
/// [`cast_slice`]: pointer::cast_slice
///
/// # Examples
///
/// ```rust
/// #![feature(ptr_cast_slice)]
///
/// let x = &mut [5, 6, 7];
/// let slice = x.as_mut_ptr().cast_slice(3);
///
/// unsafe {
/// (*slice)[2] = 99; // assign a value at an index in the slice
/// };
///
/// assert_eq!(unsafe { &*slice }[2], 99);
/// ```
///
/// You must ensure that the pointer is valid and not null before dereferencing
/// the raw slice. A slice reference must never have a null pointer, even if it's empty.
///
/// ```rust,should_panic
/// #![feature(ptr_cast_slice)]
/// use std::ptr;
/// let danger: *mut [u8] = ptr::null_mut::<u8>().cast_slice(0);
/// unsafe {
/// danger.as_mut().expect("references must not be null");
/// }
/// ```
#[inline]
#[unstable(feature = "ptr_cast_slice", issue = "149103")]
pub const fn cast_slice(self, len: usize) -> *mut [T] {
slice_from_raw_parts_mut(self, len)
}
}
impl<T> *mut MaybeUninit<T> {
/// Casts from a maybe-uninitialized type to its initialized version.

View file

@ -1377,6 +1377,35 @@ impl<T> NonNull<T> {
pub const fn cast_uninit(self) -> NonNull<MaybeUninit<T>> {
self.cast()
}
/// Creates a non-null raw slice from a thin pointer and a length.
///
/// The `len` argument is the number of **elements**, not the number of bytes.
///
/// This function is safe, but dereferencing the return value is unsafe.
/// See the documentation of [`slice::from_raw_parts`] for slice safety requirements.
///
/// # Examples
///
/// ```rust
/// #![feature(ptr_cast_slice)]
/// use std::ptr::NonNull;
///
/// // create a slice pointer when starting out with a pointer to the first element
/// let mut x = [5, 6, 7];
/// let nonnull_pointer = NonNull::new(x.as_mut_ptr()).unwrap();
/// let slice = nonnull_pointer.cast_slice(3);
/// assert_eq!(unsafe { slice.as_ref()[2] }, 7);
/// ```
///
/// (Note that this example artificially demonstrates a use of this method,
/// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.)
#[inline]
#[must_use]
#[unstable(feature = "ptr_cast_slice", issue = "149103")]
pub const fn cast_slice(self, len: usize) -> NonNull<[T]> {
NonNull::slice_from_raw_parts(self, len)
}
}
impl<T> NonNull<MaybeUninit<T>> {
/// Casts from a maybe-uninitialized type to its initialized version.