rust: pin-init: allow `Zeroable` derive macro to also be applied to unions
authorBenno Lossin <benno.lossin@proton.me>
Mon, 21 Apr 2025 22:18:41 +0000 (22:18 +0000)
committerBenno Lossin <benno.lossin@proton.me>
Thu, 1 May 2025 16:15:12 +0000 (18:15 +0200)
Enabling the same behavior for unions as for structs is correct, but
could be relaxed: the valid bit patterns for unions are the union of all
valid bit patterns of their fields. So for a union to implement
`Zeroable`, only a single field needs to implement `Zeroable`. This can
be a future improvement, as it is currently only needed for unions where
all fields implement `Zeroable`.

There is no danger for mis-parsing with the two optional tokens (ie
neither one or both tokens are parsed), as the compiler will already
have rejected that before giving it as the input to the derive macro.

Link: https://github.com/Rust-for-Linux/pin-init/pull/42/commits/5927b497ce522d82f6c082d5ba9235df57bfdb32
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
rust/pin-init/src/macros.rs

index e4054fe3ed3df79f3c5a0e497f18bfe50f4d8c66..332d7e08925bed69bf9294985c9ce8900f87a030 100644 (file)
@@ -1412,4 +1412,34 @@ macro_rules! __derive_zeroable {
             }
         };
     };
+    (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
+            $($($whr)*)?
+        {}
+        const _: () = {
+            fn assert_zeroable<T: ?::core::marker::Sized + $crate::Zeroable>() {}
+            fn ensure_zeroable<$($impl_generics)*>()
+                where $($($whr)*)?
+            {
+                $(assert_zeroable::<$field_ty>();)*
+            }
+        };
+    };
 }