Re: [PATCH v3 03/16] rust: mem: add `AsRepr` and `AsReprMut`

"Alexandre Courbot" <[email protected]>
Newsgroups dev.linux.lists.nova-gpu,dev.linux.lists.driver-core,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
On Wed Aug 19, 2026 at 8:09 PM JST, Gary Guo wrote:
> Some API like atomics and I/O operate on primitives only; therefore other
> types would need to converted to these primitive first. Add two traits
> `AsRepr` and `AsReprMut` to indicate that the type can be turned into a
> primitive for these operations.
>
> Conceptually, `T: AsRepr` means that `&T` can be viewed as `&T::Repr` and
> thus it has only a round-trip transmutability requirement. `T: AsReprMut`
> means that `&mut T` can be viewed as `&mut T::Repr` and thus it needs to
> support bi-directional transmutability.
>
> To avoid duplicating implementation, all repr types are normalized to
> unsigned integers.
>
> Signed-off-by: Gary Guo <[email protected]>
> ---
>  rust/kernel/mem.rs | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 148 insertions(+)
>
> diff --git a/rust/kernel/mem.rs b/rust/kernel/mem.rs
> index a0901cbe1b2d..5bce381d8895 100644
> --- a/rust/kernel/mem.rs
> +++ b/rust/kernel/mem.rs
> @@ -35,3 +35,151 @@ pub const fn transmute<Src: IntoBytes, Dst: FromBytes>(val: Src) -> Dst {
>      // SAFETY: transmute is safe with `IntoBytes` and `FromBytes` bounds.
>      unsafe { transmute_unchecked(val) }
>  }
> +
> +/// Type that is layout-compatible with a primitive representation.
> +///
> +/// # Round-trip transmutability
> +///
> +/// `T` is round-trip transmutable to `U` if and only if both of these properties hold:
> +///
> +/// - Any valid bit pattern for `T` is also a valid bit pattern for `U`.
> +/// - Transmuting a value of type `T` to `U` and then to `T` again
> +///   yields a value that is in all aspects equivalent to the original value.
> +///
> +/// # Safety
> +///
> +/// - [`Self`] must have the same size and alignment as [`Self::Repr`].
> +/// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
> +///
> +/// [round-trip transmutable]: AsRepr#round-trip-transmutability
> +pub unsafe trait AsRepr: Sized {

I'm a bit confused by the naming of this trait - the commit message
mentions that it means that "`&T` can be viewed as `&T::Repr`", but such
a method doesn't exist. Instead we have an `AsRepr` trait with an
`into_repr` method that makes a copy.

Can we either rename this to `IntoRepr` (and `AsReprMut` into `FromRepr`
I guess?), or maybe better, have `fn as_repr(this: &Self) ->
&Self::Repr` (on top of which `into_repr` could be implemented if
useful) so the names of the trait and provided method align, while also
making the commit message match the actual API? I haven't tried but
since all the representations we are working with are primitives that
implement `Copy`, I intuitively think it should work just as well.

Same would apply to `AsReprMut`.

Since this is becoming core infrastructure, I guess `as_repr` will also
become valuable when we want to do in-place access (with e.g. atomics)
or use it with larger types that we don't want to copy.

> +    /// Primitive representation of this type.
> +    type Repr;
> +
> +    /// Convert from [`AsRepr::Repr`] to `Self`.
> +    ///
> +    /// # Safety
> +    ///
> +    /// `repr` must be a valid bit patern of `Self`. If `repr` is previously obtained using

nit: s/patern/pattern.

> +    /// [`AsRepr::into_repr`], then it will always be safe.
> +    #[inline(always)]
> +    unsafe fn from_repr_unchecked(repr: Self::Repr) -> Self {
> +        // SAFETY: Per safety requirement of the trait.

"... of the trait and method" maybe?

> +        unsafe { transmute_unchecked(repr) }
> +    }
> +
> +    /// Convert from `Self` to [`AsRepr::Repr`].
> +    #[inline(always)]
> +    fn into_repr(this: Self) -> Self::Repr {
> +        // SAFETY: Per safety requirement of the trait.
> +        unsafe { transmute_unchecked(this) }
> +    }
> +}
> +
> +/// Type that is bi-directionally transmutable with a primitive representation.
> +///
> +/// # Safety
> +///
> +/// - [`Self`] must be [transmutable] from [`Self::Repr`].

nit: missing backticks on [transmutable].

<...>
> +#[cfg(target_pointer_width = "32")]
> +const _: () = {
> +    // SAFETY: usize has the same size and alignment with u32, and is round-trip transmutable to it.
> +    unsafe impl AsRepr for usize {
> +        type Repr = u32;
> +    }
> +
> +    // SAFETY: isize has the same size and alignment with u32, and is round-trip transmutable to it.
> +    unsafe impl AsRepr for isize {
> +        type Repr = u32;
> +    }
> +
> +    // SAFETY: usize is transmutable from u32.
> +    unsafe impl AsReprMut for usize {}
> +    // SAFETY: isize is transmutable from u32.
> +    unsafe impl AsReprMut for isize {}
> +};
> +
> +#[cfg(target_pointer_width = "64")]
> +const _: () = {
> +    // SAFETY: usize has the same size and alignment with u64, and is round-trip transmutable to it.
> +    unsafe impl AsRepr for usize {
> +        type Repr = u64;
> +    }
> +
> +    // SAFETY: isize has the same size and alignment with u64, and is round-trip transmutable to it.
> +    unsafe impl AsRepr for isize {
> +        type Repr = u64;
> +    }
> +
> +    // SAFETY: usize is transmutable from u64.
> +    unsafe impl AsReprMut for usize {}
> +    // SAFETY: isize is transmutable from u64.
> +    unsafe impl AsReprMut for isize {}
> +};

By making these available, aren't we running into the same
non-portability issue [1] that we discussed on the `casts` module?

[1] https://lore.kernel.org/all/[email protected]/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.