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///
@@ -772,7 +772,7 @@ macro_rules! stack_try_pin_init {
772772/// });
773773/// let init = pin_init!(Buf {
774774/// buf: [1; 64],
775- /// ..Zeroable::zeroed ()
775+ /// ..Zeroable::init_zeroed ()
776776/// });
777777/// ```
778778///
@@ -808,7 +808,7 @@ macro_rules! pin_init {
808808/// ```rust
809809/// # #![feature(allocator_api)]
810810/// # #[path = "../examples/error.rs"] mod error; use error::Error;
811- /// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed };
811+ /// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, init_zeroed };
812812///
813813/// #[pin_data]
814814/// struct BigBuf {
@@ -820,7 +820,7 @@ macro_rules! pin_init {
820820/// impl BigBuf {
821821/// fn new() -> impl PinInit<Self, Error> {
822822/// try_pin_init!(Self {
823- /// big: Box::init(zeroed ())?,
823+ /// big: Box::init(init_zeroed ())?,
824824/// small: [0; 1024 * 1024],
825825/// ptr: core::ptr::null_mut(),
826826/// }? Error)
@@ -869,7 +869,7 @@ macro_rules! try_pin_init {
869869/// # #[path = "../examples/error.rs"] mod error; use error::Error;
870870/// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
871871/// # use pin_init::InPlaceInit;
872- /// use pin_init::{init, Init, zeroed };
872+ /// use pin_init::{init, Init, init_zeroed };
873873///
874874/// struct BigBuf {
875875/// small: [u8; 1024 * 1024],
@@ -878,7 +878,7 @@ macro_rules! try_pin_init {
878878/// impl BigBuf {
879879/// fn new() -> impl Init<Self> {
880880/// init!(Self {
881- /// small <- zeroed (),
881+ /// small <- init_zeroed (),
882882/// })
883883/// }
884884/// }
@@ -916,7 +916,7 @@ macro_rules! init {
916916/// # #![feature(allocator_api)]
917917/// # use core::alloc::AllocError;
918918/// # use pin_init::InPlaceInit;
919- /// use pin_init::{try_init, Init, zeroed };
919+ /// use pin_init::{try_init, Init, init_zeroed };
920920///
921921/// struct BigBuf {
922922/// big: Box<[u8; 1024 * 1024 * 1024]>,
@@ -926,7 +926,7 @@ macro_rules! init {
926926/// impl BigBuf {
927927/// fn new() -> impl Init<Self, AllocError> {
928928/// try_init!(Self {
929- /// big: Box::init(zeroed ())?,
929+ /// big: Box::init(init_zeroed ())?,
930930/// small: [0; 1024 * 1024],
931931/// }? AllocError)
932932/// }
@@ -1173,7 +1173,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
11731173 ///
11741174 /// ```rust
11751175 /// # #![expect(clippy::disallowed_names)]
1176- /// use pin_init::{init, zeroed , Init};
1176+ /// use pin_init::{init, init_zeroed , Init};
11771177 ///
11781178 /// struct Foo {
11791179 /// buf: [u8; 1_000_000],
@@ -1186,7 +1186,7 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
11861186 /// }
11871187 ///
11881188 /// let foo = init!(Foo {
1189- /// buf <- zeroed ()
1189+ /// buf <- init_zeroed ()
11901190 /// }).chain(|foo| {
11911191 /// foo.setup();
11921192 /// Ok(())
@@ -1412,6 +1412,28 @@ unsafe impl<T> PinInit<T> for T {
14121412 }
14131413}
14141414
1415+ // SAFETY: when the `__init` function returns with
1416+ // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld.
1417+ // - `Err(err)`, slot was not written to.
1418+ unsafe impl < T , E > Init < T , E > for Result < T , E > {
1419+ unsafe fn __init ( self , slot : * mut T ) -> Result < ( ) , E > {
1420+ // SAFETY: `slot` is valid for writes by the safety requirements of this function.
1421+ unsafe { slot. write ( self ?) } ;
1422+ Ok ( ( ) )
1423+ }
1424+ }
1425+
1426+ // SAFETY: when the `__pinned_init` function returns with
1427+ // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld.
1428+ // - `Err(err)`, slot was not written to.
1429+ unsafe impl < T , E > PinInit < T , E > for Result < T , E > {
1430+ unsafe fn __pinned_init ( self , slot : * mut T ) -> Result < ( ) , E > {
1431+ // SAFETY: `slot` is valid for writes by the safety requirements of this function.
1432+ unsafe { slot. write ( self ?) } ;
1433+ Ok ( ( ) )
1434+ }
1435+ }
1436+
14151437/// Smart pointer containing uninitialized memory and that can write a value.
14161438pub trait InPlaceWrite < T > {
14171439 /// The type `Self` turns into when the contents are initialized.
@@ -1476,7 +1498,45 @@ pub unsafe trait PinnedDrop: __internal::HasPinData {
14761498/// ```rust,ignore
14771499/// let val: Self = unsafe { core::mem::zeroed() };
14781500/// ```
1479- pub unsafe trait Zeroable { }
1501+ pub unsafe trait Zeroable {
1502+ /// Create a new zeroed `Self`.
1503+ ///
1504+ /// The returned initializer will write `0x00` to every byte of the given `slot`.
1505+ #[ inline]
1506+ fn init_zeroed ( ) -> impl Init < Self >
1507+ where
1508+ Self : Sized ,
1509+ {
1510+ init_zeroed ( )
1511+ }
1512+
1513+ /// Create a `Self` consisting of all zeroes.
1514+ ///
1515+ /// Whenever a type implements [`Zeroable`], this function should be preferred over
1516+ /// [`core::mem::zeroed()`] or using `MaybeUninit<T>::zeroed().assume_init()`.
1517+ ///
1518+ /// # Examples
1519+ ///
1520+ /// ```
1521+ /// use pin_init::{Zeroable, zeroed};
1522+ ///
1523+ /// #[derive(Zeroable)]
1524+ /// struct Point {
1525+ /// x: u32,
1526+ /// y: u32,
1527+ /// }
1528+ ///
1529+ /// let point: Point = zeroed();
1530+ /// assert_eq!(point.x, 0);
1531+ /// assert_eq!(point.y, 0);
1532+ /// ```
1533+ fn zeroed ( ) -> Self
1534+ where
1535+ Self : Sized ,
1536+ {
1537+ zeroed ( )
1538+ }
1539+ }
14801540
14811541/// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
14821542/// `None` to that location.
@@ -1489,11 +1549,21 @@ pub unsafe trait ZeroableOption {}
14891549// SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
14901550unsafe impl < T : ZeroableOption > Zeroable for Option < T > { }
14911551
1492- /// Create a new zeroed T.
1552+ // SAFETY: `Option<&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 & T { }
1555+ // SAFETY: `Option<&mut 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 & mut T { }
1558+ // SAFETY: `Option<NonNull<T>>` is part of the option layout optimization guarantee:
1559+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1560+ unsafe impl < T > ZeroableOption for NonNull < T > { }
1561+
1562+ /// Create an initializer for a zeroed `T`.
14931563///
14941564/// The returned initializer will write `0x00` to every byte of the given `slot`.
14951565#[ inline]
1496- pub fn zeroed < T : Zeroable > ( ) -> impl Init < T > {
1566+ pub fn init_zeroed < T : Zeroable > ( ) -> impl Init < T > {
14971567 // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
14981568 // and because we write all zeroes, the memory is initialized.
14991569 unsafe {
@@ -1504,6 +1574,31 @@ pub fn zeroed<T: Zeroable>() -> impl Init<T> {
15041574 }
15051575}
15061576
1577+ /// Create a `T` consisting of all zeroes.
1578+ ///
1579+ /// Whenever a type implements [`Zeroable`], this function should be preferred over
1580+ /// [`core::mem::zeroed()`] or using `MaybeUninit<T>::zeroed().assume_init()`.
1581+ ///
1582+ /// # Examples
1583+ ///
1584+ /// ```
1585+ /// use pin_init::{Zeroable, zeroed};
1586+ ///
1587+ /// #[derive(Zeroable)]
1588+ /// struct Point {
1589+ /// x: u32,
1590+ /// y: u32,
1591+ /// }
1592+ ///
1593+ /// let point: Point = zeroed();
1594+ /// assert_eq!(point.x, 0);
1595+ /// assert_eq!(point.y, 0);
1596+ /// ```
1597+ pub const fn zeroed < T : Zeroable > ( ) -> T {
1598+ // SAFETY:By the type invariants of `Zeroable`, all zeroes is a valid bit pattern for `T`.
1599+ unsafe { core:: mem:: zeroed ( ) }
1600+ }
1601+
15071602macro_rules! impl_zeroable {
15081603 ( $( $( { $( $generics: tt) * } ) ? $t: ty, ) * ) => {
15091604 // SAFETY: Safety comments written in the macro invocation.
@@ -1541,7 +1636,6 @@ impl_zeroable! {
15411636 Option <NonZeroU128 >, Option <NonZeroUsize >,
15421637 Option <NonZeroI8 >, Option <NonZeroI16 >, Option <NonZeroI32 >, Option <NonZeroI64 >,
15431638 Option <NonZeroI128 >, Option <NonZeroIsize >,
1544- { <T >} Option <NonNull <T >>,
15451639
15461640 // SAFETY: `null` pointer is valid.
15471641 //
@@ -1571,6 +1665,22 @@ macro_rules! impl_tuple_zeroable {
15711665
15721666impl_tuple_zeroable ! ( A , B , C , D , E , F , G , H , I , J ) ;
15731667
1668+ macro_rules! impl_fn_zeroable_option {
1669+ ( [ $( $abi: literal) ,* $( , ) ?] $args: tt) => {
1670+ $( impl_fn_zeroable_option!( { extern $abi} $args) ; ) *
1671+ $( impl_fn_zeroable_option!( { unsafe extern $abi} $args) ; ) *
1672+ } ;
1673+ ( { $( $prefix: tt) * } { $( , ) ?} ) => { } ;
1674+ ( { $( $prefix: tt) * } { $ret: ident, $( $rest: ident) ,* $( , ) ?} ) => {
1675+ // SAFETY: function pointers are part of the option layout optimization:
1676+ // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
1677+ unsafe impl <$ret, $( $rest) ,* > ZeroableOption for $( $prefix) * fn ( $( $rest) ,* ) -> $ret { }
1678+ impl_fn_zeroable_option!( { $( $prefix) * } { $( $rest) ,* , } ) ;
1679+ } ;
1680+ }
1681+
1682+ 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 } ) ;
1683+
15741684/// This trait allows creating an instance of `Self` which contains exactly one
15751685/// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
15761686///
0 commit comments