summaryrefslogtreecommitdiff
path: root/rust/pin-init/src
diff options
context:
space:
mode:
authorBenno Lossin <benno.lossin@proton.me>2025-04-21 22:18:52 +0000
committerBenno Lossin <benno.lossin@proton.me>2025-05-01 18:15:26 +0200
commit00fccd3ecc2129ee32fd181079eb643f497044c4 (patch)
tree1557f9b7fe9329067606344d6b40ded549150b24 /rust/pin-init/src
parenta313d41a2b515bbb76d56df490b731ff6d64e571 (diff)
rust: pin-init: add `MaybeZeroable` derive macro
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. 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>
Diffstat (limited to 'rust/pin-init/src')
-rw-r--r--rust/pin-init/src/lib.rs30
-rw-r--r--rust/pin-init/src/macros.rs59
2 files changed, 89 insertions, 0 deletions
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::pinned_drop;
/// ```
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 @@ macro_rules! __derive_zeroable {
};
};
}
+
+#[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)*)?
+ {}
+ };
+}