diff --git a/src/lib.rs b/src/lib.rs index 05a0cd6a..9ab34036 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -395,9 +395,10 @@ pub use ::pin_init_internal::pin_data; /// ``` pub use ::pin_init_internal::pinned_drop; -/// Derives the [`Zeroable`] trait for the given struct. +/// Derives the [`Zeroable`] trait for the given `struct` or `union`. /// -/// This can only be used for structs where every field implements the [`Zeroable`] trait. +/// This can only be used for `struct`s/`union`s where every field implements the [`Zeroable`] +/// trait. /// /// # Examples /// @@ -406,14 +407,25 @@ pub use ::pin_init_internal::pinned_drop; /// /// #[derive(Zeroable)] /// pub struct DriverData { -/// id: i64, +/// pub(crate) id: i64, /// buf_ptr: *mut u8, /// len: usize, /// } /// ``` +/// +/// ``` +/// use pin_init::Zeroable; +/// +/// #[derive(Zeroable)] +/// pub union SignCast { +/// signed: i64, +/// unsigned: u64, +/// } +/// ``` pub use ::pin_init_internal::Zeroable; -/// Derives the [`Zeroable`] trait for the given struct if all fields implement [`Zeroable`]. +/// Derives the [`Zeroable`] trait for the given `struct` or `union` if all fields implement +/// [`Zeroable`]. /// /// Contrary to the derive macro named [`macro@Zeroable`], this one silently fails when a field /// doesn't implement [`Zeroable`]. @@ -426,7 +438,7 @@ pub use ::pin_init_internal::Zeroable; /// // implmements `Zeroable` /// #[derive(MaybeZeroable)] /// pub struct DriverData { -/// id: i64, +/// pub(crate) id: i64, /// buf_ptr: *mut u8, /// len: usize, /// } @@ -434,7 +446,7 @@ pub use ::pin_init_internal::Zeroable; /// // does not implmement `Zeroable` /// #[derive(MaybeZeroable)] /// pub struct DriverData2 { -/// id: i64, +/// pub(crate) id: i64, /// buf_ptr: *mut u8, /// len: usize, /// // this field doesn't implement `Zeroable` @@ -1580,7 +1592,7 @@ impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J); /// }); /// ``` pub trait Wrapper { - /// Create an pin-initializer for a [`Self`] containing `T` form the `value_init` initializer. + /// Creates an pin-initializer for a [`Self`] containing `T` from the `value_init` initializer. fn pin_init(value_init: impl PinInit) -> impl PinInit; } diff --git a/tests/ui/compile-fail/zeroable/not_all_fields_zeroable.rs b/tests/ui/compile-fail/zeroable/not_all_fields_zeroable.rs new file mode 100644 index 00000000..b13c726f --- /dev/null +++ b/tests/ui/compile-fail/zeroable/not_all_fields_zeroable.rs @@ -0,0 +1,10 @@ +extern crate pin_init; +use pin_init::*; + +#[derive(Zeroable)] +struct Foo { + a: usize, + b: &'static Foo, +} + +fn main() {} diff --git a/tests/ui/compile-fail/zeroable/not_all_fields_zeroable.stderr b/tests/ui/compile-fail/zeroable/not_all_fields_zeroable.stderr new file mode 100644 index 00000000..67b63241 --- /dev/null +++ b/tests/ui/compile-fail/zeroable/not_all_fields_zeroable.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `&'static Foo: pin_init::Zeroable` is not satisfied + --> tests/ui/compile-fail/zeroable/not_all_fields_zeroable.rs:7:8 + | +7 | b: &'static Foo, + | ^^^^^^^^^^^^ the trait `pin_init::Zeroable` is not implemented for `&'static Foo` + | +note: required by a bound in `assert_zeroable` + --> tests/ui/compile-fail/zeroable/not_all_fields_zeroable.rs:4:10 + | +4 | #[derive(Zeroable)] + | ^^^^^^^^ required by this bound in `assert_zeroable` + = note: this error originates in the macro `::pin_init::__derive_zeroable` which comes from the expansion of the derive macro `Zeroable` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the leading `&`-reference + | +7 - b: &'static Foo, +7 + b: Foo, + | diff --git a/tests/ui/expand/zeroable.expanded.rs b/tests/ui/expand/zeroable.expanded.rs new file mode 100644 index 00000000..4f9d174c --- /dev/null +++ b/tests/ui/expand/zeroable.expanded.rs @@ -0,0 +1,42 @@ +use pin_init::*; +struct Foo { + a: usize, + pub(crate) b: usize, +} +#[automatically_derived] +unsafe impl ::pin_init::Zeroable for Foo {} +const _: () = { + fn assert_zeroable() {} + fn ensure_zeroable() { + assert_zeroable::(); + assert_zeroable::(); + } +}; +struct Bar { + a: usize, + b: &'static usize, +} +#[automatically_derived] +unsafe impl ::pin_init::Zeroable for Bar +where + usize: for<'__dummy> ::pin_init::Zeroable, + &'static usize: for<'__dummy> ::pin_init::Zeroable, +{} +trait Trait {} +struct WithGenerics<'a, T, U: Trait> { + a: T, + u: &'a U, +} +#[automatically_derived] +unsafe impl< + 'a, + T: ::pin_init::Zeroable, + U: ::pin_init::Zeroable + Trait, +> ::pin_init::Zeroable for WithGenerics<'a, T, U> {} +const _: () = { + fn assert_zeroable() {} + fn ensure_zeroable<'a, T: ::pin_init::Zeroable, U: ::pin_init::Zeroable + Trait>() { + assert_zeroable::(); + assert_zeroable::<&'a U>(); + } +}; diff --git a/tests/ui/expand/zeroable.rs b/tests/ui/expand/zeroable.rs new file mode 100644 index 00000000..95cad22c --- /dev/null +++ b/tests/ui/expand/zeroable.rs @@ -0,0 +1,21 @@ +use pin_init::*; + +#[derive(Zeroable)] +struct Foo { + a: usize, + pub(crate) b: usize, +} + +#[derive(MaybeZeroable)] +struct Bar { + a: usize, + b: &'static usize, +} + +trait Trait {} + +#[derive(Zeroable)] +struct WithGenerics<'a, T, U: Trait> { + a: T, + u: &'a U, +}