190e53c5eSBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT
290e53c5eSBenno Lossin
390e53c5eSBenno Lossin //! API to safely and fallibly initialize pinned `struct`s using in-place constructors.
490e53c5eSBenno Lossin //!
590e53c5eSBenno Lossin //! It also allows in-place initialization of big `struct`s that would otherwise produce a stack
690e53c5eSBenno Lossin //! overflow.
790e53c5eSBenno Lossin //!
890e53c5eSBenno Lossin //! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential
990e53c5eSBenno Lossin //! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.
1090e53c5eSBenno Lossin //!
1190e53c5eSBenno Lossin //! # Overview
1290e53c5eSBenno Lossin //!
1390e53c5eSBenno Lossin //! To initialize a `struct` with an in-place constructor you will need two things:
1490e53c5eSBenno Lossin //! - an in-place constructor,
156841d45aSBenno Lossin //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
166841d45aSBenno Lossin //! [`UniqueArc<T>`], [`Box<T>`] or any other smart pointer that implements [`InPlaceInit`]).
1790e53c5eSBenno Lossin //!
18fc6c6baaSBenno Lossin //! To get an in-place constructor there are generally three options:
19fc6c6baaSBenno Lossin //! - directly creating an in-place constructor using the [`pin_init!`] macro,
2090e53c5eSBenno Lossin //! - a custom function/macro returning an in-place constructor provided by someone else,
2190e53c5eSBenno Lossin //! - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
2290e53c5eSBenno Lossin //!
2390e53c5eSBenno Lossin //! Aside from pinned initialization, this API also supports in-place construction without pinning,
2490e53c5eSBenno Lossin //! the macros/types/functions are generally named like the pinned variants without the `pin`
2590e53c5eSBenno Lossin //! prefix.
2690e53c5eSBenno Lossin //!
27fc6c6baaSBenno Lossin //! # Examples
28fc6c6baaSBenno Lossin //!
29fc6c6baaSBenno Lossin //! ## Using the [`pin_init!`] macro
30fc6c6baaSBenno Lossin //!
31fc6c6baaSBenno Lossin //! If you want to use [`PinInit`], then you will have to annotate your `struct` with
32fc6c6baaSBenno Lossin //! `#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for
33fc6c6baaSBenno Lossin //! [structurally pinned fields]. After doing this, you can then create an in-place constructor via
34fc6c6baaSBenno Lossin //! [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
35fc6c6baaSBenno Lossin //! that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
36fc6c6baaSBenno Lossin //!
37fc6c6baaSBenno Lossin //! ```rust
38fc6c6baaSBenno Lossin //! # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
39fc6c6baaSBenno Lossin //! use kernel::{prelude::*, sync::Mutex, new_mutex};
40fc6c6baaSBenno Lossin //! # use core::pin::Pin;
41fc6c6baaSBenno Lossin //! #[pin_data]
42fc6c6baaSBenno Lossin //! struct Foo {
43fc6c6baaSBenno Lossin //! #[pin]
44fc6c6baaSBenno Lossin //! a: Mutex<usize>,
45fc6c6baaSBenno Lossin //! b: u32,
46fc6c6baaSBenno Lossin //! }
47fc6c6baaSBenno Lossin //!
48fc6c6baaSBenno Lossin //! let foo = pin_init!(Foo {
49fc6c6baaSBenno Lossin //! a <- new_mutex!(42, "Foo::a"),
50fc6c6baaSBenno Lossin //! b: 24,
51fc6c6baaSBenno Lossin //! });
52fc6c6baaSBenno Lossin //! ```
53fc6c6baaSBenno Lossin //!
54fc6c6baaSBenno Lossin //! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
55fc6c6baaSBenno Lossin //! (or just the stack) to actually initialize a `Foo`:
56fc6c6baaSBenno Lossin //!
57fc6c6baaSBenno Lossin //! ```rust
58fc6c6baaSBenno Lossin //! # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
59fc6c6baaSBenno Lossin //! # use kernel::{prelude::*, sync::Mutex, new_mutex};
60fc6c6baaSBenno Lossin //! # use core::pin::Pin;
61fc6c6baaSBenno Lossin //! # #[pin_data]
62fc6c6baaSBenno Lossin //! # struct Foo {
63fc6c6baaSBenno Lossin //! # #[pin]
64fc6c6baaSBenno Lossin //! # a: Mutex<usize>,
65fc6c6baaSBenno Lossin //! # b: u32,
66fc6c6baaSBenno Lossin //! # }
67fc6c6baaSBenno Lossin //! # let foo = pin_init!(Foo {
68fc6c6baaSBenno Lossin //! # a <- new_mutex!(42, "Foo::a"),
69fc6c6baaSBenno Lossin //! # b: 24,
70fc6c6baaSBenno Lossin //! # });
71fc6c6baaSBenno Lossin //! let foo: Result<Pin<Box<Foo>>> = Box::pin_init(foo);
72fc6c6baaSBenno Lossin //! ```
73fc6c6baaSBenno Lossin //!
74fc6c6baaSBenno Lossin //! For more information see the [`pin_init!`] macro.
75fc6c6baaSBenno Lossin //!
76fc6c6baaSBenno Lossin //! ## Using a custom function/macro that returns an initializer
77fc6c6baaSBenno Lossin //!
78fc6c6baaSBenno Lossin //! Many types from the kernel supply a function/macro that returns an initializer, because the
79fc6c6baaSBenno Lossin //! above method only works for types where you can access the fields.
80fc6c6baaSBenno Lossin //!
81fc6c6baaSBenno Lossin //! ```rust
82fc6c6baaSBenno Lossin //! # use kernel::{new_mutex, sync::{Arc, Mutex}};
83fc6c6baaSBenno Lossin //! let mtx: Result<Arc<Mutex<usize>>> = Arc::pin_init(new_mutex!(42, "example::mtx"));
84fc6c6baaSBenno Lossin //! ```
85fc6c6baaSBenno Lossin //!
86fc6c6baaSBenno Lossin //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
87fc6c6baaSBenno Lossin //!
88fc6c6baaSBenno Lossin //! ```rust
89fc6c6baaSBenno Lossin //! # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
90fc6c6baaSBenno Lossin //! # use kernel::{sync::Mutex, prelude::*, new_mutex, init::PinInit, try_pin_init};
91fc6c6baaSBenno Lossin //! #[pin_data]
92fc6c6baaSBenno Lossin //! struct DriverData {
93fc6c6baaSBenno Lossin //! #[pin]
94fc6c6baaSBenno Lossin //! status: Mutex<i32>,
95fc6c6baaSBenno Lossin //! buffer: Box<[u8; 1_000_000]>,
96fc6c6baaSBenno Lossin //! }
97fc6c6baaSBenno Lossin //!
98fc6c6baaSBenno Lossin //! impl DriverData {
99fc6c6baaSBenno Lossin //! fn new() -> impl PinInit<Self, Error> {
100fc6c6baaSBenno Lossin //! try_pin_init!(Self {
101fc6c6baaSBenno Lossin //! status <- new_mutex!(0, "DriverData::status"),
102fc6c6baaSBenno Lossin //! buffer: Box::init(kernel::init::zeroed())?,
103fc6c6baaSBenno Lossin //! })
104fc6c6baaSBenno Lossin //! }
105fc6c6baaSBenno Lossin //! }
106fc6c6baaSBenno Lossin //! ```
107fc6c6baaSBenno Lossin //!
108d0fdc396SBenno Lossin //! ## Manual creation of an initializer
109d0fdc396SBenno Lossin //!
110d0fdc396SBenno Lossin //! Often when working with primitives the previous approaches are not sufficient. That is where
111d0fdc396SBenno Lossin //! [`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a
112d0fdc396SBenno Lossin //! [`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure
113d0fdc396SBenno Lossin //! actually does the initialization in the correct way. Here are the things to look out for
114d0fdc396SBenno Lossin //! (we are calling the parameter to the closure `slot`):
115d0fdc396SBenno Lossin //! - when the closure returns `Ok(())`, then it has completed the initialization successfully, so
116d0fdc396SBenno Lossin //! `slot` now contains a valid bit pattern for the type `T`,
117d0fdc396SBenno Lossin //! - when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so
118d0fdc396SBenno Lossin //! you need to take care to clean up anything if your initialization fails mid-way,
119d0fdc396SBenno Lossin //! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of
120d0fdc396SBenno Lossin //! `slot` gets called.
121d0fdc396SBenno Lossin //!
122d0fdc396SBenno Lossin //! ```rust
123a30e94c2SMiguel Ojeda //! # #![allow(unreachable_pub, clippy::disallowed_names)]
124a30e94c2SMiguel Ojeda //! use kernel::{prelude::*, init, types::Opaque};
125d0fdc396SBenno Lossin //! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
126d0fdc396SBenno Lossin //! # mod bindings {
127a30e94c2SMiguel Ojeda //! # #![allow(non_camel_case_types)]
128d0fdc396SBenno Lossin //! # pub struct foo;
129d0fdc396SBenno Lossin //! # pub unsafe fn init_foo(_ptr: *mut foo) {}
130d0fdc396SBenno Lossin //! # pub unsafe fn destroy_foo(_ptr: *mut foo) {}
131d0fdc396SBenno Lossin //! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }
132d0fdc396SBenno Lossin //! # }
133a30e94c2SMiguel Ojeda //! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.
134a30e94c2SMiguel Ojeda //! # trait FromErrno {
135a30e94c2SMiguel Ojeda //! # fn from_errno(errno: core::ffi::c_int) -> Error {
136a30e94c2SMiguel Ojeda //! # // Dummy error that can be constructed outside the `kernel` crate.
137a30e94c2SMiguel Ojeda //! # Error::from(core::fmt::Error)
138a30e94c2SMiguel Ojeda //! # }
139a30e94c2SMiguel Ojeda //! # }
140a30e94c2SMiguel Ojeda //! # impl FromErrno for Error {}
141d0fdc396SBenno Lossin //! /// # Invariants
142d0fdc396SBenno Lossin //! ///
143d0fdc396SBenno Lossin //! /// `foo` is always initialized
144d0fdc396SBenno Lossin //! #[pin_data(PinnedDrop)]
145d0fdc396SBenno Lossin //! pub struct RawFoo {
146d0fdc396SBenno Lossin //! #[pin]
147d0fdc396SBenno Lossin //! foo: Opaque<bindings::foo>,
148d0fdc396SBenno Lossin //! #[pin]
149d0fdc396SBenno Lossin //! _p: PhantomPinned,
150d0fdc396SBenno Lossin //! }
151d0fdc396SBenno Lossin //!
152d0fdc396SBenno Lossin //! impl RawFoo {
153d0fdc396SBenno Lossin //! pub fn new(flags: u32) -> impl PinInit<Self, Error> {
154d0fdc396SBenno Lossin //! // SAFETY:
155d0fdc396SBenno Lossin //! // - when the closure returns `Ok(())`, then it has successfully initialized and
156d0fdc396SBenno Lossin //! // enabled `foo`,
157d0fdc396SBenno Lossin //! // - when it returns `Err(e)`, then it has cleaned up before
158d0fdc396SBenno Lossin //! unsafe {
159d0fdc396SBenno Lossin //! init::pin_init_from_closure(move |slot: *mut Self| {
160d0fdc396SBenno Lossin //! // `slot` contains uninit memory, avoid creating a reference.
161d0fdc396SBenno Lossin //! let foo = addr_of_mut!((*slot).foo);
162d0fdc396SBenno Lossin //!
163d0fdc396SBenno Lossin //! // Initialize the `foo`
164d0fdc396SBenno Lossin //! bindings::init_foo(Opaque::raw_get(foo));
165d0fdc396SBenno Lossin //!
166d0fdc396SBenno Lossin //! // Try to enable it.
167d0fdc396SBenno Lossin //! let err = bindings::enable_foo(Opaque::raw_get(foo), flags);
168d0fdc396SBenno Lossin //! if err != 0 {
169d0fdc396SBenno Lossin //! // Enabling has failed, first clean up the foo and then return the error.
170d0fdc396SBenno Lossin //! bindings::destroy_foo(Opaque::raw_get(foo));
171a30e94c2SMiguel Ojeda //! return Err(Error::from_errno(err));
172d0fdc396SBenno Lossin //! }
173d0fdc396SBenno Lossin //!
174d0fdc396SBenno Lossin //! // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
175d0fdc396SBenno Lossin //! Ok(())
176d0fdc396SBenno Lossin //! })
177d0fdc396SBenno Lossin //! }
178d0fdc396SBenno Lossin //! }
179d0fdc396SBenno Lossin //! }
180d0fdc396SBenno Lossin //!
181d0fdc396SBenno Lossin //! #[pinned_drop]
182d0fdc396SBenno Lossin //! impl PinnedDrop for RawFoo {
183d0fdc396SBenno Lossin //! fn drop(self: Pin<&mut Self>) {
184d0fdc396SBenno Lossin //! // SAFETY: Since `foo` is initialized, destroying is safe.
185d0fdc396SBenno Lossin //! unsafe { bindings::destroy_foo(self.foo.get()) };
186d0fdc396SBenno Lossin //! }
187d0fdc396SBenno Lossin //! }
188d0fdc396SBenno Lossin //! ```
189d0fdc396SBenno Lossin //!
190692e8935SBenno Lossin //! For the special case where initializing a field is a single FFI-function call that cannot fail,
191692e8935SBenno Lossin //! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single
192692e8935SBenno Lossin //! [`Opaque`] field by just delegating to the supplied closure. You can use these in combination
193692e8935SBenno Lossin //! with [`pin_init!`].
194692e8935SBenno Lossin //!
195692e8935SBenno Lossin //! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
196692e8935SBenno Lossin //! the `kernel` crate. The [`sync`] module is a good starting point.
197692e8935SBenno Lossin //!
19890e53c5eSBenno Lossin //! [`sync`]: kernel::sync
19990e53c5eSBenno Lossin //! [pinning]: https://doc.rust-lang.org/std/pin/index.html
20090e53c5eSBenno Lossin //! [structurally pinned fields]:
20190e53c5eSBenno Lossin //! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
2026841d45aSBenno Lossin //! [stack]: crate::stack_pin_init
20390e53c5eSBenno Lossin //! [`Arc<T>`]: crate::sync::Arc
20490e53c5eSBenno Lossin //! [`impl PinInit<Foo>`]: PinInit
20590e53c5eSBenno Lossin //! [`impl PinInit<T, E>`]: PinInit
20690e53c5eSBenno Lossin //! [`impl Init<T, E>`]: Init
20790e53c5eSBenno Lossin //! [`Opaque`]: kernel::types::Opaque
208692e8935SBenno Lossin //! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init
20990e53c5eSBenno Lossin //! [`pin_data`]: ::macros::pin_data
2103ed03f4dSMiguel Ojeda //! [`pin_init!`]: crate::pin_init!
21190e53c5eSBenno Lossin
21292c4a1e7SBenno Lossin use crate::{
21392c4a1e7SBenno Lossin error::{self, Error},
21492c4a1e7SBenno Lossin sync::UniqueArc,
2152e704f18SBenno Lossin types::{Opaque, ScopeGuard},
21692c4a1e7SBenno Lossin };
217fc6c6baaSBenno Lossin use alloc::boxed::Box;
21892c4a1e7SBenno Lossin use core::{
21938cde0bdSBenno Lossin alloc::AllocError,
2202e704f18SBenno Lossin cell::UnsafeCell,
22138cde0bdSBenno Lossin convert::Infallible,
22238cde0bdSBenno Lossin marker::PhantomData,
22338cde0bdSBenno Lossin mem::MaybeUninit,
22438cde0bdSBenno Lossin num::*,
22538cde0bdSBenno Lossin pin::Pin,
22638cde0bdSBenno Lossin ptr::{self, NonNull},
22792c4a1e7SBenno Lossin };
22890e53c5eSBenno Lossin
22990e53c5eSBenno Lossin #[doc(hidden)]
23090e53c5eSBenno Lossin pub mod __internal;
231fc6c6baaSBenno Lossin #[doc(hidden)]
232fc6c6baaSBenno Lossin pub mod macros;
233fc6c6baaSBenno Lossin
2346841d45aSBenno Lossin /// Initialize and pin a type directly on the stack.
2356841d45aSBenno Lossin ///
2366841d45aSBenno Lossin /// # Examples
2376841d45aSBenno Lossin ///
2386841d45aSBenno Lossin /// ```rust
2396841d45aSBenno Lossin /// # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
240a30e94c2SMiguel Ojeda /// # use kernel::{init, macros::pin_data, pin_init, stack_pin_init, init::*, sync::Mutex, new_mutex};
2416841d45aSBenno Lossin /// # use core::pin::Pin;
2426841d45aSBenno Lossin /// #[pin_data]
2436841d45aSBenno Lossin /// struct Foo {
2446841d45aSBenno Lossin /// #[pin]
2456841d45aSBenno Lossin /// a: Mutex<usize>,
2466841d45aSBenno Lossin /// b: Bar,
2476841d45aSBenno Lossin /// }
2486841d45aSBenno Lossin ///
2496841d45aSBenno Lossin /// #[pin_data]
2506841d45aSBenno Lossin /// struct Bar {
2516841d45aSBenno Lossin /// x: u32,
2526841d45aSBenno Lossin /// }
2536841d45aSBenno Lossin ///
2546841d45aSBenno Lossin /// stack_pin_init!(let foo = pin_init!(Foo {
2556841d45aSBenno Lossin /// a <- new_mutex!(42),
2566841d45aSBenno Lossin /// b: Bar {
2576841d45aSBenno Lossin /// x: 64,
2586841d45aSBenno Lossin /// },
2596841d45aSBenno Lossin /// }));
2606841d45aSBenno Lossin /// let foo: Pin<&mut Foo> = foo;
261*2592a628SAlban Kurti /// pr_info!("a: {}\n", &*foo.a.lock());
2626841d45aSBenno Lossin /// ```
2636841d45aSBenno Lossin ///
2646841d45aSBenno Lossin /// # Syntax
2656841d45aSBenno Lossin ///
2666841d45aSBenno Lossin /// A normal `let` binding with optional type annotation. The expression is expected to implement
2676841d45aSBenno Lossin /// [`PinInit`]/[`Init`] with the error type [`Infallible`]. If you want to use a different error
2686841d45aSBenno Lossin /// type, then use [`stack_try_pin_init!`].
2693ed03f4dSMiguel Ojeda ///
2703ed03f4dSMiguel Ojeda /// [`stack_try_pin_init!`]: crate::stack_try_pin_init!
2716841d45aSBenno Lossin #[macro_export]
2726841d45aSBenno Lossin macro_rules! stack_pin_init {
2736841d45aSBenno Lossin (let $var:ident $(: $t:ty)? = $val:expr) => {
2746841d45aSBenno Lossin let val = $val;
2756841d45aSBenno Lossin let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
2766841d45aSBenno Lossin let mut $var = match $crate::init::__internal::StackInit::init($var, val) {
2776841d45aSBenno Lossin Ok(res) => res,
2786841d45aSBenno Lossin Err(x) => {
2796841d45aSBenno Lossin let x: ::core::convert::Infallible = x;
2806841d45aSBenno Lossin match x {}
2816841d45aSBenno Lossin }
2826841d45aSBenno Lossin };
2836841d45aSBenno Lossin };
2846841d45aSBenno Lossin }
2856841d45aSBenno Lossin
2866841d45aSBenno Lossin /// Initialize and pin a type directly on the stack.
2876841d45aSBenno Lossin ///
2886841d45aSBenno Lossin /// # Examples
2896841d45aSBenno Lossin ///
290a30e94c2SMiguel Ojeda /// ```rust,ignore
2916841d45aSBenno Lossin /// # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
2926841d45aSBenno Lossin /// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};
2936841d45aSBenno Lossin /// # use macros::pin_data;
2946841d45aSBenno Lossin /// # use core::{alloc::AllocError, pin::Pin};
2956841d45aSBenno Lossin /// #[pin_data]
2966841d45aSBenno Lossin /// struct Foo {
2976841d45aSBenno Lossin /// #[pin]
2986841d45aSBenno Lossin /// a: Mutex<usize>,
2996841d45aSBenno Lossin /// b: Box<Bar>,
3006841d45aSBenno Lossin /// }
3016841d45aSBenno Lossin ///
3026841d45aSBenno Lossin /// struct Bar {
3036841d45aSBenno Lossin /// x: u32,
3046841d45aSBenno Lossin /// }
3056841d45aSBenno Lossin ///
3066841d45aSBenno Lossin /// stack_try_pin_init!(let foo: Result<Pin<&mut Foo>, AllocError> = pin_init!(Foo {
3076841d45aSBenno Lossin /// a <- new_mutex!(42),
3086841d45aSBenno Lossin /// b: Box::try_new(Bar {
3096841d45aSBenno Lossin /// x: 64,
3106841d45aSBenno Lossin /// })?,
3116841d45aSBenno Lossin /// }));
3126841d45aSBenno Lossin /// let foo = foo.unwrap();
313*2592a628SAlban Kurti /// pr_info!("a: {}\n", &*foo.a.lock());
3146841d45aSBenno Lossin /// ```
3156841d45aSBenno Lossin ///
316a30e94c2SMiguel Ojeda /// ```rust,ignore
3176841d45aSBenno Lossin /// # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
3186841d45aSBenno Lossin /// # use kernel::{init, pin_init, stack_try_pin_init, init::*, sync::Mutex, new_mutex};
3196841d45aSBenno Lossin /// # use macros::pin_data;
3206841d45aSBenno Lossin /// # use core::{alloc::AllocError, pin::Pin};
3216841d45aSBenno Lossin /// #[pin_data]
3226841d45aSBenno Lossin /// struct Foo {
3236841d45aSBenno Lossin /// #[pin]
3246841d45aSBenno Lossin /// a: Mutex<usize>,
3256841d45aSBenno Lossin /// b: Box<Bar>,
3266841d45aSBenno Lossin /// }
3276841d45aSBenno Lossin ///
3286841d45aSBenno Lossin /// struct Bar {
3296841d45aSBenno Lossin /// x: u32,
3306841d45aSBenno Lossin /// }
3316841d45aSBenno Lossin ///
3326841d45aSBenno Lossin /// stack_try_pin_init!(let foo: Pin<&mut Foo> =? pin_init!(Foo {
3336841d45aSBenno Lossin /// a <- new_mutex!(42),
3346841d45aSBenno Lossin /// b: Box::try_new(Bar {
3356841d45aSBenno Lossin /// x: 64,
3366841d45aSBenno Lossin /// })?,
3376841d45aSBenno Lossin /// }));
338*2592a628SAlban Kurti /// pr_info!("a: {}\n", &*foo.a.lock());
3396841d45aSBenno Lossin /// # Ok::<_, AllocError>(())
3406841d45aSBenno Lossin /// ```
3416841d45aSBenno Lossin ///
3426841d45aSBenno Lossin /// # Syntax
3436841d45aSBenno Lossin ///
3446841d45aSBenno Lossin /// A normal `let` binding with optional type annotation. The expression is expected to implement
3456841d45aSBenno Lossin /// [`PinInit`]/[`Init`]. This macro assigns a result to the given variable, adding a `?` after the
3466841d45aSBenno Lossin /// `=` will propagate this error.
3476841d45aSBenno Lossin #[macro_export]
3486841d45aSBenno Lossin macro_rules! stack_try_pin_init {
3496841d45aSBenno Lossin (let $var:ident $(: $t:ty)? = $val:expr) => {
3506841d45aSBenno Lossin let val = $val;
3516841d45aSBenno Lossin let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
3526841d45aSBenno Lossin let mut $var = $crate::init::__internal::StackInit::init($var, val);
3536841d45aSBenno Lossin };
3546841d45aSBenno Lossin (let $var:ident $(: $t:ty)? =? $val:expr) => {
3556841d45aSBenno Lossin let val = $val;
3566841d45aSBenno Lossin let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
3576841d45aSBenno Lossin let mut $var = $crate::init::__internal::StackInit::init($var, val)?;
3586841d45aSBenno Lossin };
3596841d45aSBenno Lossin }
3606841d45aSBenno Lossin
361fc6c6baaSBenno Lossin /// Construct an in-place, pinned initializer for `struct`s.
362fc6c6baaSBenno Lossin ///
363fc6c6baaSBenno Lossin /// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
364fc6c6baaSBenno Lossin /// [`try_pin_init!`].
365fc6c6baaSBenno Lossin ///
366fc6c6baaSBenno Lossin /// The syntax is almost identical to that of a normal `struct` initializer:
367fc6c6baaSBenno Lossin ///
368fc6c6baaSBenno Lossin /// ```rust
369fc6c6baaSBenno Lossin /// # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
370fc6c6baaSBenno Lossin /// # use kernel::{init, pin_init, macros::pin_data, init::*};
371fc6c6baaSBenno Lossin /// # use core::pin::Pin;
372fc6c6baaSBenno Lossin /// #[pin_data]
373fc6c6baaSBenno Lossin /// struct Foo {
374fc6c6baaSBenno Lossin /// a: usize,
375fc6c6baaSBenno Lossin /// b: Bar,
376fc6c6baaSBenno Lossin /// }
377fc6c6baaSBenno Lossin ///
378fc6c6baaSBenno Lossin /// #[pin_data]
379fc6c6baaSBenno Lossin /// struct Bar {
380fc6c6baaSBenno Lossin /// x: u32,
381fc6c6baaSBenno Lossin /// }
382fc6c6baaSBenno Lossin ///
383fc6c6baaSBenno Lossin /// # fn demo() -> impl PinInit<Foo> {
384fc6c6baaSBenno Lossin /// let a = 42;
385fc6c6baaSBenno Lossin ///
386fc6c6baaSBenno Lossin /// let initializer = pin_init!(Foo {
387fc6c6baaSBenno Lossin /// a,
388fc6c6baaSBenno Lossin /// b: Bar {
389fc6c6baaSBenno Lossin /// x: 64,
390fc6c6baaSBenno Lossin /// },
391fc6c6baaSBenno Lossin /// });
392fc6c6baaSBenno Lossin /// # initializer }
393fc6c6baaSBenno Lossin /// # Box::pin_init(demo()).unwrap();
394fc6c6baaSBenno Lossin /// ```
395fc6c6baaSBenno Lossin ///
396fc6c6baaSBenno Lossin /// Arbitrary Rust expressions can be used to set the value of a variable.
397fc6c6baaSBenno Lossin ///
398fc6c6baaSBenno Lossin /// The fields are initialized in the order that they appear in the initializer. So it is possible
399fc6c6baaSBenno Lossin /// to read already initialized fields using raw pointers.
400fc6c6baaSBenno Lossin ///
401fc6c6baaSBenno Lossin /// IMPORTANT: You are not allowed to create references to fields of the struct inside of the
402fc6c6baaSBenno Lossin /// initializer.
403fc6c6baaSBenno Lossin ///
404fc6c6baaSBenno Lossin /// # Init-functions
405fc6c6baaSBenno Lossin ///
406fc6c6baaSBenno Lossin /// When working with this API it is often desired to let others construct your types without
407fc6c6baaSBenno Lossin /// giving access to all fields. This is where you would normally write a plain function `new`
408fc6c6baaSBenno Lossin /// that would return a new instance of your type. With this API that is also possible.
409fc6c6baaSBenno Lossin /// However, there are a few extra things to keep in mind.
410fc6c6baaSBenno Lossin ///
411fc6c6baaSBenno Lossin /// To create an initializer function, simply declare it like this:
412fc6c6baaSBenno Lossin ///
413fc6c6baaSBenno Lossin /// ```rust
414fc6c6baaSBenno Lossin /// # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
415fc6c6baaSBenno Lossin /// # use kernel::{init, pin_init, prelude::*, init::*};
416fc6c6baaSBenno Lossin /// # use core::pin::Pin;
417fc6c6baaSBenno Lossin /// # #[pin_data]
418fc6c6baaSBenno Lossin /// # struct Foo {
419fc6c6baaSBenno Lossin /// # a: usize,
420fc6c6baaSBenno Lossin /// # b: Bar,
421fc6c6baaSBenno Lossin /// # }
422fc6c6baaSBenno Lossin /// # #[pin_data]
423fc6c6baaSBenno Lossin /// # struct Bar {
424fc6c6baaSBenno Lossin /// # x: u32,
425fc6c6baaSBenno Lossin /// # }
426fc6c6baaSBenno Lossin /// impl Foo {
427fc6c6baaSBenno Lossin /// fn new() -> impl PinInit<Self> {
428fc6c6baaSBenno Lossin /// pin_init!(Self {
429fc6c6baaSBenno Lossin /// a: 42,
430fc6c6baaSBenno Lossin /// b: Bar {
431fc6c6baaSBenno Lossin /// x: 64,
432fc6c6baaSBenno Lossin /// },
433fc6c6baaSBenno Lossin /// })
434fc6c6baaSBenno Lossin /// }
435fc6c6baaSBenno Lossin /// }
436fc6c6baaSBenno Lossin /// ```
437fc6c6baaSBenno Lossin ///
438fc6c6baaSBenno Lossin /// Users of `Foo` can now create it like this:
439fc6c6baaSBenno Lossin ///
440fc6c6baaSBenno Lossin /// ```rust
441fc6c6baaSBenno Lossin /// # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
442fc6c6baaSBenno Lossin /// # use kernel::{init, pin_init, macros::pin_data, init::*};
443fc6c6baaSBenno Lossin /// # use core::pin::Pin;
444fc6c6baaSBenno Lossin /// # #[pin_data]
445fc6c6baaSBenno Lossin /// # struct Foo {
446fc6c6baaSBenno Lossin /// # a: usize,
447fc6c6baaSBenno Lossin /// # b: Bar,
448fc6c6baaSBenno Lossin /// # }
449fc6c6baaSBenno Lossin /// # #[pin_data]
450fc6c6baaSBenno Lossin /// # struct Bar {
451fc6c6baaSBenno Lossin /// # x: u32,
452fc6c6baaSBenno Lossin /// # }
453fc6c6baaSBenno Lossin /// # impl Foo {
454fc6c6baaSBenno Lossin /// # fn new() -> impl PinInit<Self> {
455fc6c6baaSBenno Lossin /// # pin_init!(Self {
456fc6c6baaSBenno Lossin /// # a: 42,
457fc6c6baaSBenno Lossin /// # b: Bar {
458fc6c6baaSBenno Lossin /// # x: 64,
459fc6c6baaSBenno Lossin /// # },
460fc6c6baaSBenno Lossin /// # })
461fc6c6baaSBenno Lossin /// # }
462fc6c6baaSBenno Lossin /// # }
463fc6c6baaSBenno Lossin /// let foo = Box::pin_init(Foo::new());
464fc6c6baaSBenno Lossin /// ```
465fc6c6baaSBenno Lossin ///
466fc6c6baaSBenno Lossin /// They can also easily embed it into their own `struct`s:
467fc6c6baaSBenno Lossin ///
468fc6c6baaSBenno Lossin /// ```rust
469fc6c6baaSBenno Lossin /// # #![allow(clippy::disallowed_names, clippy::new_ret_no_self)]
470fc6c6baaSBenno Lossin /// # use kernel::{init, pin_init, macros::pin_data, init::*};
471fc6c6baaSBenno Lossin /// # use core::pin::Pin;
472fc6c6baaSBenno Lossin /// # #[pin_data]
473fc6c6baaSBenno Lossin /// # struct Foo {
474fc6c6baaSBenno Lossin /// # a: usize,
475fc6c6baaSBenno Lossin /// # b: Bar,
476fc6c6baaSBenno Lossin /// # }
477fc6c6baaSBenno Lossin /// # #[pin_data]
478fc6c6baaSBenno Lossin /// # struct Bar {
479fc6c6baaSBenno Lossin /// # x: u32,
480fc6c6baaSBenno Lossin /// # }
481fc6c6baaSBenno Lossin /// # impl Foo {
482fc6c6baaSBenno Lossin /// # fn new() -> impl PinInit<Self> {
483fc6c6baaSBenno Lossin /// # pin_init!(Self {
484fc6c6baaSBenno Lossin /// # a: 42,
485fc6c6baaSBenno Lossin /// # b: Bar {
486fc6c6baaSBenno Lossin /// # x: 64,
487fc6c6baaSBenno Lossin /// # },
488fc6c6baaSBenno Lossin /// # })
489fc6c6baaSBenno Lossin /// # }
490fc6c6baaSBenno Lossin /// # }
491fc6c6baaSBenno Lossin /// #[pin_data]
492fc6c6baaSBenno Lossin /// struct FooContainer {
493fc6c6baaSBenno Lossin /// #[pin]
494fc6c6baaSBenno Lossin /// foo1: Foo,
495fc6c6baaSBenno Lossin /// #[pin]
496fc6c6baaSBenno Lossin /// foo2: Foo,
497fc6c6baaSBenno Lossin /// other: u32,
498fc6c6baaSBenno Lossin /// }
499fc6c6baaSBenno Lossin ///
500fc6c6baaSBenno Lossin /// impl FooContainer {
501fc6c6baaSBenno Lossin /// fn new(other: u32) -> impl PinInit<Self> {
502fc6c6baaSBenno Lossin /// pin_init!(Self {
503fc6c6baaSBenno Lossin /// foo1 <- Foo::new(),
504fc6c6baaSBenno Lossin /// foo2 <- Foo::new(),
505fc6c6baaSBenno Lossin /// other,
506fc6c6baaSBenno Lossin /// })
507fc6c6baaSBenno Lossin /// }
508fc6c6baaSBenno Lossin /// }
509fc6c6baaSBenno Lossin /// ```
510fc6c6baaSBenno Lossin ///
511fc6c6baaSBenno Lossin /// Here we see that when using `pin_init!` with `PinInit`, one needs to write `<-` instead of `:`.
512fc6c6baaSBenno Lossin /// This signifies that the given field is initialized in-place. As with `struct` initializers, just
513fc6c6baaSBenno Lossin /// writing the field (in this case `other`) without `:` or `<-` means `other: other,`.
514fc6c6baaSBenno Lossin ///
515fc6c6baaSBenno Lossin /// # Syntax
516fc6c6baaSBenno Lossin ///
517fc6c6baaSBenno Lossin /// As already mentioned in the examples above, inside of `pin_init!` a `struct` initializer with
518fc6c6baaSBenno Lossin /// the following modifications is expected:
519fc6c6baaSBenno Lossin /// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
520fc6c6baaSBenno Lossin /// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
521fc6c6baaSBenno Lossin /// pointer named `this` inside of the initializer.
52235e7fca2SBenno Lossin /// - Using struct update syntax one can place `..Zeroable::zeroed()` at the very end of the
52335e7fca2SBenno Lossin /// struct, this initializes every field with 0 and then runs all initializers specified in the
52435e7fca2SBenno Lossin /// body. This can only be done if [`Zeroable`] is implemented for the struct.
525fc6c6baaSBenno Lossin ///
526fc6c6baaSBenno Lossin /// For instance:
527fc6c6baaSBenno Lossin ///
528fc6c6baaSBenno Lossin /// ```rust
529a031fe8dSLinus Torvalds /// # use kernel::{macros::{Zeroable, pin_data}, pin_init};
530fc6c6baaSBenno Lossin /// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
531fc6c6baaSBenno Lossin /// #[pin_data]
53235e7fca2SBenno Lossin /// #[derive(Zeroable)]
533fc6c6baaSBenno Lossin /// struct Buf {
534fc6c6baaSBenno Lossin /// // `ptr` points into `buf`.
535fc6c6baaSBenno Lossin /// ptr: *mut u8,
536fc6c6baaSBenno Lossin /// buf: [u8; 64],
537fc6c6baaSBenno Lossin /// #[pin]
538fc6c6baaSBenno Lossin /// pin: PhantomPinned,
539fc6c6baaSBenno Lossin /// }
540fc6c6baaSBenno Lossin /// pin_init!(&this in Buf {
541fc6c6baaSBenno Lossin /// buf: [0; 64],
542fc6c6baaSBenno Lossin /// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
543fc6c6baaSBenno Lossin /// pin: PhantomPinned,
544fc6c6baaSBenno Lossin /// });
54535e7fca2SBenno Lossin /// pin_init!(Buf {
54635e7fca2SBenno Lossin /// buf: [1; 64],
54735e7fca2SBenno Lossin /// ..Zeroable::zeroed()
54835e7fca2SBenno Lossin /// });
549fc6c6baaSBenno Lossin /// ```
550fc6c6baaSBenno Lossin ///
551fc6c6baaSBenno Lossin /// [`try_pin_init!`]: kernel::try_pin_init
552fc6c6baaSBenno Lossin /// [`NonNull<Self>`]: core::ptr::NonNull
553fc6c6baaSBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
554fc6c6baaSBenno Lossin // module `__internal` inside of `init/__internal.rs`.
555fc6c6baaSBenno Lossin #[macro_export]
556fc6c6baaSBenno Lossin macro_rules! pin_init {
557fc6c6baaSBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
558fc6c6baaSBenno Lossin $($fields:tt)*
559fc6c6baaSBenno Lossin }) => {
560b3068ac3SBenno Lossin $crate::__init_internal!(
561fc6c6baaSBenno Lossin @this($($this)?),
562fc6c6baaSBenno Lossin @typ($t $(::<$($generics),*>)?),
563fc6c6baaSBenno Lossin @fields($($fields)*),
564fc6c6baaSBenno Lossin @error(::core::convert::Infallible),
565b3068ac3SBenno Lossin @data(PinData, use_data),
566b3068ac3SBenno Lossin @has_data(HasPinData, __pin_data),
567b3068ac3SBenno Lossin @construct_closure(pin_init_from_closure),
56835e7fca2SBenno Lossin @munch_fields($($fields)*),
569fc6c6baaSBenno Lossin )
570fc6c6baaSBenno Lossin };
571fc6c6baaSBenno Lossin }
572fc6c6baaSBenno Lossin
573fc6c6baaSBenno Lossin /// Construct an in-place, fallible pinned initializer for `struct`s.
574fc6c6baaSBenno Lossin ///
575fc6c6baaSBenno Lossin /// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
576fc6c6baaSBenno Lossin ///
577fc6c6baaSBenno Lossin /// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
578fc6c6baaSBenno Lossin /// initialization and return the error.
579fc6c6baaSBenno Lossin ///
580fc6c6baaSBenno Lossin /// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
581fc6c6baaSBenno Lossin /// initialization fails, the memory can be safely deallocated without any further modifications.
582fc6c6baaSBenno Lossin ///
583fc6c6baaSBenno Lossin /// This macro defaults the error to [`Error`].
584fc6c6baaSBenno Lossin ///
585fc6c6baaSBenno Lossin /// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
586fc6c6baaSBenno Lossin /// after the `struct` initializer to specify the error type you want to use.
587fc6c6baaSBenno Lossin ///
588fc6c6baaSBenno Lossin /// # Examples
589fc6c6baaSBenno Lossin ///
590fc6c6baaSBenno Lossin /// ```rust
591fc6c6baaSBenno Lossin /// # #![feature(new_uninit)]
592fc6c6baaSBenno Lossin /// use kernel::{init::{self, PinInit}, error::Error};
593fc6c6baaSBenno Lossin /// #[pin_data]
594fc6c6baaSBenno Lossin /// struct BigBuf {
595fc6c6baaSBenno Lossin /// big: Box<[u8; 1024 * 1024 * 1024]>,
596fc6c6baaSBenno Lossin /// small: [u8; 1024 * 1024],
597fc6c6baaSBenno Lossin /// ptr: *mut u8,
598fc6c6baaSBenno Lossin /// }
599fc6c6baaSBenno Lossin ///
600fc6c6baaSBenno Lossin /// impl BigBuf {
601fc6c6baaSBenno Lossin /// fn new() -> impl PinInit<Self, Error> {
602fc6c6baaSBenno Lossin /// try_pin_init!(Self {
603fc6c6baaSBenno Lossin /// big: Box::init(init::zeroed())?,
604fc6c6baaSBenno Lossin /// small: [0; 1024 * 1024],
605fc6c6baaSBenno Lossin /// ptr: core::ptr::null_mut(),
606fc6c6baaSBenno Lossin /// }? Error)
607fc6c6baaSBenno Lossin /// }
608fc6c6baaSBenno Lossin /// }
609fc6c6baaSBenno Lossin /// ```
610fc6c6baaSBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
611fc6c6baaSBenno Lossin // module `__internal` inside of `init/__internal.rs`.
612fc6c6baaSBenno Lossin #[macro_export]
613fc6c6baaSBenno Lossin macro_rules! try_pin_init {
614fc6c6baaSBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
615fc6c6baaSBenno Lossin $($fields:tt)*
616fc6c6baaSBenno Lossin }) => {
617b3068ac3SBenno Lossin $crate::__init_internal!(
618fc6c6baaSBenno Lossin @this($($this)?),
619fc6c6baaSBenno Lossin @typ($t $(::<$($generics),*>)? ),
620fc6c6baaSBenno Lossin @fields($($fields)*),
621fc6c6baaSBenno Lossin @error($crate::error::Error),
622b3068ac3SBenno Lossin @data(PinData, use_data),
623b3068ac3SBenno Lossin @has_data(HasPinData, __pin_data),
624b3068ac3SBenno Lossin @construct_closure(pin_init_from_closure),
62535e7fca2SBenno Lossin @munch_fields($($fields)*),
626fc6c6baaSBenno Lossin )
627fc6c6baaSBenno Lossin };
628fc6c6baaSBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
629fc6c6baaSBenno Lossin $($fields:tt)*
630fc6c6baaSBenno Lossin }? $err:ty) => {
631b3068ac3SBenno Lossin $crate::__init_internal!(
632fc6c6baaSBenno Lossin @this($($this)?),
633fc6c6baaSBenno Lossin @typ($t $(::<$($generics),*>)? ),
634fc6c6baaSBenno Lossin @fields($($fields)*),
635fc6c6baaSBenno Lossin @error($err),
636b3068ac3SBenno Lossin @data(PinData, use_data),
637b3068ac3SBenno Lossin @has_data(HasPinData, __pin_data),
638b3068ac3SBenno Lossin @construct_closure(pin_init_from_closure),
63935e7fca2SBenno Lossin @munch_fields($($fields)*),
640fc6c6baaSBenno Lossin )
641fc6c6baaSBenno Lossin };
642fc6c6baaSBenno Lossin }
643fc6c6baaSBenno Lossin
644fc6c6baaSBenno Lossin /// Construct an in-place initializer for `struct`s.
645fc6c6baaSBenno Lossin ///
646fc6c6baaSBenno Lossin /// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
647fc6c6baaSBenno Lossin /// [`try_init!`].
648fc6c6baaSBenno Lossin ///
649fc6c6baaSBenno Lossin /// The syntax is identical to [`pin_init!`] and its safety caveats also apply:
650fc6c6baaSBenno Lossin /// - `unsafe` code must guarantee either full initialization or return an error and allow
651fc6c6baaSBenno Lossin /// deallocation of the memory.
652fc6c6baaSBenno Lossin /// - the fields are initialized in the order given in the initializer.
653fc6c6baaSBenno Lossin /// - no references to fields are allowed to be created inside of the initializer.
654fc6c6baaSBenno Lossin ///
655fc6c6baaSBenno Lossin /// This initializer is for initializing data in-place that might later be moved. If you want to
656fc6c6baaSBenno Lossin /// pin-initialize, use [`pin_init!`].
6573ed03f4dSMiguel Ojeda ///
6583ed03f4dSMiguel Ojeda /// [`try_init!`]: crate::try_init!
659fc6c6baaSBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
660fc6c6baaSBenno Lossin // module `__internal` inside of `init/__internal.rs`.
661fc6c6baaSBenno Lossin #[macro_export]
662fc6c6baaSBenno Lossin macro_rules! init {
663fc6c6baaSBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
664fc6c6baaSBenno Lossin $($fields:tt)*
665fc6c6baaSBenno Lossin }) => {
666b3068ac3SBenno Lossin $crate::__init_internal!(
667fc6c6baaSBenno Lossin @this($($this)?),
668fc6c6baaSBenno Lossin @typ($t $(::<$($generics),*>)?),
669fc6c6baaSBenno Lossin @fields($($fields)*),
670fc6c6baaSBenno Lossin @error(::core::convert::Infallible),
671b3068ac3SBenno Lossin @data(InitData, /*no use_data*/),
672b3068ac3SBenno Lossin @has_data(HasInitData, __init_data),
673b3068ac3SBenno Lossin @construct_closure(init_from_closure),
67435e7fca2SBenno Lossin @munch_fields($($fields)*),
675fc6c6baaSBenno Lossin )
676fc6c6baaSBenno Lossin }
677fc6c6baaSBenno Lossin }
678fc6c6baaSBenno Lossin
679fc6c6baaSBenno Lossin /// Construct an in-place fallible initializer for `struct`s.
680fc6c6baaSBenno Lossin ///
681fc6c6baaSBenno Lossin /// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
682fc6c6baaSBenno Lossin /// [`init!`].
683fc6c6baaSBenno Lossin ///
684fc6c6baaSBenno Lossin /// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
685fc6c6baaSBenno Lossin /// append `? $type` after the `struct` initializer.
686fc6c6baaSBenno Lossin /// The safety caveats from [`try_pin_init!`] also apply:
687fc6c6baaSBenno Lossin /// - `unsafe` code must guarantee either full initialization or return an error and allow
688fc6c6baaSBenno Lossin /// deallocation of the memory.
689fc6c6baaSBenno Lossin /// - the fields are initialized in the order given in the initializer.
690fc6c6baaSBenno Lossin /// - no references to fields are allowed to be created inside of the initializer.
691fc6c6baaSBenno Lossin ///
692fc6c6baaSBenno Lossin /// # Examples
693fc6c6baaSBenno Lossin ///
694fc6c6baaSBenno Lossin /// ```rust
695a30e94c2SMiguel Ojeda /// use kernel::{init::{PinInit, zeroed}, error::Error};
696fc6c6baaSBenno Lossin /// struct BigBuf {
697fc6c6baaSBenno Lossin /// big: Box<[u8; 1024 * 1024 * 1024]>,
698fc6c6baaSBenno Lossin /// small: [u8; 1024 * 1024],
699fc6c6baaSBenno Lossin /// }
700fc6c6baaSBenno Lossin ///
701fc6c6baaSBenno Lossin /// impl BigBuf {
702fc6c6baaSBenno Lossin /// fn new() -> impl Init<Self, Error> {
703fc6c6baaSBenno Lossin /// try_init!(Self {
704fc6c6baaSBenno Lossin /// big: Box::init(zeroed())?,
705fc6c6baaSBenno Lossin /// small: [0; 1024 * 1024],
706fc6c6baaSBenno Lossin /// }? Error)
707fc6c6baaSBenno Lossin /// }
708fc6c6baaSBenno Lossin /// }
709fc6c6baaSBenno Lossin /// ```
710fc6c6baaSBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
711fc6c6baaSBenno Lossin // module `__internal` inside of `init/__internal.rs`.
712fc6c6baaSBenno Lossin #[macro_export]
713fc6c6baaSBenno Lossin macro_rules! try_init {
714fc6c6baaSBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
715fc6c6baaSBenno Lossin $($fields:tt)*
716fc6c6baaSBenno Lossin }) => {
717b3068ac3SBenno Lossin $crate::__init_internal!(
718fc6c6baaSBenno Lossin @this($($this)?),
719fc6c6baaSBenno Lossin @typ($t $(::<$($generics),*>)?),
720fc6c6baaSBenno Lossin @fields($($fields)*),
721fc6c6baaSBenno Lossin @error($crate::error::Error),
722b3068ac3SBenno Lossin @data(InitData, /*no use_data*/),
723b3068ac3SBenno Lossin @has_data(HasInitData, __init_data),
724b3068ac3SBenno Lossin @construct_closure(init_from_closure),
72535e7fca2SBenno Lossin @munch_fields($($fields)*),
726fc6c6baaSBenno Lossin )
727fc6c6baaSBenno Lossin };
728fc6c6baaSBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
729fc6c6baaSBenno Lossin $($fields:tt)*
730fc6c6baaSBenno Lossin }? $err:ty) => {
731b3068ac3SBenno Lossin $crate::__init_internal!(
732fc6c6baaSBenno Lossin @this($($this)?),
733fc6c6baaSBenno Lossin @typ($t $(::<$($generics),*>)?),
734fc6c6baaSBenno Lossin @fields($($fields)*),
735fc6c6baaSBenno Lossin @error($err),
736b3068ac3SBenno Lossin @data(InitData, /*no use_data*/),
737b3068ac3SBenno Lossin @has_data(HasInitData, __init_data),
738b3068ac3SBenno Lossin @construct_closure(init_from_closure),
73935e7fca2SBenno Lossin @munch_fields($($fields)*),
740fc6c6baaSBenno Lossin )
741fc6c6baaSBenno Lossin };
742fc6c6baaSBenno Lossin }
74390e53c5eSBenno Lossin
74490e53c5eSBenno Lossin /// A pin-initializer for the type `T`.
74590e53c5eSBenno Lossin ///
74690e53c5eSBenno Lossin /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
7476841d45aSBenno Lossin /// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use the
7486841d45aSBenno Lossin /// [`InPlaceInit::pin_init`] function of a smart pointer like [`Arc<T>`] on this.
74990e53c5eSBenno Lossin ///
75090e53c5eSBenno Lossin /// Also see the [module description](self).
75190e53c5eSBenno Lossin ///
75290e53c5eSBenno Lossin /// # Safety
75390e53c5eSBenno Lossin ///
75490e53c5eSBenno Lossin /// When implementing this type you will need to take great care. Also there are probably very few
75590e53c5eSBenno Lossin /// cases where a manual implementation is necessary. Use [`pin_init_from_closure`] where possible.
75690e53c5eSBenno Lossin ///
75790e53c5eSBenno Lossin /// The [`PinInit::__pinned_init`] function
75890e53c5eSBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
75990e53c5eSBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
76090e53c5eSBenno Lossin /// - `slot` can be deallocated without UB occurring,
76190e53c5eSBenno Lossin /// - `slot` does not need to be dropped,
76290e53c5eSBenno Lossin /// - `slot` is not partially initialized.
76390e53c5eSBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
76490e53c5eSBenno Lossin ///
76590e53c5eSBenno Lossin /// [`Arc<T>`]: crate::sync::Arc
76690e53c5eSBenno Lossin /// [`Arc::pin_init`]: crate::sync::Arc::pin_init
76790e53c5eSBenno Lossin #[must_use = "An initializer must be used in order to create its value."]
76890e53c5eSBenno Lossin pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
76990e53c5eSBenno Lossin /// Initializes `slot`.
77090e53c5eSBenno Lossin ///
77190e53c5eSBenno Lossin /// # Safety
77290e53c5eSBenno Lossin ///
77390e53c5eSBenno Lossin /// - `slot` is a valid pointer to uninitialized memory.
77490e53c5eSBenno Lossin /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
77590e53c5eSBenno Lossin /// deallocate.
77690e53c5eSBenno Lossin /// - `slot` will not move until it is dropped, i.e. it will be pinned.
__pinned_init(self, slot: *mut T) -> Result<(), E>77790e53c5eSBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>;
7787f8977a7SBenno Lossin
7797f8977a7SBenno Lossin /// First initializes the value using `self` then calls the function `f` with the initialized
7807f8977a7SBenno Lossin /// value.
7817f8977a7SBenno Lossin ///
7827f8977a7SBenno Lossin /// If `f` returns an error the value is dropped and the initializer will forward the error.
7837f8977a7SBenno Lossin ///
7847f8977a7SBenno Lossin /// # Examples
7857f8977a7SBenno Lossin ///
7867f8977a7SBenno Lossin /// ```rust
7877f8977a7SBenno Lossin /// # #![allow(clippy::disallowed_names)]
7887f8977a7SBenno Lossin /// use kernel::{types::Opaque, init::pin_init_from_closure};
7897f8977a7SBenno Lossin /// #[repr(C)]
7907f8977a7SBenno Lossin /// struct RawFoo([u8; 16]);
7916a42d637SMiguel Ojeda /// extern "C" {
7927f8977a7SBenno Lossin /// fn init_foo(_: *mut RawFoo);
7937f8977a7SBenno Lossin /// }
7947f8977a7SBenno Lossin ///
7957f8977a7SBenno Lossin /// #[pin_data]
7967f8977a7SBenno Lossin /// struct Foo {
7977f8977a7SBenno Lossin /// #[pin]
7987f8977a7SBenno Lossin /// raw: Opaque<RawFoo>,
7997f8977a7SBenno Lossin /// }
8007f8977a7SBenno Lossin ///
8017f8977a7SBenno Lossin /// impl Foo {
8027f8977a7SBenno Lossin /// fn setup(self: Pin<&mut Self>) {
803*2592a628SAlban Kurti /// pr_info!("Setting up foo\n");
8047f8977a7SBenno Lossin /// }
8057f8977a7SBenno Lossin /// }
8067f8977a7SBenno Lossin ///
8077f8977a7SBenno Lossin /// let foo = pin_init!(Foo {
8087f8977a7SBenno Lossin /// raw <- unsafe {
8097f8977a7SBenno Lossin /// Opaque::ffi_init(|s| {
8107f8977a7SBenno Lossin /// init_foo(s);
8117f8977a7SBenno Lossin /// })
8127f8977a7SBenno Lossin /// },
8137f8977a7SBenno Lossin /// }).pin_chain(|foo| {
8147f8977a7SBenno Lossin /// foo.setup();
8157f8977a7SBenno Lossin /// Ok(())
8167f8977a7SBenno Lossin /// });
8177f8977a7SBenno Lossin /// ```
pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E> where F: FnOnce(Pin<&mut T>) -> Result<(), E>,8187f8977a7SBenno Lossin fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
8197f8977a7SBenno Lossin where
8207f8977a7SBenno Lossin F: FnOnce(Pin<&mut T>) -> Result<(), E>,
8217f8977a7SBenno Lossin {
8227f8977a7SBenno Lossin ChainPinInit(self, f, PhantomData)
8237f8977a7SBenno Lossin }
8247f8977a7SBenno Lossin }
8257f8977a7SBenno Lossin
8267f8977a7SBenno Lossin /// An initializer returned by [`PinInit::pin_chain`].
8277f8977a7SBenno Lossin pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, Box<T>)>);
8287f8977a7SBenno Lossin
8297f8977a7SBenno Lossin // SAFETY: The `__pinned_init` function is implemented such that it
8307f8977a7SBenno Lossin // - returns `Ok(())` on successful initialization,
8317f8977a7SBenno Lossin // - returns `Err(err)` on error and in this case `slot` will be dropped.
8327f8977a7SBenno Lossin // - considers `slot` pinned.
8337f8977a7SBenno Lossin unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainPinInit<I, F, T, E>
8347f8977a7SBenno Lossin where
8357f8977a7SBenno Lossin I: PinInit<T, E>,
8367f8977a7SBenno Lossin F: FnOnce(Pin<&mut T>) -> Result<(), E>,
8377f8977a7SBenno Lossin {
__pinned_init(self, slot: *mut T) -> Result<(), E>8387f8977a7SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
8397f8977a7SBenno Lossin // SAFETY: All requirements fulfilled since this function is `__pinned_init`.
8407f8977a7SBenno Lossin unsafe { self.0.__pinned_init(slot)? };
8417f8977a7SBenno Lossin // SAFETY: The above call initialized `slot` and we still have unique access.
8427f8977a7SBenno Lossin let val = unsafe { &mut *slot };
8437f8977a7SBenno Lossin // SAFETY: `slot` is considered pinned.
8447f8977a7SBenno Lossin let val = unsafe { Pin::new_unchecked(val) };
8457f8977a7SBenno Lossin (self.1)(val).map_err(|e| {
8467f8977a7SBenno Lossin // SAFETY: `slot` was initialized above.
8477f8977a7SBenno Lossin unsafe { core::ptr::drop_in_place(slot) };
8487f8977a7SBenno Lossin e
8497f8977a7SBenno Lossin })
8507f8977a7SBenno Lossin }
85190e53c5eSBenno Lossin }
85290e53c5eSBenno Lossin
85390e53c5eSBenno Lossin /// An initializer for `T`.
85490e53c5eSBenno Lossin ///
85590e53c5eSBenno Lossin /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
8566841d45aSBenno Lossin /// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use the
8576841d45aSBenno Lossin /// [`InPlaceInit::init`] function of a smart pointer like [`Arc<T>`] on this. Because
8586841d45aSBenno Lossin /// [`PinInit<T, E>`] is a super trait, you can use every function that takes it as well.
85990e53c5eSBenno Lossin ///
86090e53c5eSBenno Lossin /// Also see the [module description](self).
86190e53c5eSBenno Lossin ///
86290e53c5eSBenno Lossin /// # Safety
86390e53c5eSBenno Lossin ///
86490e53c5eSBenno Lossin /// When implementing this type you will need to take great care. Also there are probably very few
86590e53c5eSBenno Lossin /// cases where a manual implementation is necessary. Use [`init_from_closure`] where possible.
86690e53c5eSBenno Lossin ///
86790e53c5eSBenno Lossin /// The [`Init::__init`] function
86890e53c5eSBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
86990e53c5eSBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
87090e53c5eSBenno Lossin /// - `slot` can be deallocated without UB occurring,
87190e53c5eSBenno Lossin /// - `slot` does not need to be dropped,
87290e53c5eSBenno Lossin /// - `slot` is not partially initialized.
87390e53c5eSBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
87490e53c5eSBenno Lossin ///
87590e53c5eSBenno Lossin /// The `__pinned_init` function from the supertrait [`PinInit`] needs to execute the exact same
87690e53c5eSBenno Lossin /// code as `__init`.
87790e53c5eSBenno Lossin ///
87890e53c5eSBenno Lossin /// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
87990e53c5eSBenno Lossin /// move the pointee after initialization.
88090e53c5eSBenno Lossin ///
88190e53c5eSBenno Lossin /// [`Arc<T>`]: crate::sync::Arc
88290e53c5eSBenno Lossin #[must_use = "An initializer must be used in order to create its value."]
8831a8076acSBenno Lossin pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
88490e53c5eSBenno Lossin /// Initializes `slot`.
88590e53c5eSBenno Lossin ///
88690e53c5eSBenno Lossin /// # Safety
88790e53c5eSBenno Lossin ///
88890e53c5eSBenno Lossin /// - `slot` is a valid pointer to uninitialized memory.
88990e53c5eSBenno Lossin /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
89090e53c5eSBenno Lossin /// deallocate.
__init(self, slot: *mut T) -> Result<(), E>89190e53c5eSBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
8927f8977a7SBenno Lossin
8937f8977a7SBenno Lossin /// First initializes the value using `self` then calls the function `f` with the initialized
8947f8977a7SBenno Lossin /// value.
8957f8977a7SBenno Lossin ///
8967f8977a7SBenno Lossin /// If `f` returns an error the value is dropped and the initializer will forward the error.
8977f8977a7SBenno Lossin ///
8987f8977a7SBenno Lossin /// # Examples
8997f8977a7SBenno Lossin ///
9007f8977a7SBenno Lossin /// ```rust
9017f8977a7SBenno Lossin /// # #![allow(clippy::disallowed_names)]
9027f8977a7SBenno Lossin /// use kernel::{types::Opaque, init::{self, init_from_closure}};
9037f8977a7SBenno Lossin /// struct Foo {
9047f8977a7SBenno Lossin /// buf: [u8; 1_000_000],
9057f8977a7SBenno Lossin /// }
9067f8977a7SBenno Lossin ///
9077f8977a7SBenno Lossin /// impl Foo {
9087f8977a7SBenno Lossin /// fn setup(&mut self) {
909*2592a628SAlban Kurti /// pr_info!("Setting up foo\n");
9107f8977a7SBenno Lossin /// }
9117f8977a7SBenno Lossin /// }
9127f8977a7SBenno Lossin ///
9137f8977a7SBenno Lossin /// let foo = init!(Foo {
9147f8977a7SBenno Lossin /// buf <- init::zeroed()
9157f8977a7SBenno Lossin /// }).chain(|foo| {
9167f8977a7SBenno Lossin /// foo.setup();
9177f8977a7SBenno Lossin /// Ok(())
9187f8977a7SBenno Lossin /// });
9197f8977a7SBenno Lossin /// ```
chain<F>(self, f: F) -> ChainInit<Self, F, T, E> where F: FnOnce(&mut T) -> Result<(), E>,9207f8977a7SBenno Lossin fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
9217f8977a7SBenno Lossin where
9227f8977a7SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
9237f8977a7SBenno Lossin {
9247f8977a7SBenno Lossin ChainInit(self, f, PhantomData)
9257f8977a7SBenno Lossin }
92690e53c5eSBenno Lossin }
92790e53c5eSBenno Lossin
9287f8977a7SBenno Lossin /// An initializer returned by [`Init::chain`].
9297f8977a7SBenno Lossin pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, Box<T>)>);
9307f8977a7SBenno Lossin
9317f8977a7SBenno Lossin // SAFETY: The `__init` function is implemented such that it
9327f8977a7SBenno Lossin // - returns `Ok(())` on successful initialization,
9337f8977a7SBenno Lossin // - returns `Err(err)` on error and in this case `slot` will be dropped.
9347f8977a7SBenno Lossin unsafe impl<T: ?Sized, E, I, F> Init<T, E> for ChainInit<I, F, T, E>
93590e53c5eSBenno Lossin where
93690e53c5eSBenno Lossin I: Init<T, E>,
9377f8977a7SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
9387f8977a7SBenno Lossin {
__init(self, slot: *mut T) -> Result<(), E>9397f8977a7SBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
9407f8977a7SBenno Lossin // SAFETY: All requirements fulfilled since this function is `__init`.
9417f8977a7SBenno Lossin unsafe { self.0.__pinned_init(slot)? };
9427f8977a7SBenno Lossin // SAFETY: The above call initialized `slot` and we still have unique access.
9437f8977a7SBenno Lossin (self.1)(unsafe { &mut *slot }).map_err(|e| {
9447f8977a7SBenno Lossin // SAFETY: `slot` was initialized above.
9457f8977a7SBenno Lossin unsafe { core::ptr::drop_in_place(slot) };
9467f8977a7SBenno Lossin e
9477f8977a7SBenno Lossin })
9487f8977a7SBenno Lossin }
9497f8977a7SBenno Lossin }
9507f8977a7SBenno Lossin
9517f8977a7SBenno Lossin // SAFETY: `__pinned_init` behaves exactly the same as `__init`.
9527f8977a7SBenno Lossin unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainInit<I, F, T, E>
9537f8977a7SBenno Lossin where
9547f8977a7SBenno Lossin I: Init<T, E>,
9557f8977a7SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
95690e53c5eSBenno Lossin {
__pinned_init(self, slot: *mut T) -> Result<(), E>95790e53c5eSBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
9587f8977a7SBenno Lossin // SAFETY: `__init` has less strict requirements compared to `__pinned_init`.
95990e53c5eSBenno Lossin unsafe { self.__init(slot) }
96090e53c5eSBenno Lossin }
96190e53c5eSBenno Lossin }
96290e53c5eSBenno Lossin
96390e53c5eSBenno Lossin /// Creates a new [`PinInit<T, E>`] from the given closure.
96490e53c5eSBenno Lossin ///
96590e53c5eSBenno Lossin /// # Safety
96690e53c5eSBenno Lossin ///
96790e53c5eSBenno Lossin /// The closure:
96890e53c5eSBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
96990e53c5eSBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
97090e53c5eSBenno Lossin /// - `slot` can be deallocated without UB occurring,
97190e53c5eSBenno Lossin /// - `slot` does not need to be dropped,
97290e53c5eSBenno Lossin /// - `slot` is not partially initialized.
97390e53c5eSBenno Lossin /// - may assume that the `slot` does not move if `T: !Unpin`,
97490e53c5eSBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
97590e53c5eSBenno Lossin #[inline]
pin_init_from_closure<T: ?Sized, E>( f: impl FnOnce(*mut T) -> Result<(), E>, ) -> impl PinInit<T, E>97690e53c5eSBenno Lossin pub const unsafe fn pin_init_from_closure<T: ?Sized, E>(
97790e53c5eSBenno Lossin f: impl FnOnce(*mut T) -> Result<(), E>,
97890e53c5eSBenno Lossin ) -> impl PinInit<T, E> {
97990e53c5eSBenno Lossin __internal::InitClosure(f, PhantomData)
98090e53c5eSBenno Lossin }
98190e53c5eSBenno Lossin
98290e53c5eSBenno Lossin /// Creates a new [`Init<T, E>`] from the given closure.
98390e53c5eSBenno Lossin ///
98490e53c5eSBenno Lossin /// # Safety
98590e53c5eSBenno Lossin ///
98690e53c5eSBenno Lossin /// The closure:
98790e53c5eSBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
98890e53c5eSBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
98990e53c5eSBenno Lossin /// - `slot` can be deallocated without UB occurring,
99090e53c5eSBenno Lossin /// - `slot` does not need to be dropped,
99190e53c5eSBenno Lossin /// - `slot` is not partially initialized.
99290e53c5eSBenno Lossin /// - the `slot` may move after initialization.
99390e53c5eSBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
99490e53c5eSBenno Lossin #[inline]
init_from_closure<T: ?Sized, E>( f: impl FnOnce(*mut T) -> Result<(), E>, ) -> impl Init<T, E>99590e53c5eSBenno Lossin pub const unsafe fn init_from_closure<T: ?Sized, E>(
99690e53c5eSBenno Lossin f: impl FnOnce(*mut T) -> Result<(), E>,
99790e53c5eSBenno Lossin ) -> impl Init<T, E> {
99890e53c5eSBenno Lossin __internal::InitClosure(f, PhantomData)
99990e53c5eSBenno Lossin }
100090e53c5eSBenno Lossin
100190e53c5eSBenno Lossin /// An initializer that leaves the memory uninitialized.
100290e53c5eSBenno Lossin ///
100390e53c5eSBenno Lossin /// The initializer is a no-op. The `slot` memory is not changed.
100490e53c5eSBenno Lossin #[inline]
uninit<T, E>() -> impl Init<MaybeUninit<T>, E>100590e53c5eSBenno Lossin pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
100690e53c5eSBenno Lossin // SAFETY: The memory is allowed to be uninitialized.
100790e53c5eSBenno Lossin unsafe { init_from_closure(|_| Ok(())) }
100890e53c5eSBenno Lossin }
100990e53c5eSBenno Lossin
10109e494390SBenno Lossin /// Initializes an array by initializing each element via the provided initializer.
10119e494390SBenno Lossin ///
10129e494390SBenno Lossin /// # Examples
10139e494390SBenno Lossin ///
10149e494390SBenno Lossin /// ```rust
10159e494390SBenno Lossin /// use kernel::{error::Error, init::init_array_from_fn};
10169e494390SBenno Lossin /// let array: Box<[usize; 1_000]>= Box::init::<Error>(init_array_from_fn(|i| i)).unwrap();
10179e494390SBenno Lossin /// assert_eq!(array.len(), 1_000);
10189e494390SBenno Lossin /// ```
init_array_from_fn<I, const N: usize, T, E>( mut make_init: impl FnMut(usize) -> I, ) -> impl Init<[T; N], E> where I: Init<T, E>,10199e494390SBenno Lossin pub fn init_array_from_fn<I, const N: usize, T, E>(
10209e494390SBenno Lossin mut make_init: impl FnMut(usize) -> I,
10219e494390SBenno Lossin ) -> impl Init<[T; N], E>
10229e494390SBenno Lossin where
10239e494390SBenno Lossin I: Init<T, E>,
10249e494390SBenno Lossin {
10259e494390SBenno Lossin let init = move |slot: *mut [T; N]| {
10269e494390SBenno Lossin let slot = slot.cast::<T>();
10279e494390SBenno Lossin // Counts the number of initialized elements and when dropped drops that many elements from
10289e494390SBenno Lossin // `slot`.
10299e494390SBenno Lossin let mut init_count = ScopeGuard::new_with_data(0, |i| {
10309e494390SBenno Lossin // We now free every element that has been initialized before:
10319e494390SBenno Lossin // SAFETY: The loop initialized exactly the values from 0..i and since we
10329e494390SBenno Lossin // return `Err` below, the caller will consider the memory at `slot` as
10339e494390SBenno Lossin // uninitialized.
10349e494390SBenno Lossin unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
10359e494390SBenno Lossin });
10369e494390SBenno Lossin for i in 0..N {
10379e494390SBenno Lossin let init = make_init(i);
10389e494390SBenno Lossin // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
10399e494390SBenno Lossin let ptr = unsafe { slot.add(i) };
10409e494390SBenno Lossin // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
10419e494390SBenno Lossin // requirements.
10429e494390SBenno Lossin unsafe { init.__init(ptr) }?;
10439e494390SBenno Lossin *init_count += 1;
10449e494390SBenno Lossin }
10459e494390SBenno Lossin init_count.dismiss();
10469e494390SBenno Lossin Ok(())
10479e494390SBenno Lossin };
10489e494390SBenno Lossin // SAFETY: The initializer above initializes every element of the array. On failure it drops
10499e494390SBenno Lossin // any initialized elements and returns `Err`.
10509e494390SBenno Lossin unsafe { init_from_closure(init) }
10519e494390SBenno Lossin }
10529e494390SBenno Lossin
10539e494390SBenno Lossin /// Initializes an array by initializing each element via the provided initializer.
10549e494390SBenno Lossin ///
10559e494390SBenno Lossin /// # Examples
10569e494390SBenno Lossin ///
10579e494390SBenno Lossin /// ```rust
10589e494390SBenno Lossin /// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex};
10599e494390SBenno Lossin /// let array: Arc<[Mutex<usize>; 1_000]>=
10609e494390SBenno Lossin /// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i))).unwrap();
10619e494390SBenno Lossin /// assert_eq!(array.len(), 1_000);
10629e494390SBenno Lossin /// ```
pin_init_array_from_fn<I, const N: usize, T, E>( mut make_init: impl FnMut(usize) -> I, ) -> impl PinInit<[T; N], E> where I: PinInit<T, E>,10639e494390SBenno Lossin pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
10649e494390SBenno Lossin mut make_init: impl FnMut(usize) -> I,
10659e494390SBenno Lossin ) -> impl PinInit<[T; N], E>
10669e494390SBenno Lossin where
10679e494390SBenno Lossin I: PinInit<T, E>,
10689e494390SBenno Lossin {
10699e494390SBenno Lossin let init = move |slot: *mut [T; N]| {
10709e494390SBenno Lossin let slot = slot.cast::<T>();
10719e494390SBenno Lossin // Counts the number of initialized elements and when dropped drops that many elements from
10729e494390SBenno Lossin // `slot`.
10739e494390SBenno Lossin let mut init_count = ScopeGuard::new_with_data(0, |i| {
10749e494390SBenno Lossin // We now free every element that has been initialized before:
10759e494390SBenno Lossin // SAFETY: The loop initialized exactly the values from 0..i and since we
10769e494390SBenno Lossin // return `Err` below, the caller will consider the memory at `slot` as
10779e494390SBenno Lossin // uninitialized.
10789e494390SBenno Lossin unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
10799e494390SBenno Lossin });
10809e494390SBenno Lossin for i in 0..N {
10819e494390SBenno Lossin let init = make_init(i);
10829e494390SBenno Lossin // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
10839e494390SBenno Lossin let ptr = unsafe { slot.add(i) };
10849e494390SBenno Lossin // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
10859e494390SBenno Lossin // requirements.
10869e494390SBenno Lossin unsafe { init.__pinned_init(ptr) }?;
10879e494390SBenno Lossin *init_count += 1;
10889e494390SBenno Lossin }
10899e494390SBenno Lossin init_count.dismiss();
10909e494390SBenno Lossin Ok(())
10919e494390SBenno Lossin };
10929e494390SBenno Lossin // SAFETY: The initializer above initializes every element of the array. On failure it drops
10939e494390SBenno Lossin // any initialized elements and returns `Err`.
10949e494390SBenno Lossin unsafe { pin_init_from_closure(init) }
10959e494390SBenno Lossin }
10969e494390SBenno Lossin
109790e53c5eSBenno Lossin // SAFETY: Every type can be initialized by-value.
109852a7f2deSBenno Lossin unsafe impl<T, E> Init<T, E> for T {
__init(self, slot: *mut T) -> Result<(), E>109952a7f2deSBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
110090e53c5eSBenno Lossin unsafe { slot.write(self) };
110190e53c5eSBenno Lossin Ok(())
110290e53c5eSBenno Lossin }
110390e53c5eSBenno Lossin }
110492c4a1e7SBenno Lossin
11051a8076acSBenno Lossin // SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`.
11061a8076acSBenno Lossin unsafe impl<T, E> PinInit<T, E> for T {
__pinned_init(self, slot: *mut T) -> Result<(), E>11071a8076acSBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
11081a8076acSBenno Lossin unsafe { self.__init(slot) }
11091a8076acSBenno Lossin }
11101a8076acSBenno Lossin }
11111a8076acSBenno Lossin
111292c4a1e7SBenno Lossin /// Smart pointer that can initialize memory in-place.
111392c4a1e7SBenno Lossin pub trait InPlaceInit<T>: Sized {
111492c4a1e7SBenno Lossin /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
111592c4a1e7SBenno Lossin /// type.
111692c4a1e7SBenno Lossin ///
111792c4a1e7SBenno Lossin /// If `T: !Unpin` it will not be able to move afterwards.
try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E> where E: From<AllocError>111892c4a1e7SBenno Lossin fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
111992c4a1e7SBenno Lossin where
112092c4a1e7SBenno Lossin E: From<AllocError>;
112192c4a1e7SBenno Lossin
112292c4a1e7SBenno Lossin /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
112392c4a1e7SBenno Lossin /// type.
112492c4a1e7SBenno Lossin ///
112592c4a1e7SBenno Lossin /// If `T: !Unpin` it will not be able to move afterwards.
pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Pin<Self>> where Error: From<E>,112692c4a1e7SBenno Lossin fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Pin<Self>>
112792c4a1e7SBenno Lossin where
112892c4a1e7SBenno Lossin Error: From<E>,
112992c4a1e7SBenno Lossin {
113092c4a1e7SBenno Lossin // SAFETY: We delegate to `init` and only change the error type.
113192c4a1e7SBenno Lossin let init = unsafe {
113292c4a1e7SBenno Lossin pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
113392c4a1e7SBenno Lossin };
113492c4a1e7SBenno Lossin Self::try_pin_init(init)
113592c4a1e7SBenno Lossin }
113692c4a1e7SBenno Lossin
113792c4a1e7SBenno Lossin /// Use the given initializer to in-place initialize a `T`.
try_init<E>(init: impl Init<T, E>) -> Result<Self, E> where E: From<AllocError>113892c4a1e7SBenno Lossin fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
113992c4a1e7SBenno Lossin where
114092c4a1e7SBenno Lossin E: From<AllocError>;
114192c4a1e7SBenno Lossin
114292c4a1e7SBenno Lossin /// Use the given initializer to in-place initialize a `T`.
init<E>(init: impl Init<T, E>) -> error::Result<Self> where Error: From<E>,114392c4a1e7SBenno Lossin fn init<E>(init: impl Init<T, E>) -> error::Result<Self>
114492c4a1e7SBenno Lossin where
114592c4a1e7SBenno Lossin Error: From<E>,
114692c4a1e7SBenno Lossin {
114792c4a1e7SBenno Lossin // SAFETY: We delegate to `init` and only change the error type.
114892c4a1e7SBenno Lossin let init = unsafe {
114992c4a1e7SBenno Lossin init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
115092c4a1e7SBenno Lossin };
115192c4a1e7SBenno Lossin Self::try_init(init)
115292c4a1e7SBenno Lossin }
115392c4a1e7SBenno Lossin }
115492c4a1e7SBenno Lossin
115592c4a1e7SBenno Lossin impl<T> InPlaceInit<T> for Box<T> {
115692c4a1e7SBenno Lossin #[inline]
try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E> where E: From<AllocError>,115792c4a1e7SBenno Lossin fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
115892c4a1e7SBenno Lossin where
115992c4a1e7SBenno Lossin E: From<AllocError>,
116092c4a1e7SBenno Lossin {
116192c4a1e7SBenno Lossin let mut this = Box::try_new_uninit()?;
116292c4a1e7SBenno Lossin let slot = this.as_mut_ptr();
116392c4a1e7SBenno Lossin // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
116492c4a1e7SBenno Lossin // slot is valid and will not be moved, because we pin it later.
116592c4a1e7SBenno Lossin unsafe { init.__pinned_init(slot)? };
116692c4a1e7SBenno Lossin // SAFETY: All fields have been initialized.
116792c4a1e7SBenno Lossin Ok(unsafe { this.assume_init() }.into())
116892c4a1e7SBenno Lossin }
116992c4a1e7SBenno Lossin
117092c4a1e7SBenno Lossin #[inline]
try_init<E>(init: impl Init<T, E>) -> Result<Self, E> where E: From<AllocError>,117192c4a1e7SBenno Lossin fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
117292c4a1e7SBenno Lossin where
117392c4a1e7SBenno Lossin E: From<AllocError>,
117492c4a1e7SBenno Lossin {
117592c4a1e7SBenno Lossin let mut this = Box::try_new_uninit()?;
117692c4a1e7SBenno Lossin let slot = this.as_mut_ptr();
117792c4a1e7SBenno Lossin // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
117892c4a1e7SBenno Lossin // slot is valid.
117992c4a1e7SBenno Lossin unsafe { init.__init(slot)? };
118092c4a1e7SBenno Lossin // SAFETY: All fields have been initialized.
118192c4a1e7SBenno Lossin Ok(unsafe { this.assume_init() })
118292c4a1e7SBenno Lossin }
118392c4a1e7SBenno Lossin }
118492c4a1e7SBenno Lossin
118592c4a1e7SBenno Lossin impl<T> InPlaceInit<T> for UniqueArc<T> {
118692c4a1e7SBenno Lossin #[inline]
try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E> where E: From<AllocError>,118792c4a1e7SBenno Lossin fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
118892c4a1e7SBenno Lossin where
118992c4a1e7SBenno Lossin E: From<AllocError>,
119092c4a1e7SBenno Lossin {
119192c4a1e7SBenno Lossin let mut this = UniqueArc::try_new_uninit()?;
119292c4a1e7SBenno Lossin let slot = this.as_mut_ptr();
119392c4a1e7SBenno Lossin // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
119492c4a1e7SBenno Lossin // slot is valid and will not be moved, because we pin it later.
119592c4a1e7SBenno Lossin unsafe { init.__pinned_init(slot)? };
119692c4a1e7SBenno Lossin // SAFETY: All fields have been initialized.
119792c4a1e7SBenno Lossin Ok(unsafe { this.assume_init() }.into())
119892c4a1e7SBenno Lossin }
119992c4a1e7SBenno Lossin
120092c4a1e7SBenno Lossin #[inline]
try_init<E>(init: impl Init<T, E>) -> Result<Self, E> where E: From<AllocError>,120192c4a1e7SBenno Lossin fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
120292c4a1e7SBenno Lossin where
120392c4a1e7SBenno Lossin E: From<AllocError>,
120492c4a1e7SBenno Lossin {
120592c4a1e7SBenno Lossin let mut this = UniqueArc::try_new_uninit()?;
120692c4a1e7SBenno Lossin let slot = this.as_mut_ptr();
120792c4a1e7SBenno Lossin // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
120892c4a1e7SBenno Lossin // slot is valid.
120992c4a1e7SBenno Lossin unsafe { init.__init(slot)? };
121092c4a1e7SBenno Lossin // SAFETY: All fields have been initialized.
121192c4a1e7SBenno Lossin Ok(unsafe { this.assume_init() })
121292c4a1e7SBenno Lossin }
121392c4a1e7SBenno Lossin }
1214d0fdc396SBenno Lossin
1215d0fdc396SBenno Lossin /// Trait facilitating pinned destruction.
1216d0fdc396SBenno Lossin ///
1217d0fdc396SBenno Lossin /// Use [`pinned_drop`] to implement this trait safely:
1218d0fdc396SBenno Lossin ///
1219d0fdc396SBenno Lossin /// ```rust
1220d0fdc396SBenno Lossin /// # use kernel::sync::Mutex;
1221d0fdc396SBenno Lossin /// use kernel::macros::pinned_drop;
1222d0fdc396SBenno Lossin /// use core::pin::Pin;
1223d0fdc396SBenno Lossin /// #[pin_data(PinnedDrop)]
1224d0fdc396SBenno Lossin /// struct Foo {
1225d0fdc396SBenno Lossin /// #[pin]
1226d0fdc396SBenno Lossin /// mtx: Mutex<usize>,
1227d0fdc396SBenno Lossin /// }
1228d0fdc396SBenno Lossin ///
1229d0fdc396SBenno Lossin /// #[pinned_drop]
1230d0fdc396SBenno Lossin /// impl PinnedDrop for Foo {
1231d0fdc396SBenno Lossin /// fn drop(self: Pin<&mut Self>) {
1232*2592a628SAlban Kurti /// pr_info!("Foo is being dropped!\n");
1233d0fdc396SBenno Lossin /// }
1234d0fdc396SBenno Lossin /// }
1235d0fdc396SBenno Lossin /// ```
1236d0fdc396SBenno Lossin ///
1237d0fdc396SBenno Lossin /// # Safety
1238d0fdc396SBenno Lossin ///
1239d0fdc396SBenno Lossin /// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
1240d0fdc396SBenno Lossin ///
1241d0fdc396SBenno Lossin /// [`pinned_drop`]: kernel::macros::pinned_drop
1242d0fdc396SBenno Lossin pub unsafe trait PinnedDrop: __internal::HasPinData {
1243d0fdc396SBenno Lossin /// Executes the pinned destructor of this type.
1244d0fdc396SBenno Lossin ///
1245d0fdc396SBenno Lossin /// While this function is marked safe, it is actually unsafe to call it manually. For this
1246d0fdc396SBenno Lossin /// reason it takes an additional parameter. This type can only be constructed by `unsafe` code
1247d0fdc396SBenno Lossin /// and thus prevents this function from being called where it should not.
1248d0fdc396SBenno Lossin ///
1249d0fdc396SBenno Lossin /// This extra parameter will be generated by the `#[pinned_drop]` proc-macro attribute
1250d0fdc396SBenno Lossin /// automatically.
drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop)1251d0fdc396SBenno Lossin fn drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop);
1252d0fdc396SBenno Lossin }
125338cde0bdSBenno Lossin
125438cde0bdSBenno Lossin /// Marker trait for types that can be initialized by writing just zeroes.
125538cde0bdSBenno Lossin ///
125638cde0bdSBenno Lossin /// # Safety
125738cde0bdSBenno Lossin ///
125838cde0bdSBenno Lossin /// The bit pattern consisting of only zeroes is a valid bit pattern for this type. In other words,
125938cde0bdSBenno Lossin /// this is not UB:
126038cde0bdSBenno Lossin ///
126138cde0bdSBenno Lossin /// ```rust,ignore
126238cde0bdSBenno Lossin /// let val: Self = unsafe { core::mem::zeroed() };
126338cde0bdSBenno Lossin /// ```
126438cde0bdSBenno Lossin pub unsafe trait Zeroable {}
126538cde0bdSBenno Lossin
126638cde0bdSBenno Lossin /// Create a new zeroed T.
126738cde0bdSBenno Lossin ///
126838cde0bdSBenno Lossin /// The returned initializer will write `0x00` to every byte of the given `slot`.
126938cde0bdSBenno Lossin #[inline]
zeroed<T: Zeroable>() -> impl Init<T>127038cde0bdSBenno Lossin pub fn zeroed<T: Zeroable>() -> impl Init<T> {
127138cde0bdSBenno Lossin // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
127238cde0bdSBenno Lossin // and because we write all zeroes, the memory is initialized.
127338cde0bdSBenno Lossin unsafe {
127438cde0bdSBenno Lossin init_from_closure(|slot: *mut T| {
127538cde0bdSBenno Lossin slot.write_bytes(0, 1);
127638cde0bdSBenno Lossin Ok(())
127738cde0bdSBenno Lossin })
127838cde0bdSBenno Lossin }
127938cde0bdSBenno Lossin }
128038cde0bdSBenno Lossin
128138cde0bdSBenno Lossin macro_rules! impl_zeroable {
128238cde0bdSBenno Lossin ($($({$($generics:tt)*})? $t:ty, )*) => {
128338cde0bdSBenno Lossin $(unsafe impl$($($generics)*)? Zeroable for $t {})*
128438cde0bdSBenno Lossin };
128538cde0bdSBenno Lossin }
128638cde0bdSBenno Lossin
128738cde0bdSBenno Lossin impl_zeroable! {
128838cde0bdSBenno Lossin // SAFETY: All primitives that are allowed to be zero.
128938cde0bdSBenno Lossin bool,
129038cde0bdSBenno Lossin char,
129138cde0bdSBenno Lossin u8, u16, u32, u64, u128, usize,
129238cde0bdSBenno Lossin i8, i16, i32, i64, i128, isize,
129338cde0bdSBenno Lossin f32, f64,
129438cde0bdSBenno Lossin
1295c34a8052SLaine Taffin Altman // Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
1296c34a8052SLaine Taffin Altman // creating an instance of an uninhabited type is immediate undefined behavior. For more on
1297c34a8052SLaine Taffin Altman // uninhabited/empty types, consult The Rustonomicon:
1298c34a8052SLaine Taffin Altman // <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
1299c34a8052SLaine Taffin Altman // also has information on undefined behavior:
1300c34a8052SLaine Taffin Altman // <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
1301c34a8052SLaine Taffin Altman //
1302c34a8052SLaine Taffin Altman // SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
1303c34a8052SLaine Taffin Altman {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
130438cde0bdSBenno Lossin
130538cde0bdSBenno Lossin // SAFETY: Type is allowed to take any value, including all zeros.
130638cde0bdSBenno Lossin {<T>} MaybeUninit<T>,
13072e704f18SBenno Lossin // SAFETY: Type is allowed to take any value, including all zeros.
13082e704f18SBenno Lossin {<T>} Opaque<T>,
13092e704f18SBenno Lossin
13102e704f18SBenno Lossin // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.
13112e704f18SBenno Lossin {<T: ?Sized + Zeroable>} UnsafeCell<T>,
131238cde0bdSBenno Lossin
1313aa4d9b54SBenno Lossin // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
1314aa4d9b54SBenno Lossin // https://doc.rust-lang.org/stable/std/option/index.html#representation).
131538cde0bdSBenno Lossin Option<NonZeroU8>, Option<NonZeroU16>, Option<NonZeroU32>, Option<NonZeroU64>,
131638cde0bdSBenno Lossin Option<NonZeroU128>, Option<NonZeroUsize>,
131738cde0bdSBenno Lossin Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>,
131838cde0bdSBenno Lossin Option<NonZeroI128>, Option<NonZeroIsize>,
1319aa4d9b54SBenno Lossin {<T>} Option<NonNull<T>>,
1320aa4d9b54SBenno Lossin {<T>} Option<Box<T>>,
132138cde0bdSBenno Lossin
132238cde0bdSBenno Lossin // SAFETY: `null` pointer is valid.
132338cde0bdSBenno Lossin //
132438cde0bdSBenno Lossin // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be
132538cde0bdSBenno Lossin // null.
132638cde0bdSBenno Lossin //
132738cde0bdSBenno Lossin // When `Pointee` gets stabilized, we could use
132838cde0bdSBenno Lossin // `T: ?Sized where <T as Pointee>::Metadata: Zeroable`
132938cde0bdSBenno Lossin {<T>} *mut T, {<T>} *const T,
133038cde0bdSBenno Lossin
133138cde0bdSBenno Lossin // SAFETY: `null` pointer is valid and the metadata part of these fat pointers is allowed to be
133238cde0bdSBenno Lossin // zero.
133338cde0bdSBenno Lossin {<T>} *mut [T], {<T>} *const [T], *mut str, *const str,
133438cde0bdSBenno Lossin
133538cde0bdSBenno Lossin // SAFETY: `T` is `Zeroable`.
133638cde0bdSBenno Lossin {<const N: usize, T: Zeroable>} [T; N], {<T: Zeroable>} Wrapping<T>,
133738cde0bdSBenno Lossin }
133838cde0bdSBenno Lossin
133938cde0bdSBenno Lossin macro_rules! impl_tuple_zeroable {
134038cde0bdSBenno Lossin ($(,)?) => {};
134138cde0bdSBenno Lossin ($first:ident, $($t:ident),* $(,)?) => {
134238cde0bdSBenno Lossin // SAFETY: All elements are zeroable and padding can be zero.
134338cde0bdSBenno Lossin unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}
134438cde0bdSBenno Lossin impl_tuple_zeroable!($($t),* ,);
134538cde0bdSBenno Lossin }
134638cde0bdSBenno Lossin }
134738cde0bdSBenno Lossin
134838cde0bdSBenno Lossin impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);
1349