148148//! fn new() -> impl PinInit<Self, Error> {
149149//! try_pin_init!(Self {
150150//! status <- CMutex::new(0),
151- //! buffer: Box::init(pin_init::zeroed ())?,
151+ //! buffer: Box::init(pin_init::init_zeroed ())?,
152152//! }? Error)
153153//! }
154154//! }
@@ -742,7 +742,7 @@ macro_rules! stack_try_pin_init {
742742/// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
743743/// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
744744/// pointer named `this` inside of the initializer.
745- /// - Using struct update syntax one can place `..Zeroable::zeroed ()` at the very end of the
745+ /// - Using struct update syntax one can place `..Zeroable::init_zeroed ()` at the very end of the
746746/// struct, this initializes every field with 0 and then runs all initializers specified in the
747747/// body. This can only be done if [`Zeroable`] is implemented for the struct.
748748///
@@ -769,7 +769,7 @@ macro_rules! stack_try_pin_init {
769769/// });
770770/// let init = pin_init!(Buf {
771771/// buf: [1; 64],
772- /// ..Zeroable::zeroed ()
772+ /// ..Zeroable::init_zeroed ()
773773/// });
774774/// ```
775775///
@@ -805,7 +805,7 @@ macro_rules! pin_init {
805805/// ```rust
806806/// # #![feature(allocator_api)]
807807/// # #[path = "../examples/error.rs"] mod error; use error::Error;
808- /// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed };
808+ /// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, init_zeroed };
809809///
810810/// #[pin_data]
811811/// struct BigBuf {
@@ -817,7 +817,7 @@ macro_rules! pin_init {
817817/// impl BigBuf {
818818/// fn new() -> impl PinInit<Self, Error> {
819819/// try_pin_init!(Self {
820- /// big: Box::init(zeroed ())?,
820+ /// big: Box::init(init_zeroed ())?,
821821/// small: [0; 1024 * 1024],
822822/// ptr: core::ptr::null_mut(),
823823/// }? Error)
@@ -866,7 +866,7 @@ macro_rules! try_pin_init {
866866/// # #[path = "../examples/error.rs"] mod error; use error::Error;
867867/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
868868/// # use pin_init::InPlaceInit;
869- /// use pin_init::{init, Init, zeroed };
869+ /// use pin_init::{init, Init, init_zeroed };
870870///
871871/// struct BigBuf {
872872/// small: [u8; 1024 * 1024],
@@ -875,7 +875,7 @@ macro_rules! try_pin_init {
875875/// impl BigBuf {
876876/// fn new() -> impl Init<Self> {
877877/// init!(Self {
878- /// small <- zeroed (),
878+ /// small <- init_zeroed (),
879879/// })
880880/// }
881881/// }
@@ -913,7 +913,7 @@ macro_rules! init {
913913/// # #![feature(allocator_api)]
914914/// # use core::alloc::AllocError;
915915/// # use pin_init::InPlaceInit;
916- /// use pin_init::{try_init, Init, zeroed };
916+ /// use pin_init::{try_init, Init, init_zeroed };
917917///
918918/// struct BigBuf {
919919/// big: Box<[u8; 1024 * 1024 * 1024]>,
@@ -923,7 +923,7 @@ macro_rules! init {
923923/// impl BigBuf {
924924/// fn new() -> impl Init<Self, AllocError> {
925925/// try_init!(Self {
926- /// big: Box::init(zeroed ())?,
926+ /// big: Box::init(init_zeroed ())?,
927927/// small: [0; 1024 * 1024],
928928/// }? AllocError)
929929/// }
@@ -1170,7 +1170,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
11701170 ///
11711171 /// ```rust
11721172 /// # #![expect(clippy::disallowed_names)]
1173- /// use pin_init::{init, zeroed , Init};
1173+ /// use pin_init::{init, init_zeroed , Init};
11741174 ///
11751175 /// struct Foo {
11761176 /// buf: [u8; 1_000_000],
@@ -1183,7 +1183,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
11831183 /// }
11841184 ///
11851185 /// let foo = init!(Foo {
1186- /// buf <- zeroed ()
1186+ /// buf <- init_zeroed ()
11871187 /// }).chain(|foo| {
11881188 /// foo.setup();
11891189 /// Ok(())
@@ -1495,7 +1495,45 @@ pub unsafe trait PinnedDrop: __internal::HasPinData {
14951495/// ```rust,ignore
14961496/// let val: Self = unsafe { core::mem::zeroed() };
14971497/// ```
1498- pub unsafe trait Zeroable { }
1498+ pub unsafe trait Zeroable {
1499+ /// Create a new zeroed `Self`.
1500+ ///
1501+ /// The returned initializer will write `0x00` to every byte of the given `slot`.
1502+ #[ inline]
1503+ fn init_zeroed ( ) -> impl Init < Self >
1504+ where
1505+ Self : Sized ,
1506+ {
1507+ init_zeroed ( )
1508+ }
1509+
1510+ /// Create a `Self` consisting of all zeroes.
1511+ ///
1512+ /// Whenever a type implements [`Zeroable`], this function should be preferred over
1513+ /// [`core::mem::zeroed()`] or using `MaybeUninit<T>::zeroed().assume_init()`.
1514+ ///
1515+ /// # Examples
1516+ ///
1517+ /// ```
1518+ /// use pin_init::{Zeroable, zeroed};
1519+ ///
1520+ /// #[derive(Zeroable)]
1521+ /// struct Point {
1522+ /// x: u32,
1523+ /// y: u32,
1524+ /// }
1525+ ///
1526+ /// let point: Point = zeroed();
1527+ /// assert_eq!(point.x, 0);
1528+ /// assert_eq!(point.y, 0);
1529+ /// ```
1530+ fn zeroed ( ) -> Self
1531+ where
1532+ Self : Sized ,
1533+ {
1534+ zeroed ( )
1535+ }
1536+ }
14991537
15001538/// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
15011539/// `None` to that location.
@@ -1508,11 +1546,21 @@ pub unsafe trait ZeroableOption {}
15081546// SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
15091547unsafe impl < T : ZeroableOption > Zeroable for Option < T > { }
15101548
1511- /// Create a new zeroed T.
1549+ // SAFETY: `Option<&T>` is part of the option layout optimization guarantee:
1550+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1551+ unsafe impl < T > ZeroableOption for & T { }
1552+ // SAFETY: `Option<&mut T>` is part of the option layout optimization guarantee:
1553+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1554+ unsafe impl < T > ZeroableOption for & mut T { }
1555+ // SAFETY: `Option<NonNull<T>>` is part of the option layout optimization guarantee:
1556+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1557+ unsafe impl < T > ZeroableOption for NonNull < T > { }
1558+
1559+ /// Create an initializer for a zeroed `T`.
15121560///
15131561/// The returned initializer will write `0x00` to every byte of the given `slot`.
15141562#[ inline]
1515- pub fn zeroed < T : Zeroable > ( ) -> impl Init < T > {
1563+ pub fn init_zeroed < T : Zeroable > ( ) -> impl Init < T > {
15161564 // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
15171565 // and because we write all zeroes, the memory is initialized.
15181566 unsafe {
@@ -1523,6 +1571,31 @@ pub fn zeroed<T: Zeroable>() -> impl Init<T> {
15231571 }
15241572}
15251573
1574+ /// Create a `T` consisting of all zeroes.
1575+ ///
1576+ /// Whenever a type implements [`Zeroable`], this function should be preferred over
1577+ /// [`core::mem::zeroed()`] or using `MaybeUninit<T>::zeroed().assume_init()`.
1578+ ///
1579+ /// # Examples
1580+ ///
1581+ /// ```
1582+ /// use pin_init::{Zeroable, zeroed};
1583+ ///
1584+ /// #[derive(Zeroable)]
1585+ /// struct Point {
1586+ /// x: u32,
1587+ /// y: u32,
1588+ /// }
1589+ ///
1590+ /// let point: Point = zeroed();
1591+ /// assert_eq!(point.x, 0);
1592+ /// assert_eq!(point.y, 0);
1593+ /// ```
1594+ pub const fn zeroed < T : Zeroable > ( ) -> T {
1595+ // SAFETY:By the type invariants of `Zeroable`, all zeroes is a valid bit pattern for `T`.
1596+ unsafe { core:: mem:: zeroed ( ) }
1597+ }
1598+
15261599macro_rules! impl_zeroable {
15271600 ( $( $( { $( $generics: tt) * } ) ? $t: ty, ) * ) => {
15281601 // SAFETY: Safety comments written in the macro invocation.
@@ -1560,7 +1633,6 @@ impl_zeroable! {
15601633 Option <NonZeroU128 >, Option <NonZeroUsize >,
15611634 Option <NonZeroI8 >, Option <NonZeroI16 >, Option <NonZeroI32 >, Option <NonZeroI64 >,
15621635 Option <NonZeroI128 >, Option <NonZeroIsize >,
1563- { <T >} Option <NonNull <T >>,
15641636
15651637 // SAFETY: `null` pointer is valid.
15661638 //
@@ -1590,6 +1662,22 @@ macro_rules! impl_tuple_zeroable {
15901662
15911663impl_tuple_zeroable ! ( A , B , C , D , E , F , G , H , I , J ) ;
15921664
1665+ macro_rules! impl_fn_zeroable_option {
1666+ ( [ $( $abi: literal) ,* $( , ) ?] $args: tt) => {
1667+ $( impl_fn_zeroable_option!( { extern $abi} $args) ; ) *
1668+ $( impl_fn_zeroable_option!( { unsafe extern $abi} $args) ; ) *
1669+ } ;
1670+ ( { $( $prefix: tt) * } { $( , ) ?} ) => { } ;
1671+ ( { $( $prefix: tt) * } { $ret: ident, $( $rest: ident) ,* $( , ) ?} ) => {
1672+ // SAFETY: function pointers are part of the option layout optimization:
1673+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1674+ unsafe impl <$ret, $( $rest) ,* > ZeroableOption for $( $prefix) * fn ( $( $rest) ,* ) -> $ret { }
1675+ impl_fn_zeroable_option!( { $( $prefix) * } { $( $rest) ,* , } ) ;
1676+ } ;
1677+ }
1678+
1679+ impl_fn_zeroable_option ! ( [ "Rust" , "C" ] { A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q , R , S , T , U } ) ;
1680+
15931681/// This trait allows creating an instance of `Self` which contains exactly one
15941682/// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
15951683///
0 commit comments