bytemuck

Derive Macro Zeroable

Source
#[derive(Zeroable)]
{
    // Attributes available to this derive:
    #[bytemuck]
    #[zeroable]
}
Expand description

Derive the Zeroable trait for a type.

The macro ensures that the type follows all the the safety requirements for the Zeroable trait.

The following constraints need to be satisfied for the macro to succeed on a struct:

  • All fields in the struct must implement Zeroable

The following constraints need to be satisfied for the macro to succeed on an enum:

  • The enum has an explicit #[repr(Int)], #[repr(C)], or #[repr(C, Int)].
  • The enum has a variant with discriminant 0 (explicitly or implicitly).
  • All fields in the variant with discriminant 0 (if any) must implement Zeroable

The macro always succeeds on unions.

§Example

#[derive(Copy, Clone, Zeroable)]
#[repr(C)]
struct Test {
  a: u16,
  b: u16,
}
#[derive(Copy, Clone, Zeroable)]
#[repr(i32)]
enum Values {
  A = 0,
  B = 1,
  C = 2,
}
#[derive(Clone, Zeroable)]
#[repr(C)]
enum Implicit {
  A(bool, u8, char),
  B(String),
  C(std::num::NonZeroU8),
}

§Custom bounds

Custom bounds for the derived Zeroable impl can be given using the #[zeroable(bound = "")] helper attribute.

Using this attribute additionally opts-in to “perfect derive” semantics, where instead of adding bounds for each generic type parameter, bounds are added for each field’s type.

§Examples

#[derive(Clone, Zeroable)]
#[zeroable(bound = "")]
struct AlwaysZeroable<T> {
  a: PhantomData<T>,
}

AlwaysZeroable::<std::num::NonZeroU8>::zeroed();
#[derive(Copy, Clone, Zeroable)]
#[repr(u8)]
#[zeroable(bound = "")]
enum MyOption<T> {
  None,
  Some(T),
}

assert!(matches!(MyOption::<std::num::NonZeroU8>::zeroed(), MyOption::None));
#[derive(Clone, Zeroable)]
#[zeroable(bound = "T: Copy")]
struct ZeroableWhenTIsCopy<T> {
  a: PhantomData<T>,
}

ZeroableWhenTIsCopy::<String>::zeroed();

The restriction that all fields must be Zeroable is still applied, and this is enforced using the mentioned “perfect derive” semantics.

#[derive(Clone, Zeroable)]
#[zeroable(bound = "")]
struct ZeroableWhenTIsZeroable<T> {
  a: T,
}
ZeroableWhenTIsZeroable::<u32>::zeroed();
ZeroableWhenTIsZeroable::<String>::zeroed();