[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAJ-ks9m0=TRiq_6p_11xj3GjXJnPgrHYp9UByZt1HEHXyTorEg@mail.gmail.com>
Date: Mon, 21 Apr 2025 14:42:24 -0400
From: Tamir Duberstein <tamird@...il.com>
To: Benno Lossin <benno.lossin@...ton.me>
Cc: Simona Vetter <simona.vetter@...ll.ch>, Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Miguel Ojeda <ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Andreas Hindborg <a.hindborg@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>,
Trevor Gross <tmgross@...ch.edu>, Aliet Exposito Garcia <aliet.exposito@...il.com>,
Fiona Behrens <me@...enk.dev>, rust-for-linux@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH v3 1/4] rust: transmute: add `cast_slice[_mut]` functions
On Mon, Apr 21, 2025 at 9:50 AM Benno Lossin <benno.lossin@...ton.me> wrote:
>
> Add functions to make casting slices only one `unsafe` block.
>
> Signed-off-by: Benno Lossin <benno.lossin@...ton.me>
> ---
> rust/kernel/transmute.rs | 41 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 41 insertions(+)
>
> diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
> index 1c7d43771a37..242623bbb565 100644
> --- a/rust/kernel/transmute.rs
> +++ b/rust/kernel/transmute.rs
> @@ -2,6 +2,8 @@
>
> //! Traits for transmuting types.
>
> +use core::slice;
> +
> /// Types for which any bit pattern is valid.
> ///
> /// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
> @@ -69,3 +71,42 @@ macro_rules! impl_asbytes {
> {<T: AsBytes>} [T],
> {<T: AsBytes, const N: usize>} [T; N],
> }
> +
> +/// Casts the type of a slice to another.
> +///
> +/// # Examples
> +///
> +/// ```rust
> +/// # use kernel::transmute::cast_slice;
> +/// #[repr(transparent)]
> +/// #[derive(Debug)]
> +/// struct Container<T>(T);
> +///
> +/// let array = [0u32; 42];
> +/// let slice = &array;
> +/// // SAFETY: `Container<T>` transparently wraps a `T`.
> +/// let container_slice = unsafe { cast_slice(slice) };
> +/// pr_info!("{container_slice}");
> +/// ```
How can this example compile? The type of `container_slice` can't
possibly be known.
> +///
> +/// # Safety
> +/// - `T` and `U` must have the same layout.
> +pub unsafe fn cast_slice<T, U>(slice: &[T]) -> &[U] {
> + // CAST: by the safety requirements, `T` and `U` have the same layout.
> + let ptr = slice.as_ptr().cast::<U>();
> + // SAFETY: `ptr` and `len` come from the same slice reference.
> + unsafe { slice::from_raw_parts(ptr, slice.len()) }
> +}
> +
> +/// Casts the type of a slice to another.
> +///
> +/// Also see [`cast_slice`].
> +///
> +/// # Safety
> +/// - `T` and `U` must have the same layout.
> +pub unsafe fn cast_slice_mut<T, U>(slice: &mut [T]) -> &mut [U] {
> + // CAST: by the safety requirements, `T` and `U` have the same layout.
> + let ptr = slice.as_mut_ptr().cast::<U>();
> + // SAFETY: `ptr` and `len` come from the same slice reference.
> + unsafe { slice::from_raw_parts_mut(ptr, slice.len()) }
> +}
With the example fixed (or if I'm mistaken and it does compile):
Reviewed-by: Tamir Duberstein <tamird@...il.com>
Powered by blists - more mailing lists