From: Boqun Feng <boqun.feng@gmail.com>
To: Benno Lossin <benno.lossin@proton.me>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Fiona Behrens" <me@kloenk.dev>,
"Christian Schrefl" <chrisi.schrefl@gmail.com>,
"Alban Kurti" <kurti@invicto.ai>,
"Michael Vetter" <jubalh@iodoru.org>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 8/8] rust: pin-init: add `MaybeZeroable` derive macro
Date: Mon, 21 Apr 2025 21:54:11 -0700 [thread overview]
Message-ID: <aAcg86QfvlA0zAh4@Mac.home> (raw)
In-Reply-To: <20250421221728.528089-9-benno.lossin@proton.me>
On Mon, Apr 21, 2025 at 10:18:52PM +0000, Benno Lossin wrote:
> This derive macro implements `Zeroable` for structs & unions precisely
> if all fields also implement `Zeroable` and does nothing otherwise. The
> plain `Zeroable` derive macro instead errors when it cannot derive
> `Zeroable` safely. The `MaybeZeroable` derive macro is useful in cases
> where manual checking is infeasible such as with the bindings crate.
>
Hmm... seems we need a customized auto trait? How hard would that be?
Regards,
Boqun
> Move the zeroable generics parsing into a standalone function in order
> to avoid code duplication between the two derive macros.
>
> Link: https://github.com/Rust-for-Linux/pin-init/pull/42/commits/1165cdad1a391b923efaf30cf76bc61e38da022e
> Signed-off-by: Benno Lossin <benno.lossin@proton.me>
> ---
> rust/pin-init/internal/src/lib.rs | 5 +++
> rust/pin-init/internal/src/zeroable.rs | 27 +++++++++++-
> rust/pin-init/src/lib.rs | 30 +++++++++++++
> rust/pin-init/src/macros.rs | 59 ++++++++++++++++++++++++++
> 4 files changed, 120 insertions(+), 1 deletion(-)
>
> diff --git a/rust/pin-init/internal/src/lib.rs b/rust/pin-init/internal/src/lib.rs
> index 56aa9ecc1e1a..297b0129a5bf 100644
> --- a/rust/pin-init/internal/src/lib.rs
> +++ b/rust/pin-init/internal/src/lib.rs
> @@ -47,3 +47,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
> pub fn derive_zeroable(input: TokenStream) -> TokenStream {
> zeroable::derive(input.into()).into()
> }
> +
> +#[proc_macro_derive(MaybeZeroable)]
> +pub fn maybe_derive_zeroable(input: TokenStream) -> TokenStream {
> + zeroable::maybe_derive(input.into()).into()
> +}
> diff --git a/rust/pin-init/internal/src/zeroable.rs b/rust/pin-init/internal/src/zeroable.rs
> index acc94008c152..e0ed3998445c 100644
> --- a/rust/pin-init/internal/src/zeroable.rs
> +++ b/rust/pin-init/internal/src/zeroable.rs
> @@ -6,7 +6,14 @@
> use crate::helpers::{parse_generics, Generics};
> use proc_macro::{TokenStream, TokenTree};
>
> -pub(crate) fn derive(input: TokenStream) -> TokenStream {
> +pub(crate) fn parse_zeroable_derive_input(
> + input: TokenStream,
> +) -> (
> + Vec<TokenTree>,
> + Vec<TokenTree>,
> + Vec<TokenTree>,
> + Option<TokenTree>,
> +) {
> let (
> Generics {
> impl_generics,
> @@ -64,6 +71,11 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
> if in_generic && !inserted {
> new_impl_generics.extend(quote! { : ::pin_init::Zeroable });
> }
> + (rest, new_impl_generics, ty_generics, last)
> +}
> +
> +pub(crate) fn derive(input: TokenStream) -> TokenStream {
> + let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input);
> quote! {
> ::pin_init::__derive_zeroable!(
> parse_input:
> @@ -74,3 +86,16 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
> );
> }
> }
> +
> +pub(crate) fn maybe_derive(input: TokenStream) -> TokenStream {
> + let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input);
> + quote! {
> + ::pin_init::__maybe_derive_zeroable!(
> + parse_input:
> + @sig(#(#rest)*),
> + @impl_generics(#(#new_impl_generics)*),
> + @ty_generics(#(#ty_generics)*),
> + @body(#last),
> + );
> + }
> +}
> diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
> index 774f8ca033bc..05a0cd6ad8f4 100644
> --- a/rust/pin-init/src/lib.rs
> +++ b/rust/pin-init/src/lib.rs
> @@ -413,6 +413,36 @@
> /// ```
> pub use ::pin_init_internal::Zeroable;
>
> +/// Derives the [`Zeroable`] trait for the given struct if all fields implement [`Zeroable`].
> +///
> +/// Contrary to the derive macro named [`macro@Zeroable`], this one silently fails when a field
> +/// doesn't implement [`Zeroable`].
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use pin_init::MaybeZeroable;
> +///
> +/// // implmements `Zeroable`
> +/// #[derive(MaybeZeroable)]
> +/// pub struct DriverData {
> +/// id: i64,
> +/// buf_ptr: *mut u8,
> +/// len: usize,
> +/// }
> +///
> +/// // does not implmement `Zeroable`
> +/// #[derive(MaybeZeroable)]
> +/// pub struct DriverData2 {
> +/// id: i64,
> +/// buf_ptr: *mut u8,
> +/// len: usize,
> +/// // this field doesn't implement `Zeroable`
> +/// other_data: &'static i32,
> +/// }
> +/// ```
> +pub use ::pin_init_internal::MaybeZeroable;
> +
> /// Initialize and pin a type directly on the stack.
> ///
> /// # Examples
> diff --git a/rust/pin-init/src/macros.rs b/rust/pin-init/src/macros.rs
> index 332d7e08925b..935d77745d1d 100644
> --- a/rust/pin-init/src/macros.rs
> +++ b/rust/pin-init/src/macros.rs
> @@ -1443,3 +1443,62 @@ fn ensure_zeroable<$($impl_generics)*>()
> };
> };
> }
> +
> +#[doc(hidden)]
> +#[macro_export]
> +macro_rules! __maybe_derive_zeroable {
> + (parse_input:
> + @sig(
> + $(#[$($struct_attr:tt)*])*
> + $vis:vis struct $name:ident
> + $(where $($whr:tt)*)?
> + ),
> + @impl_generics($($impl_generics:tt)*),
> + @ty_generics($($ty_generics:tt)*),
> + @body({
> + $(
> + $(#[$($field_attr:tt)*])*
> + $field_vis:vis $field:ident : $field_ty:ty
> + ),* $(,)?
> + }),
> + ) => {
> + // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
> + #[automatically_derived]
> + unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
> + where
> + $(
> + // the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds`
> + // feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>.
> + $field_ty: for<'__dummy> $crate::Zeroable,
> + )*
> + $($($whr)*)?
> + {}
> + };
> + (parse_input:
> + @sig(
> + $(#[$($struct_attr:tt)*])*
> + $vis:vis union $name:ident
> + $(where $($whr:tt)*)?
> + ),
> + @impl_generics($($impl_generics:tt)*),
> + @ty_generics($($ty_generics:tt)*),
> + @body({
> + $(
> + $(#[$($field_attr:tt)*])*
> + $field_vis:vis $field:ident : $field_ty:ty
> + ),* $(,)?
> + }),
> + ) => {
> + // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
> + #[automatically_derived]
> + unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
> + where
> + $(
> + // the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds`
> + // feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>.
> + $field_ty: for<'__dummy> $crate::Zeroable,
> + )*
> + $($($whr)*)?
> + {}
> + };
> +}
> --
> 2.48.1
>
>
next prev parent reply other threads:[~2025-04-22 4:54 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-21 22:17 [PATCH 0/8] pin-init sync for v6.16 Benno Lossin
2025-04-21 22:17 ` [PATCH 1/8] rust: pin-init: add `cast_[pin_]init` functions to change the initialized type Benno Lossin
2025-04-22 6:56 ` Christian Schrefl
2025-04-21 22:17 ` [PATCH 2/8] rust: pin-init: Add the `Wrapper` trait Benno Lossin
2025-04-22 4:44 ` Boqun Feng
2025-04-21 22:18 ` [PATCH 3/8] rust: pin-init: Implement `Wrapper` for `UnsafePinned` behind feature flag Benno Lossin
2025-04-22 9:42 ` Christian Schrefl
2025-04-22 11:21 ` Benno Lossin
2025-04-22 14:17 ` Christian Schrefl
2025-04-21 22:18 ` [PATCH 4/8] rust: pin-init: Update Changelog and Readme Benno Lossin
2025-04-21 22:18 ` [PATCH 5/8] rust: pin-init: Update the structural pinning link in readme Benno Lossin
2025-04-21 22:18 ` [PATCH 6/8] rust: pin-init: allow `pub` fields in `derive(Zeroable)` Benno Lossin
2025-04-22 4:55 ` Boqun Feng
2025-04-22 8:30 ` Benno Lossin
2025-04-22 14:14 ` Boqun Feng
2025-04-22 14:45 ` Benno Lossin
2025-04-22 21:11 ` Boqun Feng
2025-04-22 21:56 ` Benno Lossin
2025-04-21 22:18 ` [PATCH 7/8] rust: pin-init: allow `Zeroable` derive macro to also be applied to unions Benno Lossin
2025-04-21 22:18 ` [PATCH 8/8] rust: pin-init: add `MaybeZeroable` derive macro Benno Lossin
2025-04-22 4:54 ` Boqun Feng [this message]
2025-04-22 7:56 ` Benno Lossin
2025-05-01 16:38 ` [PATCH 0/8] pin-init sync for v6.16 Benno Lossin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aAcg86QfvlA0zAh4@Mac.home \
--to=boqun.feng@gmail.com \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=chrisi.schrefl@gmail.com \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=jubalh@iodoru.org \
--cc=kurti@invicto.ai \
--cc=linux-kernel@vger.kernel.org \
--cc=me@kloenk.dev \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.