1fbf8fb32SBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT
2fbf8fb32SBenno Lossin
302c01c08SBenno Lossin //! Library to safely and fallibly initialize pinned `struct`s using in-place constructors.
402c01c08SBenno Lossin //!
502c01c08SBenno Lossin //! [Pinning][pinning] is Rust's way of ensuring data does not move.
6fbf8fb32SBenno Lossin //!
7fbf8fb32SBenno Lossin //! It also allows in-place initialization of big `struct`s that would otherwise produce a stack
8fbf8fb32SBenno Lossin //! overflow.
9fbf8fb32SBenno Lossin //!
1002c01c08SBenno Lossin //! This library's main use-case is in [Rust-for-Linux]. Although this version can be used
1102c01c08SBenno Lossin //! standalone.
1202c01c08SBenno Lossin //!
1302c01c08SBenno Lossin //! There are cases when you want to in-place initialize a struct. For example when it is very big
1402c01c08SBenno Lossin //! and moving it from the stack is not an option, because it is bigger than the stack itself.
1502c01c08SBenno Lossin //! Another reason would be that you need the address of the object to initialize it. This stands
1602c01c08SBenno Lossin //! in direct conflict with Rust's normal process of first initializing an object and then moving
1702c01c08SBenno Lossin //! it into it's final memory location. For more information, see
1802c01c08SBenno Lossin //! <https://rust-for-linux.com/the-safe-pinned-initialization-problem>.
1902c01c08SBenno Lossin //!
2002c01c08SBenno Lossin //! This library allows you to do in-place initialization safely.
2102c01c08SBenno Lossin //!
2202c01c08SBenno Lossin //! ## Nightly Needed for `alloc` feature
2302c01c08SBenno Lossin //!
2402c01c08SBenno Lossin //! This library requires the [`allocator_api` unstable feature] when the `alloc` feature is
2502c01c08SBenno Lossin //! enabled and thus this feature can only be used with a nightly compiler. When enabling the
2602c01c08SBenno Lossin //! `alloc` feature, the user will be required to activate `allocator_api` as well.
2702c01c08SBenno Lossin //!
2802c01c08SBenno Lossin //! [`allocator_api` unstable feature]: https://doc.rust-lang.org/nightly/unstable-book/library-features/allocator-api.html
2902c01c08SBenno Lossin //!
3002c01c08SBenno Lossin //! The feature is enabled by default, thus by default `pin-init` will require a nightly compiler.
3102c01c08SBenno Lossin //! However, using the crate on stable compilers is possible by disabling `alloc`. In practice this
3202c01c08SBenno Lossin //! will require the `std` feature, because stable compilers have neither `Box` nor `Arc` in no-std
3302c01c08SBenno Lossin //! mode.
3402c01c08SBenno Lossin //!
35fbf8fb32SBenno Lossin //! # Overview
36fbf8fb32SBenno Lossin //!
37fbf8fb32SBenno Lossin //! To initialize a `struct` with an in-place constructor you will need two things:
38fbf8fb32SBenno Lossin //! - an in-place constructor,
39fbf8fb32SBenno Lossin //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
40129e97beSBenno Lossin //! [`Box<T>`] or any other smart pointer that supports this library).
41fbf8fb32SBenno Lossin //!
42fbf8fb32SBenno Lossin //! To get an in-place constructor there are generally three options:
43fbf8fb32SBenno Lossin //! - directly creating an in-place constructor using the [`pin_init!`] macro,
44fbf8fb32SBenno Lossin //! - a custom function/macro returning an in-place constructor provided by someone else,
45fbf8fb32SBenno Lossin //! - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
46fbf8fb32SBenno Lossin //!
4702c01c08SBenno Lossin //! Aside from pinned initialization, this library also supports in-place construction without
4802c01c08SBenno Lossin //! pinning, the macros/types/functions are generally named like the pinned variants without the
4902c01c08SBenno Lossin //! `pin_` prefix.
50fbf8fb32SBenno Lossin //!
51fbf8fb32SBenno Lossin //! # Examples
52fbf8fb32SBenno Lossin //!
5302c01c08SBenno Lossin //! Throughout the examples we will often make use of the `CMutex` type which can be found in
5402c01c08SBenno Lossin //! `../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from
5502c01c08SBenno Lossin //! the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list
5602c01c08SBenno Lossin //! requires it to be pinned to be locked and thus is a prime candidate for using this library.
5702c01c08SBenno Lossin //!
58fbf8fb32SBenno Lossin //! ## Using the [`pin_init!`] macro
59fbf8fb32SBenno Lossin //!
60fbf8fb32SBenno Lossin //! If you want to use [`PinInit`], then you will have to annotate your `struct` with
61fbf8fb32SBenno Lossin //! `#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for
62fbf8fb32SBenno Lossin //! [structurally pinned fields]. After doing this, you can then create an in-place constructor via
63fbf8fb32SBenno Lossin //! [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
64fbf8fb32SBenno Lossin //! that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
65fbf8fb32SBenno Lossin //!
661ab10101SBenno Lossin //! ```rust
67fbf8fb32SBenno Lossin //! # #![expect(clippy::disallowed_names)]
6884837cf6SBenno Lossin //! # #![feature(allocator_api)]
6984837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
70fbf8fb32SBenno Lossin //! # use core::pin::Pin;
7102c01c08SBenno Lossin //! use pin_init::{pin_data, pin_init, InPlaceInit};
7284837cf6SBenno Lossin //!
73fbf8fb32SBenno Lossin //! #[pin_data]
74fbf8fb32SBenno Lossin //! struct Foo {
75fbf8fb32SBenno Lossin //! #[pin]
7684837cf6SBenno Lossin //! a: CMutex<usize>,
77fbf8fb32SBenno Lossin //! b: u32,
78fbf8fb32SBenno Lossin //! }
79fbf8fb32SBenno Lossin //!
80fbf8fb32SBenno Lossin //! let foo = pin_init!(Foo {
8184837cf6SBenno Lossin //! a <- CMutex::new(42),
82fbf8fb32SBenno Lossin //! b: 24,
83fbf8fb32SBenno Lossin //! });
8484837cf6SBenno Lossin //! # let _ = Box::pin_init(foo);
85fbf8fb32SBenno Lossin //! ```
86fbf8fb32SBenno Lossin //!
87fbf8fb32SBenno Lossin //! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
88fbf8fb32SBenno Lossin //! (or just the stack) to actually initialize a `Foo`:
89fbf8fb32SBenno Lossin //!
901ab10101SBenno Lossin //! ```rust
91fbf8fb32SBenno Lossin //! # #![expect(clippy::disallowed_names)]
9284837cf6SBenno Lossin //! # #![feature(allocator_api)]
9384837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
9484837cf6SBenno Lossin //! # use core::{alloc::AllocError, pin::Pin};
9584837cf6SBenno Lossin //! # use pin_init::*;
9684837cf6SBenno Lossin //! #
97fbf8fb32SBenno Lossin //! # #[pin_data]
98fbf8fb32SBenno Lossin //! # struct Foo {
99fbf8fb32SBenno Lossin //! # #[pin]
10084837cf6SBenno Lossin //! # a: CMutex<usize>,
101fbf8fb32SBenno Lossin //! # b: u32,
102fbf8fb32SBenno Lossin //! # }
10384837cf6SBenno Lossin //! #
104fbf8fb32SBenno Lossin //! # let foo = pin_init!(Foo {
10584837cf6SBenno Lossin //! # a <- CMutex::new(42),
106fbf8fb32SBenno Lossin //! # b: 24,
107fbf8fb32SBenno Lossin //! # });
10884837cf6SBenno Lossin //! let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo);
109fbf8fb32SBenno Lossin //! ```
110fbf8fb32SBenno Lossin //!
111fbf8fb32SBenno Lossin //! For more information see the [`pin_init!`] macro.
112fbf8fb32SBenno Lossin //!
113fbf8fb32SBenno Lossin //! ## Using a custom function/macro that returns an initializer
114fbf8fb32SBenno Lossin //!
11502c01c08SBenno Lossin //! Many types that use this library supply a function/macro that returns an initializer, because
11602c01c08SBenno Lossin //! the above method only works for types where you can access the fields.
117fbf8fb32SBenno Lossin //!
1181ab10101SBenno Lossin //! ```rust
11984837cf6SBenno Lossin //! # #![feature(allocator_api)]
12084837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
12184837cf6SBenno Lossin //! # use pin_init::*;
12284837cf6SBenno Lossin //! # use std::sync::Arc;
12384837cf6SBenno Lossin //! # use core::pin::Pin;
12484837cf6SBenno Lossin //! let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
125fbf8fb32SBenno Lossin //! ```
126fbf8fb32SBenno Lossin //!
127fbf8fb32SBenno Lossin //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
128fbf8fb32SBenno Lossin //!
1291ab10101SBenno Lossin //! ```rust
13084837cf6SBenno Lossin //! # #![feature(allocator_api)]
13184837cf6SBenno Lossin //! # use pin_init::*;
13284837cf6SBenno Lossin //! # #[path = "../examples/error.rs"] mod error; use error::Error;
13384837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
134fbf8fb32SBenno Lossin //! #[pin_data]
135fbf8fb32SBenno Lossin //! struct DriverData {
136fbf8fb32SBenno Lossin //! #[pin]
13784837cf6SBenno Lossin //! status: CMutex<i32>,
13884837cf6SBenno Lossin //! buffer: Box<[u8; 1_000_000]>,
139fbf8fb32SBenno Lossin //! }
140fbf8fb32SBenno Lossin //!
141fbf8fb32SBenno Lossin //! impl DriverData {
142fbf8fb32SBenno Lossin //! fn new() -> impl PinInit<Self, Error> {
143fbf8fb32SBenno Lossin //! try_pin_init!(Self {
14484837cf6SBenno Lossin //! status <- CMutex::new(0),
14584837cf6SBenno Lossin //! buffer: Box::init(pin_init::zeroed())?,
14684837cf6SBenno Lossin //! }? Error)
147fbf8fb32SBenno Lossin //! }
148fbf8fb32SBenno Lossin //! }
149fbf8fb32SBenno Lossin //! ```
150fbf8fb32SBenno Lossin //!
151fbf8fb32SBenno Lossin //! ## Manual creation of an initializer
152fbf8fb32SBenno Lossin //!
153fbf8fb32SBenno Lossin //! Often when working with primitives the previous approaches are not sufficient. That is where
154fbf8fb32SBenno Lossin //! [`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a
155fbf8fb32SBenno Lossin //! [`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure
156fbf8fb32SBenno Lossin //! actually does the initialization in the correct way. Here are the things to look out for
157fbf8fb32SBenno Lossin //! (we are calling the parameter to the closure `slot`):
158fbf8fb32SBenno Lossin //! - when the closure returns `Ok(())`, then it has completed the initialization successfully, so
159fbf8fb32SBenno Lossin //! `slot` now contains a valid bit pattern for the type `T`,
160fbf8fb32SBenno Lossin //! - when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so
161fbf8fb32SBenno Lossin //! you need to take care to clean up anything if your initialization fails mid-way,
162fbf8fb32SBenno Lossin //! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of
163fbf8fb32SBenno Lossin //! `slot` gets called.
164fbf8fb32SBenno Lossin //!
1651ab10101SBenno Lossin //! ```rust
16684837cf6SBenno Lossin //! # #![feature(extern_types)]
16702c01c08SBenno Lossin //! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
16884837cf6SBenno Lossin //! use core::{
16984837cf6SBenno Lossin //! ptr::addr_of_mut,
17084837cf6SBenno Lossin //! marker::PhantomPinned,
17184837cf6SBenno Lossin //! cell::UnsafeCell,
17284837cf6SBenno Lossin //! pin::Pin,
17384837cf6SBenno Lossin //! mem::MaybeUninit,
17484837cf6SBenno Lossin //! };
17584837cf6SBenno Lossin //! mod bindings {
17602c01c08SBenno Lossin //! #[repr(C)]
17702c01c08SBenno Lossin //! pub struct foo {
17802c01c08SBenno Lossin //! /* fields from C ... */
17902c01c08SBenno Lossin //! }
18084837cf6SBenno Lossin //! extern "C" {
18184837cf6SBenno Lossin //! pub fn init_foo(ptr: *mut foo);
18284837cf6SBenno Lossin //! pub fn destroy_foo(ptr: *mut foo);
18384837cf6SBenno Lossin //! #[must_use = "you must check the error return code"]
18484837cf6SBenno Lossin //! pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32;
18584837cf6SBenno Lossin //! }
18684837cf6SBenno Lossin //! }
18784837cf6SBenno Lossin //!
188fbf8fb32SBenno Lossin //! /// # Invariants
189fbf8fb32SBenno Lossin //! ///
190fbf8fb32SBenno Lossin //! /// `foo` is always initialized
191fbf8fb32SBenno Lossin //! #[pin_data(PinnedDrop)]
192fbf8fb32SBenno Lossin //! pub struct RawFoo {
193fbf8fb32SBenno Lossin //! #[pin]
194fbf8fb32SBenno Lossin //! _p: PhantomPinned,
19584837cf6SBenno Lossin //! #[pin]
19684837cf6SBenno Lossin //! foo: UnsafeCell<MaybeUninit<bindings::foo>>,
197fbf8fb32SBenno Lossin //! }
198fbf8fb32SBenno Lossin //!
199fbf8fb32SBenno Lossin //! impl RawFoo {
20084837cf6SBenno Lossin //! pub fn new(flags: u32) -> impl PinInit<Self, i32> {
201fbf8fb32SBenno Lossin //! // SAFETY:
202fbf8fb32SBenno Lossin //! // - when the closure returns `Ok(())`, then it has successfully initialized and
203fbf8fb32SBenno Lossin //! // enabled `foo`,
204fbf8fb32SBenno Lossin //! // - when it returns `Err(e)`, then it has cleaned up before
205fbf8fb32SBenno Lossin //! unsafe {
20684837cf6SBenno Lossin //! pin_init_from_closure(move |slot: *mut Self| {
207fbf8fb32SBenno Lossin //! // `slot` contains uninit memory, avoid creating a reference.
208fbf8fb32SBenno Lossin //! let foo = addr_of_mut!((*slot).foo);
20984837cf6SBenno Lossin //! let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
210fbf8fb32SBenno Lossin //!
211fbf8fb32SBenno Lossin //! // Initialize the `foo`
21284837cf6SBenno Lossin //! bindings::init_foo(foo);
213fbf8fb32SBenno Lossin //!
214fbf8fb32SBenno Lossin //! // Try to enable it.
21584837cf6SBenno Lossin //! let err = bindings::enable_foo(foo, flags);
216fbf8fb32SBenno Lossin //! if err != 0 {
217fbf8fb32SBenno Lossin //! // Enabling has failed, first clean up the foo and then return the error.
21884837cf6SBenno Lossin //! bindings::destroy_foo(foo);
21984837cf6SBenno Lossin //! Err(err)
22084837cf6SBenno Lossin //! } else {
221fbf8fb32SBenno Lossin //! // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
222fbf8fb32SBenno Lossin //! Ok(())
22384837cf6SBenno Lossin //! }
224fbf8fb32SBenno Lossin //! })
225fbf8fb32SBenno Lossin //! }
226fbf8fb32SBenno Lossin //! }
227fbf8fb32SBenno Lossin //! }
228fbf8fb32SBenno Lossin //!
229fbf8fb32SBenno Lossin //! #[pinned_drop]
230fbf8fb32SBenno Lossin //! impl PinnedDrop for RawFoo {
231fbf8fb32SBenno Lossin //! fn drop(self: Pin<&mut Self>) {
232fbf8fb32SBenno Lossin //! // SAFETY: Since `foo` is initialized, destroying is safe.
23384837cf6SBenno Lossin //! unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) };
234fbf8fb32SBenno Lossin //! }
235fbf8fb32SBenno Lossin //! }
236fbf8fb32SBenno Lossin //! ```
237fbf8fb32SBenno Lossin //!
23802c01c08SBenno Lossin //! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
23902c01c08SBenno Lossin //! the `kernel` crate. The [`sync`] module is a good starting point.
24002c01c08SBenno Lossin //!
24102c01c08SBenno Lossin //! [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
242fbf8fb32SBenno Lossin //! [pinning]: https://doc.rust-lang.org/std/pin/index.html
243fbf8fb32SBenno Lossin //! [structurally pinned fields]:
244fbf8fb32SBenno Lossin //! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
245fbf8fb32SBenno Lossin //! [stack]: crate::stack_pin_init
2469b2299afSBenno Lossin #![cfg_attr(
2479b2299afSBenno Lossin kernel,
2489b2299afSBenno Lossin doc = "[`Arc<T>`]: https://rust.docs.kernel.org/kernel/sync/struct.Arc.html"
2499b2299afSBenno Lossin )]
2509b2299afSBenno Lossin #![cfg_attr(
2519b2299afSBenno Lossin kernel,
2529b2299afSBenno Lossin doc = "[`Box<T>`]: https://rust.docs.kernel.org/kernel/alloc/kbox/struct.Box.html"
2539b2299afSBenno Lossin )]
2549b2299afSBenno Lossin #![cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
2559b2299afSBenno Lossin #![cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
25602c01c08SBenno Lossin //! [`impl PinInit<Foo>`]: crate::PinInit
25702c01c08SBenno Lossin //! [`impl PinInit<T, E>`]: crate::PinInit
25802c01c08SBenno Lossin //! [`impl Init<T, E>`]: crate::Init
25902c01c08SBenno Lossin //! [Rust-for-Linux]: https://rust-for-linux.com/
260fbf8fb32SBenno Lossin
261dbd5058bSBenno Lossin #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
262dbd5058bSBenno Lossin #![cfg_attr(
263dbd5058bSBenno Lossin all(
264dbd5058bSBenno Lossin any(feature = "alloc", feature = "std"),
265dbd5058bSBenno Lossin not(RUSTC_NEW_UNINIT_IS_STABLE)
266dbd5058bSBenno Lossin ),
267dbd5058bSBenno Lossin feature(new_uninit)
268dbd5058bSBenno Lossin )]
269dbd5058bSBenno Lossin #![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
270dbd5058bSBenno Lossin #![cfg_attr(not(feature = "std"), no_std)]
271dbd5058bSBenno Lossin #![cfg_attr(feature = "alloc", feature(allocator_api))]
272dbd5058bSBenno Lossin
273fbf8fb32SBenno Lossin use core::{
274fbf8fb32SBenno Lossin cell::UnsafeCell,
275fbf8fb32SBenno Lossin convert::Infallible,
276fbf8fb32SBenno Lossin marker::PhantomData,
277fbf8fb32SBenno Lossin mem::MaybeUninit,
278fbf8fb32SBenno Lossin num::*,
279fbf8fb32SBenno Lossin pin::Pin,
280fbf8fb32SBenno Lossin ptr::{self, NonNull},
281fbf8fb32SBenno Lossin };
282fbf8fb32SBenno Lossin
283fbf8fb32SBenno Lossin #[doc(hidden)]
284fbf8fb32SBenno Lossin pub mod __internal;
285fbf8fb32SBenno Lossin #[doc(hidden)]
286fbf8fb32SBenno Lossin pub mod macros;
287fbf8fb32SBenno Lossin
2889b2299afSBenno Lossin #[cfg(any(feature = "std", feature = "alloc"))]
2899b2299afSBenno Lossin mod alloc;
2909b2299afSBenno Lossin #[cfg(any(feature = "std", feature = "alloc"))]
2919b2299afSBenno Lossin pub use alloc::InPlaceInit;
2929b2299afSBenno Lossin
2934b11798eSBenno Lossin /// Used to specify the pinning information of the fields of a struct.
2944b11798eSBenno Lossin ///
2954b11798eSBenno Lossin /// This is somewhat similar in purpose as
2964b11798eSBenno Lossin /// [pin-project-lite](https://crates.io/crates/pin-project-lite).
2974b11798eSBenno Lossin /// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
2984b11798eSBenno Lossin /// field you want to structurally pin.
2994b11798eSBenno Lossin ///
3004b11798eSBenno Lossin /// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
3014b11798eSBenno Lossin /// then `#[pin]` directs the type of initializer that is required.
3024b11798eSBenno Lossin ///
3034b11798eSBenno Lossin /// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
3044b11798eSBenno Lossin /// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
3054b11798eSBenno Lossin /// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
3064b11798eSBenno Lossin ///
3074b11798eSBenno Lossin /// # Examples
3084b11798eSBenno Lossin ///
3091ab10101SBenno Lossin /// ```
31084837cf6SBenno Lossin /// # #![feature(allocator_api)]
31184837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
31284837cf6SBenno Lossin /// use pin_init::pin_data;
31384837cf6SBenno Lossin ///
31484837cf6SBenno Lossin /// enum Command {
31584837cf6SBenno Lossin /// /* ... */
31684837cf6SBenno Lossin /// }
31784837cf6SBenno Lossin ///
3184b11798eSBenno Lossin /// #[pin_data]
3194b11798eSBenno Lossin /// struct DriverData {
3204b11798eSBenno Lossin /// #[pin]
32184837cf6SBenno Lossin /// queue: CMutex<Vec<Command>>,
32284837cf6SBenno Lossin /// buf: Box<[u8; 1024 * 1024]>,
3234b11798eSBenno Lossin /// }
3244b11798eSBenno Lossin /// ```
3254b11798eSBenno Lossin ///
3261ab10101SBenno Lossin /// ```
32784837cf6SBenno Lossin /// # #![feature(allocator_api)]
32884837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
32984837cf6SBenno Lossin /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
33084837cf6SBenno Lossin /// use core::pin::Pin;
33184837cf6SBenno Lossin /// use pin_init::{pin_data, pinned_drop, PinnedDrop};
33284837cf6SBenno Lossin ///
33384837cf6SBenno Lossin /// enum Command {
33484837cf6SBenno Lossin /// /* ... */
33584837cf6SBenno Lossin /// }
3364b11798eSBenno Lossin ///
3374b11798eSBenno Lossin /// #[pin_data(PinnedDrop)]
3384b11798eSBenno Lossin /// struct DriverData {
3394b11798eSBenno Lossin /// #[pin]
34084837cf6SBenno Lossin /// queue: CMutex<Vec<Command>>,
34184837cf6SBenno Lossin /// buf: Box<[u8; 1024 * 1024]>,
34284837cf6SBenno Lossin /// raw_info: *mut bindings::info,
3434b11798eSBenno Lossin /// }
3444b11798eSBenno Lossin ///
3454b11798eSBenno Lossin /// #[pinned_drop]
3464b11798eSBenno Lossin /// impl PinnedDrop for DriverData {
3474b11798eSBenno Lossin /// fn drop(self: Pin<&mut Self>) {
3484b11798eSBenno Lossin /// unsafe { bindings::destroy_info(self.raw_info) };
3494b11798eSBenno Lossin /// }
3504b11798eSBenno Lossin /// }
3514b11798eSBenno Lossin /// ```
352dbd5058bSBenno Lossin pub use ::pin_init_internal::pin_data;
3534b11798eSBenno Lossin
3544b11798eSBenno Lossin /// Used to implement `PinnedDrop` safely.
3554b11798eSBenno Lossin ///
3564b11798eSBenno Lossin /// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
3574b11798eSBenno Lossin ///
3584b11798eSBenno Lossin /// # Examples
3594b11798eSBenno Lossin ///
3601ab10101SBenno Lossin /// ```
36184837cf6SBenno Lossin /// # #![feature(allocator_api)]
36284837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
36384837cf6SBenno Lossin /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
36484837cf6SBenno Lossin /// use core::pin::Pin;
36584837cf6SBenno Lossin /// use pin_init::{pin_data, pinned_drop, PinnedDrop};
36684837cf6SBenno Lossin ///
36784837cf6SBenno Lossin /// enum Command {
36884837cf6SBenno Lossin /// /* ... */
36984837cf6SBenno Lossin /// }
37084837cf6SBenno Lossin ///
3714b11798eSBenno Lossin /// #[pin_data(PinnedDrop)]
3724b11798eSBenno Lossin /// struct DriverData {
3734b11798eSBenno Lossin /// #[pin]
37484837cf6SBenno Lossin /// queue: CMutex<Vec<Command>>,
37584837cf6SBenno Lossin /// buf: Box<[u8; 1024 * 1024]>,
37684837cf6SBenno Lossin /// raw_info: *mut bindings::info,
3774b11798eSBenno Lossin /// }
3784b11798eSBenno Lossin ///
3794b11798eSBenno Lossin /// #[pinned_drop]
3804b11798eSBenno Lossin /// impl PinnedDrop for DriverData {
3814b11798eSBenno Lossin /// fn drop(self: Pin<&mut Self>) {
3824b11798eSBenno Lossin /// unsafe { bindings::destroy_info(self.raw_info) };
3834b11798eSBenno Lossin /// }
3844b11798eSBenno Lossin /// }
3854b11798eSBenno Lossin /// ```
386dbd5058bSBenno Lossin pub use ::pin_init_internal::pinned_drop;
3874b11798eSBenno Lossin
3884b11798eSBenno Lossin /// Derives the [`Zeroable`] trait for the given struct.
3894b11798eSBenno Lossin ///
3904b11798eSBenno Lossin /// This can only be used for structs where every field implements the [`Zeroable`] trait.
3914b11798eSBenno Lossin ///
3924b11798eSBenno Lossin /// # Examples
3934b11798eSBenno Lossin ///
3941ab10101SBenno Lossin /// ```
39584837cf6SBenno Lossin /// use pin_init::Zeroable;
3964b11798eSBenno Lossin ///
3974b11798eSBenno Lossin /// #[derive(Zeroable)]
3984b11798eSBenno Lossin /// pub struct DriverData {
3994b11798eSBenno Lossin /// id: i64,
4004b11798eSBenno Lossin /// buf_ptr: *mut u8,
4014b11798eSBenno Lossin /// len: usize,
4024b11798eSBenno Lossin /// }
4034b11798eSBenno Lossin /// ```
404dbd5058bSBenno Lossin pub use ::pin_init_internal::Zeroable;
4054b11798eSBenno Lossin
406fbf8fb32SBenno Lossin /// Initialize and pin a type directly on the stack.
407fbf8fb32SBenno Lossin ///
408fbf8fb32SBenno Lossin /// # Examples
409fbf8fb32SBenno Lossin ///
4101ab10101SBenno Lossin /// ```rust
411fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
41284837cf6SBenno Lossin /// # #![feature(allocator_api)]
41384837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
41484837cf6SBenno Lossin /// # use pin_init::*;
415fbf8fb32SBenno Lossin /// # use core::pin::Pin;
416fbf8fb32SBenno Lossin /// #[pin_data]
417fbf8fb32SBenno Lossin /// struct Foo {
418fbf8fb32SBenno Lossin /// #[pin]
41984837cf6SBenno Lossin /// a: CMutex<usize>,
420fbf8fb32SBenno Lossin /// b: Bar,
421fbf8fb32SBenno Lossin /// }
422fbf8fb32SBenno Lossin ///
423fbf8fb32SBenno Lossin /// #[pin_data]
424fbf8fb32SBenno Lossin /// struct Bar {
425fbf8fb32SBenno Lossin /// x: u32,
426fbf8fb32SBenno Lossin /// }
427fbf8fb32SBenno Lossin ///
428fbf8fb32SBenno Lossin /// stack_pin_init!(let foo = pin_init!(Foo {
42984837cf6SBenno Lossin /// a <- CMutex::new(42),
430fbf8fb32SBenno Lossin /// b: Bar {
431fbf8fb32SBenno Lossin /// x: 64,
432fbf8fb32SBenno Lossin /// },
433fbf8fb32SBenno Lossin /// }));
434fbf8fb32SBenno Lossin /// let foo: Pin<&mut Foo> = foo;
43584837cf6SBenno Lossin /// println!("a: {}", &*foo.a.lock());
436fbf8fb32SBenno Lossin /// ```
437fbf8fb32SBenno Lossin ///
438fbf8fb32SBenno Lossin /// # Syntax
439fbf8fb32SBenno Lossin ///
440fbf8fb32SBenno Lossin /// A normal `let` binding with optional type annotation. The expression is expected to implement
441fbf8fb32SBenno Lossin /// [`PinInit`]/[`Init`] with the error type [`Infallible`]. If you want to use a different error
442fbf8fb32SBenno Lossin /// type, then use [`stack_try_pin_init!`].
443fbf8fb32SBenno Lossin #[macro_export]
444fbf8fb32SBenno Lossin macro_rules! stack_pin_init {
445fbf8fb32SBenno Lossin (let $var:ident $(: $t:ty)? = $val:expr) => {
446fbf8fb32SBenno Lossin let val = $val;
447dbd5058bSBenno Lossin let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
448dbd5058bSBenno Lossin let mut $var = match $crate::__internal::StackInit::init($var, val) {
449fbf8fb32SBenno Lossin Ok(res) => res,
450fbf8fb32SBenno Lossin Err(x) => {
451fbf8fb32SBenno Lossin let x: ::core::convert::Infallible = x;
452fbf8fb32SBenno Lossin match x {}
453fbf8fb32SBenno Lossin }
454fbf8fb32SBenno Lossin };
455fbf8fb32SBenno Lossin };
456fbf8fb32SBenno Lossin }
457fbf8fb32SBenno Lossin
458fbf8fb32SBenno Lossin /// Initialize and pin a type directly on the stack.
459fbf8fb32SBenno Lossin ///
460fbf8fb32SBenno Lossin /// # Examples
461fbf8fb32SBenno Lossin ///
4621ab10101SBenno Lossin /// ```rust
463fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
46484837cf6SBenno Lossin /// # #![feature(allocator_api)]
46584837cf6SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
46684837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
46784837cf6SBenno Lossin /// # use pin_init::*;
468fbf8fb32SBenno Lossin /// #[pin_data]
469fbf8fb32SBenno Lossin /// struct Foo {
470fbf8fb32SBenno Lossin /// #[pin]
47184837cf6SBenno Lossin /// a: CMutex<usize>,
47284837cf6SBenno Lossin /// b: Box<Bar>,
473fbf8fb32SBenno Lossin /// }
474fbf8fb32SBenno Lossin ///
475fbf8fb32SBenno Lossin /// struct Bar {
476fbf8fb32SBenno Lossin /// x: u32,
477fbf8fb32SBenno Lossin /// }
478fbf8fb32SBenno Lossin ///
47984837cf6SBenno Lossin /// stack_try_pin_init!(let foo: Foo = try_pin_init!(Foo {
48084837cf6SBenno Lossin /// a <- CMutex::new(42),
48184837cf6SBenno Lossin /// b: Box::try_new(Bar {
482fbf8fb32SBenno Lossin /// x: 64,
48384837cf6SBenno Lossin /// })?,
48484837cf6SBenno Lossin /// }? Error));
485fbf8fb32SBenno Lossin /// let foo = foo.unwrap();
48684837cf6SBenno Lossin /// println!("a: {}", &*foo.a.lock());
487fbf8fb32SBenno Lossin /// ```
488fbf8fb32SBenno Lossin ///
4891ab10101SBenno Lossin /// ```rust
490fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
49184837cf6SBenno Lossin /// # #![feature(allocator_api)]
49284837cf6SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
49384837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
49484837cf6SBenno Lossin /// # use pin_init::*;
495fbf8fb32SBenno Lossin /// #[pin_data]
496fbf8fb32SBenno Lossin /// struct Foo {
497fbf8fb32SBenno Lossin /// #[pin]
49884837cf6SBenno Lossin /// a: CMutex<usize>,
49984837cf6SBenno Lossin /// b: Box<Bar>,
500fbf8fb32SBenno Lossin /// }
501fbf8fb32SBenno Lossin ///
502fbf8fb32SBenno Lossin /// struct Bar {
503fbf8fb32SBenno Lossin /// x: u32,
504fbf8fb32SBenno Lossin /// }
505fbf8fb32SBenno Lossin ///
50684837cf6SBenno Lossin /// stack_try_pin_init!(let foo: Foo =? try_pin_init!(Foo {
50784837cf6SBenno Lossin /// a <- CMutex::new(42),
50884837cf6SBenno Lossin /// b: Box::try_new(Bar {
509fbf8fb32SBenno Lossin /// x: 64,
51084837cf6SBenno Lossin /// })?,
51184837cf6SBenno Lossin /// }? Error));
51284837cf6SBenno Lossin /// println!("a: {}", &*foo.a.lock());
51384837cf6SBenno Lossin /// # Ok::<_, Error>(())
514fbf8fb32SBenno Lossin /// ```
515fbf8fb32SBenno Lossin ///
516fbf8fb32SBenno Lossin /// # Syntax
517fbf8fb32SBenno Lossin ///
518fbf8fb32SBenno Lossin /// A normal `let` binding with optional type annotation. The expression is expected to implement
519fbf8fb32SBenno Lossin /// [`PinInit`]/[`Init`]. This macro assigns a result to the given variable, adding a `?` after the
520fbf8fb32SBenno Lossin /// `=` will propagate this error.
521fbf8fb32SBenno Lossin #[macro_export]
522fbf8fb32SBenno Lossin macro_rules! stack_try_pin_init {
523fbf8fb32SBenno Lossin (let $var:ident $(: $t:ty)? = $val:expr) => {
524fbf8fb32SBenno Lossin let val = $val;
525dbd5058bSBenno Lossin let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
526dbd5058bSBenno Lossin let mut $var = $crate::__internal::StackInit::init($var, val);
527fbf8fb32SBenno Lossin };
528fbf8fb32SBenno Lossin (let $var:ident $(: $t:ty)? =? $val:expr) => {
529fbf8fb32SBenno Lossin let val = $val;
530dbd5058bSBenno Lossin let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
531dbd5058bSBenno Lossin let mut $var = $crate::__internal::StackInit::init($var, val)?;
532fbf8fb32SBenno Lossin };
533fbf8fb32SBenno Lossin }
534fbf8fb32SBenno Lossin
535fbf8fb32SBenno Lossin /// Construct an in-place, pinned initializer for `struct`s.
536fbf8fb32SBenno Lossin ///
537578eb8b6SBenno Lossin /// This macro defaults the error to [`Infallible`]. If you need a different error, then use
538fbf8fb32SBenno Lossin /// [`try_pin_init!`].
539fbf8fb32SBenno Lossin ///
540fbf8fb32SBenno Lossin /// The syntax is almost identical to that of a normal `struct` initializer:
541fbf8fb32SBenno Lossin ///
5421ab10101SBenno Lossin /// ```rust
54384837cf6SBenno Lossin /// # use pin_init::*;
544fbf8fb32SBenno Lossin /// # use core::pin::Pin;
545fbf8fb32SBenno Lossin /// #[pin_data]
546fbf8fb32SBenno Lossin /// struct Foo {
547fbf8fb32SBenno Lossin /// a: usize,
548fbf8fb32SBenno Lossin /// b: Bar,
549fbf8fb32SBenno Lossin /// }
550fbf8fb32SBenno Lossin ///
551fbf8fb32SBenno Lossin /// #[pin_data]
552fbf8fb32SBenno Lossin /// struct Bar {
553fbf8fb32SBenno Lossin /// x: u32,
554fbf8fb32SBenno Lossin /// }
555fbf8fb32SBenno Lossin ///
556fbf8fb32SBenno Lossin /// # fn demo() -> impl PinInit<Foo> {
557fbf8fb32SBenno Lossin /// let a = 42;
558fbf8fb32SBenno Lossin ///
559fbf8fb32SBenno Lossin /// let initializer = pin_init!(Foo {
560fbf8fb32SBenno Lossin /// a,
561fbf8fb32SBenno Lossin /// b: Bar {
562fbf8fb32SBenno Lossin /// x: 64,
563fbf8fb32SBenno Lossin /// },
564fbf8fb32SBenno Lossin /// });
565fbf8fb32SBenno Lossin /// # initializer }
56684837cf6SBenno Lossin /// # Box::pin_init(demo()).unwrap();
567fbf8fb32SBenno Lossin /// ```
568fbf8fb32SBenno Lossin ///
569fbf8fb32SBenno Lossin /// Arbitrary Rust expressions can be used to set the value of a variable.
570fbf8fb32SBenno Lossin ///
571fbf8fb32SBenno Lossin /// The fields are initialized in the order that they appear in the initializer. So it is possible
572fbf8fb32SBenno Lossin /// to read already initialized fields using raw pointers.
573fbf8fb32SBenno Lossin ///
574fbf8fb32SBenno Lossin /// IMPORTANT: You are not allowed to create references to fields of the struct inside of the
575fbf8fb32SBenno Lossin /// initializer.
576fbf8fb32SBenno Lossin ///
577fbf8fb32SBenno Lossin /// # Init-functions
578fbf8fb32SBenno Lossin ///
57902c01c08SBenno Lossin /// When working with this library it is often desired to let others construct your types without
58002c01c08SBenno Lossin /// giving access to all fields. This is where you would normally write a plain function `new` that
58102c01c08SBenno Lossin /// would return a new instance of your type. With this library that is also possible. However,
58202c01c08SBenno Lossin /// there are a few extra things to keep in mind.
583fbf8fb32SBenno Lossin ///
584fbf8fb32SBenno Lossin /// To create an initializer function, simply declare it like this:
585fbf8fb32SBenno Lossin ///
5861ab10101SBenno Lossin /// ```rust
58784837cf6SBenno Lossin /// # use pin_init::*;
588fbf8fb32SBenno Lossin /// # use core::pin::Pin;
589fbf8fb32SBenno Lossin /// # #[pin_data]
590fbf8fb32SBenno Lossin /// # struct Foo {
591fbf8fb32SBenno Lossin /// # a: usize,
592fbf8fb32SBenno Lossin /// # b: Bar,
593fbf8fb32SBenno Lossin /// # }
594fbf8fb32SBenno Lossin /// # #[pin_data]
595fbf8fb32SBenno Lossin /// # struct Bar {
596fbf8fb32SBenno Lossin /// # x: u32,
597fbf8fb32SBenno Lossin /// # }
598fbf8fb32SBenno Lossin /// impl Foo {
599fbf8fb32SBenno Lossin /// fn new() -> impl PinInit<Self> {
600fbf8fb32SBenno Lossin /// pin_init!(Self {
601fbf8fb32SBenno Lossin /// a: 42,
602fbf8fb32SBenno Lossin /// b: Bar {
603fbf8fb32SBenno Lossin /// x: 64,
604fbf8fb32SBenno Lossin /// },
605fbf8fb32SBenno Lossin /// })
606fbf8fb32SBenno Lossin /// }
607fbf8fb32SBenno Lossin /// }
608fbf8fb32SBenno Lossin /// ```
609fbf8fb32SBenno Lossin ///
610fbf8fb32SBenno Lossin /// Users of `Foo` can now create it like this:
611fbf8fb32SBenno Lossin ///
6121ab10101SBenno Lossin /// ```rust
613fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
61484837cf6SBenno Lossin /// # use pin_init::*;
615fbf8fb32SBenno Lossin /// # use core::pin::Pin;
616fbf8fb32SBenno Lossin /// # #[pin_data]
617fbf8fb32SBenno Lossin /// # struct Foo {
618fbf8fb32SBenno Lossin /// # a: usize,
619fbf8fb32SBenno Lossin /// # b: Bar,
620fbf8fb32SBenno Lossin /// # }
621fbf8fb32SBenno Lossin /// # #[pin_data]
622fbf8fb32SBenno Lossin /// # struct Bar {
623fbf8fb32SBenno Lossin /// # x: u32,
624fbf8fb32SBenno Lossin /// # }
625fbf8fb32SBenno Lossin /// # impl Foo {
626fbf8fb32SBenno Lossin /// # fn new() -> impl PinInit<Self> {
627fbf8fb32SBenno Lossin /// # pin_init!(Self {
628fbf8fb32SBenno Lossin /// # a: 42,
629fbf8fb32SBenno Lossin /// # b: Bar {
630fbf8fb32SBenno Lossin /// # x: 64,
631fbf8fb32SBenno Lossin /// # },
632fbf8fb32SBenno Lossin /// # })
633fbf8fb32SBenno Lossin /// # }
634fbf8fb32SBenno Lossin /// # }
63584837cf6SBenno Lossin /// let foo = Box::pin_init(Foo::new());
636fbf8fb32SBenno Lossin /// ```
637fbf8fb32SBenno Lossin ///
638fbf8fb32SBenno Lossin /// They can also easily embed it into their own `struct`s:
639fbf8fb32SBenno Lossin ///
6401ab10101SBenno Lossin /// ```rust
64184837cf6SBenno Lossin /// # use pin_init::*;
642fbf8fb32SBenno Lossin /// # use core::pin::Pin;
643fbf8fb32SBenno Lossin /// # #[pin_data]
644fbf8fb32SBenno Lossin /// # struct Foo {
645fbf8fb32SBenno Lossin /// # a: usize,
646fbf8fb32SBenno Lossin /// # b: Bar,
647fbf8fb32SBenno Lossin /// # }
648fbf8fb32SBenno Lossin /// # #[pin_data]
649fbf8fb32SBenno Lossin /// # struct Bar {
650fbf8fb32SBenno Lossin /// # x: u32,
651fbf8fb32SBenno Lossin /// # }
652fbf8fb32SBenno Lossin /// # impl Foo {
653fbf8fb32SBenno Lossin /// # fn new() -> impl PinInit<Self> {
654fbf8fb32SBenno Lossin /// # pin_init!(Self {
655fbf8fb32SBenno Lossin /// # a: 42,
656fbf8fb32SBenno Lossin /// # b: Bar {
657fbf8fb32SBenno Lossin /// # x: 64,
658fbf8fb32SBenno Lossin /// # },
659fbf8fb32SBenno Lossin /// # })
660fbf8fb32SBenno Lossin /// # }
661fbf8fb32SBenno Lossin /// # }
662fbf8fb32SBenno Lossin /// #[pin_data]
663fbf8fb32SBenno Lossin /// struct FooContainer {
664fbf8fb32SBenno Lossin /// #[pin]
665fbf8fb32SBenno Lossin /// foo1: Foo,
666fbf8fb32SBenno Lossin /// #[pin]
667fbf8fb32SBenno Lossin /// foo2: Foo,
668fbf8fb32SBenno Lossin /// other: u32,
669fbf8fb32SBenno Lossin /// }
670fbf8fb32SBenno Lossin ///
671fbf8fb32SBenno Lossin /// impl FooContainer {
672fbf8fb32SBenno Lossin /// fn new(other: u32) -> impl PinInit<Self> {
673fbf8fb32SBenno Lossin /// pin_init!(Self {
674fbf8fb32SBenno Lossin /// foo1 <- Foo::new(),
675fbf8fb32SBenno Lossin /// foo2 <- Foo::new(),
676fbf8fb32SBenno Lossin /// other,
677fbf8fb32SBenno Lossin /// })
678fbf8fb32SBenno Lossin /// }
679fbf8fb32SBenno Lossin /// }
680fbf8fb32SBenno Lossin /// ```
681fbf8fb32SBenno Lossin ///
682fbf8fb32SBenno Lossin /// Here we see that when using `pin_init!` with `PinInit`, one needs to write `<-` instead of `:`.
683fbf8fb32SBenno Lossin /// This signifies that the given field is initialized in-place. As with `struct` initializers, just
684fbf8fb32SBenno Lossin /// writing the field (in this case `other`) without `:` or `<-` means `other: other,`.
685fbf8fb32SBenno Lossin ///
686fbf8fb32SBenno Lossin /// # Syntax
687fbf8fb32SBenno Lossin ///
688fbf8fb32SBenno Lossin /// As already mentioned in the examples above, inside of `pin_init!` a `struct` initializer with
689fbf8fb32SBenno Lossin /// the following modifications is expected:
690fbf8fb32SBenno Lossin /// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
691fbf8fb32SBenno Lossin /// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
692fbf8fb32SBenno Lossin /// pointer named `this` inside of the initializer.
693fbf8fb32SBenno Lossin /// - Using struct update syntax one can place `..Zeroable::zeroed()` at the very end of the
694fbf8fb32SBenno Lossin /// struct, this initializes every field with 0 and then runs all initializers specified in the
695fbf8fb32SBenno Lossin /// body. This can only be done if [`Zeroable`] is implemented for the struct.
696fbf8fb32SBenno Lossin ///
697fbf8fb32SBenno Lossin /// For instance:
698fbf8fb32SBenno Lossin ///
6991ab10101SBenno Lossin /// ```rust
70084837cf6SBenno Lossin /// # use pin_init::*;
701fbf8fb32SBenno Lossin /// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
702fbf8fb32SBenno Lossin /// #[pin_data]
703fbf8fb32SBenno Lossin /// #[derive(Zeroable)]
704fbf8fb32SBenno Lossin /// struct Buf {
705fbf8fb32SBenno Lossin /// // `ptr` points into `buf`.
706fbf8fb32SBenno Lossin /// ptr: *mut u8,
707fbf8fb32SBenno Lossin /// buf: [u8; 64],
708fbf8fb32SBenno Lossin /// #[pin]
709fbf8fb32SBenno Lossin /// pin: PhantomPinned,
710fbf8fb32SBenno Lossin /// }
71102c01c08SBenno Lossin ///
71202c01c08SBenno Lossin /// let init = pin_init!(&this in Buf {
713fbf8fb32SBenno Lossin /// buf: [0; 64],
714fbf8fb32SBenno Lossin /// // SAFETY: TODO.
715fbf8fb32SBenno Lossin /// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
716fbf8fb32SBenno Lossin /// pin: PhantomPinned,
717fbf8fb32SBenno Lossin /// });
71802c01c08SBenno Lossin /// let init = pin_init!(Buf {
719fbf8fb32SBenno Lossin /// buf: [1; 64],
720fbf8fb32SBenno Lossin /// ..Zeroable::zeroed()
721fbf8fb32SBenno Lossin /// });
722fbf8fb32SBenno Lossin /// ```
723fbf8fb32SBenno Lossin ///
724fbf8fb32SBenno Lossin /// [`NonNull<Self>`]: core::ptr::NonNull
725fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
72602c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
727fbf8fb32SBenno Lossin #[macro_export]
728fbf8fb32SBenno Lossin macro_rules! pin_init {
729fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
730fbf8fb32SBenno Lossin $($fields:tt)*
731fbf8fb32SBenno Lossin }) => {
732dbd5058bSBenno Lossin $crate::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
733c2ddbdbbSBenno Lossin $($fields)*
734c2ddbdbbSBenno Lossin }? ::core::convert::Infallible)
735fbf8fb32SBenno Lossin };
736fbf8fb32SBenno Lossin }
737fbf8fb32SBenno Lossin
738fbf8fb32SBenno Lossin /// Construct an in-place, fallible pinned initializer for `struct`s.
739fbf8fb32SBenno Lossin ///
740fbf8fb32SBenno Lossin /// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
741fbf8fb32SBenno Lossin ///
742fbf8fb32SBenno Lossin /// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
743fbf8fb32SBenno Lossin /// initialization and return the error.
744fbf8fb32SBenno Lossin ///
745fbf8fb32SBenno Lossin /// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
746fbf8fb32SBenno Lossin /// initialization fails, the memory can be safely deallocated without any further modifications.
747fbf8fb32SBenno Lossin ///
748578eb8b6SBenno Lossin /// The syntax is identical to [`pin_init!`] with the following exception: you must append `? $type`
749fbf8fb32SBenno Lossin /// after the `struct` initializer to specify the error type you want to use.
750fbf8fb32SBenno Lossin ///
751fbf8fb32SBenno Lossin /// # Examples
752fbf8fb32SBenno Lossin ///
7531ab10101SBenno Lossin /// ```rust
75484837cf6SBenno Lossin /// # #![feature(allocator_api)]
75584837cf6SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
75602c01c08SBenno Lossin /// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed};
75702c01c08SBenno Lossin ///
758fbf8fb32SBenno Lossin /// #[pin_data]
759fbf8fb32SBenno Lossin /// struct BigBuf {
76084837cf6SBenno Lossin /// big: Box<[u8; 1024 * 1024 * 1024]>,
761fbf8fb32SBenno Lossin /// small: [u8; 1024 * 1024],
762fbf8fb32SBenno Lossin /// ptr: *mut u8,
763fbf8fb32SBenno Lossin /// }
764fbf8fb32SBenno Lossin ///
765fbf8fb32SBenno Lossin /// impl BigBuf {
766fbf8fb32SBenno Lossin /// fn new() -> impl PinInit<Self, Error> {
767fbf8fb32SBenno Lossin /// try_pin_init!(Self {
76802c01c08SBenno Lossin /// big: Box::init(zeroed())?,
769fbf8fb32SBenno Lossin /// small: [0; 1024 * 1024],
770fbf8fb32SBenno Lossin /// ptr: core::ptr::null_mut(),
771fbf8fb32SBenno Lossin /// }? Error)
772fbf8fb32SBenno Lossin /// }
773fbf8fb32SBenno Lossin /// }
77484837cf6SBenno Lossin /// # let _ = Box::pin_init(BigBuf::new());
775fbf8fb32SBenno Lossin /// ```
776fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
77702c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
778fbf8fb32SBenno Lossin #[macro_export]
779dbd5058bSBenno Lossin macro_rules! try_pin_init {
780fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
781fbf8fb32SBenno Lossin $($fields:tt)*
782fbf8fb32SBenno Lossin }? $err:ty) => {
783fbf8fb32SBenno Lossin $crate::__init_internal!(
784fbf8fb32SBenno Lossin @this($($this)?),
785fbf8fb32SBenno Lossin @typ($t $(::<$($generics),*>)? ),
786fbf8fb32SBenno Lossin @fields($($fields)*),
787fbf8fb32SBenno Lossin @error($err),
788fbf8fb32SBenno Lossin @data(PinData, use_data),
789fbf8fb32SBenno Lossin @has_data(HasPinData, __pin_data),
790fbf8fb32SBenno Lossin @construct_closure(pin_init_from_closure),
791fbf8fb32SBenno Lossin @munch_fields($($fields)*),
792fbf8fb32SBenno Lossin )
793578eb8b6SBenno Lossin }
794fbf8fb32SBenno Lossin }
795fbf8fb32SBenno Lossin
796fbf8fb32SBenno Lossin /// Construct an in-place initializer for `struct`s.
797fbf8fb32SBenno Lossin ///
798578eb8b6SBenno Lossin /// This macro defaults the error to [`Infallible`]. If you need a different error, then use
799fbf8fb32SBenno Lossin /// [`try_init!`].
800fbf8fb32SBenno Lossin ///
801fbf8fb32SBenno Lossin /// The syntax is identical to [`pin_init!`] and its safety caveats also apply:
802fbf8fb32SBenno Lossin /// - `unsafe` code must guarantee either full initialization or return an error and allow
803fbf8fb32SBenno Lossin /// deallocation of the memory.
804fbf8fb32SBenno Lossin /// - the fields are initialized in the order given in the initializer.
805fbf8fb32SBenno Lossin /// - no references to fields are allowed to be created inside of the initializer.
806fbf8fb32SBenno Lossin ///
807fbf8fb32SBenno Lossin /// This initializer is for initializing data in-place that might later be moved. If you want to
808fbf8fb32SBenno Lossin /// pin-initialize, use [`pin_init!`].
809fbf8fb32SBenno Lossin ///
81002c01c08SBenno Lossin /// # Examples
81102c01c08SBenno Lossin ///
81202c01c08SBenno Lossin /// ```rust
81302c01c08SBenno Lossin /// # #![feature(allocator_api)]
81402c01c08SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
81502c01c08SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
81602c01c08SBenno Lossin /// # use pin_init::InPlaceInit;
81702c01c08SBenno Lossin /// use pin_init::{init, Init, zeroed};
81802c01c08SBenno Lossin ///
81902c01c08SBenno Lossin /// struct BigBuf {
82002c01c08SBenno Lossin /// small: [u8; 1024 * 1024],
82102c01c08SBenno Lossin /// }
82202c01c08SBenno Lossin ///
82302c01c08SBenno Lossin /// impl BigBuf {
82402c01c08SBenno Lossin /// fn new() -> impl Init<Self> {
82502c01c08SBenno Lossin /// init!(Self {
82602c01c08SBenno Lossin /// small <- zeroed(),
82702c01c08SBenno Lossin /// })
82802c01c08SBenno Lossin /// }
82902c01c08SBenno Lossin /// }
83002c01c08SBenno Lossin /// # let _ = Box::init(BigBuf::new());
83102c01c08SBenno Lossin /// ```
832fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
83302c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
834fbf8fb32SBenno Lossin #[macro_export]
835fbf8fb32SBenno Lossin macro_rules! init {
836fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
837fbf8fb32SBenno Lossin $($fields:tt)*
838fbf8fb32SBenno Lossin }) => {
839dbd5058bSBenno Lossin $crate::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
840c2ddbdbbSBenno Lossin $($fields)*
841c2ddbdbbSBenno Lossin }? ::core::convert::Infallible)
842fbf8fb32SBenno Lossin }
843fbf8fb32SBenno Lossin }
844fbf8fb32SBenno Lossin
845fbf8fb32SBenno Lossin /// Construct an in-place fallible initializer for `struct`s.
846fbf8fb32SBenno Lossin ///
847578eb8b6SBenno Lossin /// If the initialization can complete without error (or [`Infallible`]), then use
848fbf8fb32SBenno Lossin /// [`init!`].
849fbf8fb32SBenno Lossin ///
850578eb8b6SBenno Lossin /// The syntax is identical to [`try_pin_init!`]. You need to specify a custom error
851578eb8b6SBenno Lossin /// via `? $type` after the `struct` initializer.
852fbf8fb32SBenno Lossin /// The safety caveats from [`try_pin_init!`] also apply:
853fbf8fb32SBenno Lossin /// - `unsafe` code must guarantee either full initialization or return an error and allow
854fbf8fb32SBenno Lossin /// deallocation of the memory.
855fbf8fb32SBenno Lossin /// - the fields are initialized in the order given in the initializer.
856fbf8fb32SBenno Lossin /// - no references to fields are allowed to be created inside of the initializer.
857fbf8fb32SBenno Lossin ///
858fbf8fb32SBenno Lossin /// # Examples
859fbf8fb32SBenno Lossin ///
8601ab10101SBenno Lossin /// ```rust
86184837cf6SBenno Lossin /// # #![feature(allocator_api)]
86284837cf6SBenno Lossin /// # use core::alloc::AllocError;
86302c01c08SBenno Lossin /// # use pin_init::InPlaceInit;
86402c01c08SBenno Lossin /// use pin_init::{try_init, Init, zeroed};
86502c01c08SBenno Lossin ///
866fbf8fb32SBenno Lossin /// struct BigBuf {
86784837cf6SBenno Lossin /// big: Box<[u8; 1024 * 1024 * 1024]>,
868fbf8fb32SBenno Lossin /// small: [u8; 1024 * 1024],
869fbf8fb32SBenno Lossin /// }
870fbf8fb32SBenno Lossin ///
871fbf8fb32SBenno Lossin /// impl BigBuf {
87284837cf6SBenno Lossin /// fn new() -> impl Init<Self, AllocError> {
873fbf8fb32SBenno Lossin /// try_init!(Self {
87484837cf6SBenno Lossin /// big: Box::init(zeroed())?,
875fbf8fb32SBenno Lossin /// small: [0; 1024 * 1024],
87684837cf6SBenno Lossin /// }? AllocError)
877fbf8fb32SBenno Lossin /// }
878fbf8fb32SBenno Lossin /// }
87902c01c08SBenno Lossin /// # let _ = Box::init(BigBuf::new());
880fbf8fb32SBenno Lossin /// ```
881fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
88202c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
883fbf8fb32SBenno Lossin #[macro_export]
884dbd5058bSBenno Lossin macro_rules! try_init {
885fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
886fbf8fb32SBenno Lossin $($fields:tt)*
887fbf8fb32SBenno Lossin }? $err:ty) => {
888fbf8fb32SBenno Lossin $crate::__init_internal!(
889fbf8fb32SBenno Lossin @this($($this)?),
890fbf8fb32SBenno Lossin @typ($t $(::<$($generics),*>)?),
891fbf8fb32SBenno Lossin @fields($($fields)*),
892fbf8fb32SBenno Lossin @error($err),
893fbf8fb32SBenno Lossin @data(InitData, /*no use_data*/),
894fbf8fb32SBenno Lossin @has_data(HasInitData, __init_data),
895fbf8fb32SBenno Lossin @construct_closure(init_from_closure),
896fbf8fb32SBenno Lossin @munch_fields($($fields)*),
897fbf8fb32SBenno Lossin )
898578eb8b6SBenno Lossin }
899fbf8fb32SBenno Lossin }
900fbf8fb32SBenno Lossin
901fbf8fb32SBenno Lossin /// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is
902fbf8fb32SBenno Lossin /// structurally pinned.
903fbf8fb32SBenno Lossin ///
904fbf8fb32SBenno Lossin /// # Example
905fbf8fb32SBenno Lossin ///
906fbf8fb32SBenno Lossin /// This will succeed:
9071ab10101SBenno Lossin /// ```
90802c01c08SBenno Lossin /// use pin_init::{pin_data, assert_pinned};
90902c01c08SBenno Lossin ///
910fbf8fb32SBenno Lossin /// #[pin_data]
911fbf8fb32SBenno Lossin /// struct MyStruct {
912fbf8fb32SBenno Lossin /// #[pin]
913fbf8fb32SBenno Lossin /// some_field: u64,
914fbf8fb32SBenno Lossin /// }
915fbf8fb32SBenno Lossin ///
916fbf8fb32SBenno Lossin /// assert_pinned!(MyStruct, some_field, u64);
917fbf8fb32SBenno Lossin /// ```
918fbf8fb32SBenno Lossin ///
919fbf8fb32SBenno Lossin /// This will fail:
9201ab10101SBenno Lossin /// ```compile_fail
92102c01c08SBenno Lossin /// use pin_init::{pin_data, assert_pinned};
92202c01c08SBenno Lossin ///
923fbf8fb32SBenno Lossin /// #[pin_data]
924fbf8fb32SBenno Lossin /// struct MyStruct {
925fbf8fb32SBenno Lossin /// some_field: u64,
926fbf8fb32SBenno Lossin /// }
927fbf8fb32SBenno Lossin ///
928fbf8fb32SBenno Lossin /// assert_pinned!(MyStruct, some_field, u64);
929fbf8fb32SBenno Lossin /// ```
930fbf8fb32SBenno Lossin ///
931fbf8fb32SBenno Lossin /// Some uses of the macro may trigger the `can't use generic parameters from outer item` error. To
932fbf8fb32SBenno Lossin /// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
933fbf8fb32SBenno Lossin /// only be used when the macro is invoked from a function body.
9341ab10101SBenno Lossin /// ```
93502c01c08SBenno Lossin /// # use core::pin::Pin;
93602c01c08SBenno Lossin /// use pin_init::{pin_data, assert_pinned};
93702c01c08SBenno Lossin ///
938fbf8fb32SBenno Lossin /// #[pin_data]
939fbf8fb32SBenno Lossin /// struct Foo<T> {
940fbf8fb32SBenno Lossin /// #[pin]
941fbf8fb32SBenno Lossin /// elem: T,
942fbf8fb32SBenno Lossin /// }
943fbf8fb32SBenno Lossin ///
944fbf8fb32SBenno Lossin /// impl<T> Foo<T> {
945fbf8fb32SBenno Lossin /// fn project(self: Pin<&mut Self>) -> Pin<&mut T> {
946fbf8fb32SBenno Lossin /// assert_pinned!(Foo<T>, elem, T, inline);
947fbf8fb32SBenno Lossin ///
948fbf8fb32SBenno Lossin /// // SAFETY: The field is structurally pinned.
949fbf8fb32SBenno Lossin /// unsafe { self.map_unchecked_mut(|me| &mut me.elem) }
950fbf8fb32SBenno Lossin /// }
951fbf8fb32SBenno Lossin /// }
952fbf8fb32SBenno Lossin /// ```
953fbf8fb32SBenno Lossin #[macro_export]
954fbf8fb32SBenno Lossin macro_rules! assert_pinned {
955fbf8fb32SBenno Lossin ($ty:ty, $field:ident, $field_ty:ty, inline) => {
956fbf8fb32SBenno Lossin let _ = move |ptr: *mut $field_ty| {
957fbf8fb32SBenno Lossin // SAFETY: This code is unreachable.
958dbd5058bSBenno Lossin let data = unsafe { <$ty as $crate::__internal::HasPinData>::__pin_data() };
959dbd5058bSBenno Lossin let init = $crate::__internal::AlwaysFail::<$field_ty>::new();
960fbf8fb32SBenno Lossin // SAFETY: This code is unreachable.
961fbf8fb32SBenno Lossin unsafe { data.$field(ptr, init) }.ok();
962fbf8fb32SBenno Lossin };
963fbf8fb32SBenno Lossin };
964fbf8fb32SBenno Lossin
965fbf8fb32SBenno Lossin ($ty:ty, $field:ident, $field_ty:ty) => {
966fbf8fb32SBenno Lossin const _: () = {
967fbf8fb32SBenno Lossin $crate::assert_pinned!($ty, $field, $field_ty, inline);
968fbf8fb32SBenno Lossin };
969fbf8fb32SBenno Lossin };
970fbf8fb32SBenno Lossin }
971fbf8fb32SBenno Lossin
972fbf8fb32SBenno Lossin /// A pin-initializer for the type `T`.
973fbf8fb32SBenno Lossin ///
974fbf8fb32SBenno Lossin /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
975129e97beSBenno Lossin /// be [`Box<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]).
976fbf8fb32SBenno Lossin ///
977fbf8fb32SBenno Lossin /// Also see the [module description](self).
978fbf8fb32SBenno Lossin ///
979fbf8fb32SBenno Lossin /// # Safety
980fbf8fb32SBenno Lossin ///
981fbf8fb32SBenno Lossin /// When implementing this trait you will need to take great care. Also there are probably very few
982fbf8fb32SBenno Lossin /// cases where a manual implementation is necessary. Use [`pin_init_from_closure`] where possible.
983fbf8fb32SBenno Lossin ///
984fbf8fb32SBenno Lossin /// The [`PinInit::__pinned_init`] function:
985fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
986fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
987fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
988fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
989fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
990fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
991fbf8fb32SBenno Lossin ///
9929b2299afSBenno Lossin #[cfg_attr(
9939b2299afSBenno Lossin kernel,
9949b2299afSBenno Lossin doc = "[`Arc<T>`]: https://rust.docs.kernel.org/kernel/sync/struct.Arc.html"
9959b2299afSBenno Lossin )]
9969b2299afSBenno Lossin #[cfg_attr(
9979b2299afSBenno Lossin kernel,
9989b2299afSBenno Lossin doc = "[`Box<T>`]: https://rust.docs.kernel.org/kernel/alloc/kbox/struct.Box.html"
9999b2299afSBenno Lossin )]
10009b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
10019b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
1002fbf8fb32SBenno Lossin #[must_use = "An initializer must be used in order to create its value."]
1003fbf8fb32SBenno Lossin pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
1004fbf8fb32SBenno Lossin /// Initializes `slot`.
1005fbf8fb32SBenno Lossin ///
1006fbf8fb32SBenno Lossin /// # Safety
1007fbf8fb32SBenno Lossin ///
1008fbf8fb32SBenno Lossin /// - `slot` is a valid pointer to uninitialized memory.
1009fbf8fb32SBenno Lossin /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
1010fbf8fb32SBenno Lossin /// deallocate.
1011fbf8fb32SBenno Lossin /// - `slot` will not move until it is dropped, i.e. it will be pinned.
__pinned_init(self, slot: *mut T) -> Result<(), E>1012fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>;
1013fbf8fb32SBenno Lossin
1014fbf8fb32SBenno Lossin /// First initializes the value using `self` then calls the function `f` with the initialized
1015fbf8fb32SBenno Lossin /// value.
1016fbf8fb32SBenno Lossin ///
1017fbf8fb32SBenno Lossin /// If `f` returns an error the value is dropped and the initializer will forward the error.
1018fbf8fb32SBenno Lossin ///
1019fbf8fb32SBenno Lossin /// # Examples
1020fbf8fb32SBenno Lossin ///
10211ab10101SBenno Lossin /// ```rust
102284837cf6SBenno Lossin /// # #![feature(allocator_api)]
102384837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
102484837cf6SBenno Lossin /// # use pin_init::*;
102584837cf6SBenno Lossin /// let mtx_init = CMutex::new(42);
102684837cf6SBenno Lossin /// // Make the initializer print the value.
102784837cf6SBenno Lossin /// let mtx_init = mtx_init.pin_chain(|mtx| {
102884837cf6SBenno Lossin /// println!("{:?}", mtx.get_data_mut());
1029fbf8fb32SBenno Lossin /// Ok(())
1030fbf8fb32SBenno Lossin /// });
1031fbf8fb32SBenno Lossin /// ```
pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E> where F: FnOnce(Pin<&mut T>) -> Result<(), E>,1032fbf8fb32SBenno Lossin fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
1033fbf8fb32SBenno Lossin where
1034fbf8fb32SBenno Lossin F: FnOnce(Pin<&mut T>) -> Result<(), E>,
1035fbf8fb32SBenno Lossin {
1036fbf8fb32SBenno Lossin ChainPinInit(self, f, PhantomData)
1037fbf8fb32SBenno Lossin }
1038fbf8fb32SBenno Lossin }
1039fbf8fb32SBenno Lossin
1040fbf8fb32SBenno Lossin /// An initializer returned by [`PinInit::pin_chain`].
104131547c98SBenno Lossin pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
1042fbf8fb32SBenno Lossin
1043fbf8fb32SBenno Lossin // SAFETY: The `__pinned_init` function is implemented such that it
1044fbf8fb32SBenno Lossin // - returns `Ok(())` on successful initialization,
1045fbf8fb32SBenno Lossin // - returns `Err(err)` on error and in this case `slot` will be dropped.
1046fbf8fb32SBenno Lossin // - considers `slot` pinned.
1047fbf8fb32SBenno Lossin unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainPinInit<I, F, T, E>
1048fbf8fb32SBenno Lossin where
1049fbf8fb32SBenno Lossin I: PinInit<T, E>,
1050fbf8fb32SBenno Lossin F: FnOnce(Pin<&mut T>) -> Result<(), E>,
1051fbf8fb32SBenno Lossin {
__pinned_init(self, slot: *mut T) -> Result<(), E>1052fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1053fbf8fb32SBenno Lossin // SAFETY: All requirements fulfilled since this function is `__pinned_init`.
1054fbf8fb32SBenno Lossin unsafe { self.0.__pinned_init(slot)? };
1055fbf8fb32SBenno Lossin // SAFETY: The above call initialized `slot` and we still have unique access.
1056fbf8fb32SBenno Lossin let val = unsafe { &mut *slot };
1057fbf8fb32SBenno Lossin // SAFETY: `slot` is considered pinned.
1058fbf8fb32SBenno Lossin let val = unsafe { Pin::new_unchecked(val) };
1059fbf8fb32SBenno Lossin // SAFETY: `slot` was initialized above.
1060fbf8fb32SBenno Lossin (self.1)(val).inspect_err(|_| unsafe { core::ptr::drop_in_place(slot) })
1061fbf8fb32SBenno Lossin }
1062fbf8fb32SBenno Lossin }
1063fbf8fb32SBenno Lossin
1064fbf8fb32SBenno Lossin /// An initializer for `T`.
1065fbf8fb32SBenno Lossin ///
1066fbf8fb32SBenno Lossin /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
1067129e97beSBenno Lossin /// be [`Box<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]). Because
1068fbf8fb32SBenno Lossin /// [`PinInit<T, E>`] is a super trait, you can use every function that takes it as well.
1069fbf8fb32SBenno Lossin ///
1070fbf8fb32SBenno Lossin /// Also see the [module description](self).
1071fbf8fb32SBenno Lossin ///
1072fbf8fb32SBenno Lossin /// # Safety
1073fbf8fb32SBenno Lossin ///
1074fbf8fb32SBenno Lossin /// When implementing this trait you will need to take great care. Also there are probably very few
1075fbf8fb32SBenno Lossin /// cases where a manual implementation is necessary. Use [`init_from_closure`] where possible.
1076fbf8fb32SBenno Lossin ///
1077fbf8fb32SBenno Lossin /// The [`Init::__init`] function:
1078fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
1079fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
1080fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
1081fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
1082fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
1083fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
1084fbf8fb32SBenno Lossin ///
1085fbf8fb32SBenno Lossin /// The `__pinned_init` function from the supertrait [`PinInit`] needs to execute the exact same
1086fbf8fb32SBenno Lossin /// code as `__init`.
1087fbf8fb32SBenno Lossin ///
1088fbf8fb32SBenno Lossin /// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
1089fbf8fb32SBenno Lossin /// move the pointee after initialization.
1090fbf8fb32SBenno Lossin ///
10919b2299afSBenno Lossin #[cfg_attr(
10929b2299afSBenno Lossin kernel,
10939b2299afSBenno Lossin doc = "[`Arc<T>`]: https://rust.docs.kernel.org/kernel/sync/struct.Arc.html"
10949b2299afSBenno Lossin )]
10959b2299afSBenno Lossin #[cfg_attr(
10969b2299afSBenno Lossin kernel,
10979b2299afSBenno Lossin doc = "[`Box<T>`]: https://rust.docs.kernel.org/kernel/alloc/kbox/struct.Box.html"
10989b2299afSBenno Lossin )]
10999b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
11009b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
1101fbf8fb32SBenno Lossin #[must_use = "An initializer must be used in order to create its value."]
1102fbf8fb32SBenno Lossin pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
1103fbf8fb32SBenno Lossin /// Initializes `slot`.
1104fbf8fb32SBenno Lossin ///
1105fbf8fb32SBenno Lossin /// # Safety
1106fbf8fb32SBenno Lossin ///
1107fbf8fb32SBenno Lossin /// - `slot` is a valid pointer to uninitialized memory.
1108fbf8fb32SBenno Lossin /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
1109fbf8fb32SBenno Lossin /// deallocate.
__init(self, slot: *mut T) -> Result<(), E>1110fbf8fb32SBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
1111fbf8fb32SBenno Lossin
1112fbf8fb32SBenno Lossin /// First initializes the value using `self` then calls the function `f` with the initialized
1113fbf8fb32SBenno Lossin /// value.
1114fbf8fb32SBenno Lossin ///
1115fbf8fb32SBenno Lossin /// If `f` returns an error the value is dropped and the initializer will forward the error.
1116fbf8fb32SBenno Lossin ///
1117fbf8fb32SBenno Lossin /// # Examples
1118fbf8fb32SBenno Lossin ///
11191ab10101SBenno Lossin /// ```rust
1120fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
112102c01c08SBenno Lossin /// use pin_init::{init, zeroed, Init};
112202c01c08SBenno Lossin ///
1123fbf8fb32SBenno Lossin /// struct Foo {
1124fbf8fb32SBenno Lossin /// buf: [u8; 1_000_000],
1125fbf8fb32SBenno Lossin /// }
1126fbf8fb32SBenno Lossin ///
1127fbf8fb32SBenno Lossin /// impl Foo {
1128fbf8fb32SBenno Lossin /// fn setup(&mut self) {
112902c01c08SBenno Lossin /// println!("Setting up foo");
1130fbf8fb32SBenno Lossin /// }
1131fbf8fb32SBenno Lossin /// }
1132fbf8fb32SBenno Lossin ///
1133fbf8fb32SBenno Lossin /// let foo = init!(Foo {
113484837cf6SBenno Lossin /// buf <- zeroed()
1135fbf8fb32SBenno Lossin /// }).chain(|foo| {
1136fbf8fb32SBenno Lossin /// foo.setup();
1137fbf8fb32SBenno Lossin /// Ok(())
1138fbf8fb32SBenno Lossin /// });
1139fbf8fb32SBenno Lossin /// ```
chain<F>(self, f: F) -> ChainInit<Self, F, T, E> where F: FnOnce(&mut T) -> Result<(), E>,1140fbf8fb32SBenno Lossin fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
1141fbf8fb32SBenno Lossin where
1142fbf8fb32SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
1143fbf8fb32SBenno Lossin {
1144fbf8fb32SBenno Lossin ChainInit(self, f, PhantomData)
1145fbf8fb32SBenno Lossin }
1146fbf8fb32SBenno Lossin }
1147fbf8fb32SBenno Lossin
1148fbf8fb32SBenno Lossin /// An initializer returned by [`Init::chain`].
114931547c98SBenno Lossin pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
1150fbf8fb32SBenno Lossin
1151fbf8fb32SBenno Lossin // SAFETY: The `__init` function is implemented such that it
1152fbf8fb32SBenno Lossin // - returns `Ok(())` on successful initialization,
1153fbf8fb32SBenno Lossin // - returns `Err(err)` on error and in this case `slot` will be dropped.
1154fbf8fb32SBenno Lossin unsafe impl<T: ?Sized, E, I, F> Init<T, E> for ChainInit<I, F, T, E>
1155fbf8fb32SBenno Lossin where
1156fbf8fb32SBenno Lossin I: Init<T, E>,
1157fbf8fb32SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
1158fbf8fb32SBenno Lossin {
__init(self, slot: *mut T) -> Result<(), E>1159fbf8fb32SBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
1160fbf8fb32SBenno Lossin // SAFETY: All requirements fulfilled since this function is `__init`.
1161fbf8fb32SBenno Lossin unsafe { self.0.__pinned_init(slot)? };
1162fbf8fb32SBenno Lossin // SAFETY: The above call initialized `slot` and we still have unique access.
1163fbf8fb32SBenno Lossin (self.1)(unsafe { &mut *slot }).inspect_err(|_|
1164fbf8fb32SBenno Lossin // SAFETY: `slot` was initialized above.
1165fbf8fb32SBenno Lossin unsafe { core::ptr::drop_in_place(slot) })
1166fbf8fb32SBenno Lossin }
1167fbf8fb32SBenno Lossin }
1168fbf8fb32SBenno Lossin
1169fbf8fb32SBenno Lossin // SAFETY: `__pinned_init` behaves exactly the same as `__init`.
1170fbf8fb32SBenno Lossin unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainInit<I, F, T, E>
1171fbf8fb32SBenno Lossin where
1172fbf8fb32SBenno Lossin I: Init<T, E>,
1173fbf8fb32SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
1174fbf8fb32SBenno Lossin {
__pinned_init(self, slot: *mut T) -> Result<(), E>1175fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1176fbf8fb32SBenno Lossin // SAFETY: `__init` has less strict requirements compared to `__pinned_init`.
1177fbf8fb32SBenno Lossin unsafe { self.__init(slot) }
1178fbf8fb32SBenno Lossin }
1179fbf8fb32SBenno Lossin }
1180fbf8fb32SBenno Lossin
1181fbf8fb32SBenno Lossin /// Creates a new [`PinInit<T, E>`] from the given closure.
1182fbf8fb32SBenno Lossin ///
1183fbf8fb32SBenno Lossin /// # Safety
1184fbf8fb32SBenno Lossin ///
1185fbf8fb32SBenno Lossin /// The closure:
1186fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
1187fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
1188fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
1189fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
1190fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
1191fbf8fb32SBenno Lossin /// - may assume that the `slot` does not move if `T: !Unpin`,
1192fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
1193fbf8fb32SBenno Lossin #[inline]
pin_init_from_closure<T: ?Sized, E>( f: impl FnOnce(*mut T) -> Result<(), E>, ) -> impl PinInit<T, E>1194fbf8fb32SBenno Lossin pub const unsafe fn pin_init_from_closure<T: ?Sized, E>(
1195fbf8fb32SBenno Lossin f: impl FnOnce(*mut T) -> Result<(), E>,
1196fbf8fb32SBenno Lossin ) -> impl PinInit<T, E> {
1197fbf8fb32SBenno Lossin __internal::InitClosure(f, PhantomData)
1198fbf8fb32SBenno Lossin }
1199fbf8fb32SBenno Lossin
1200fbf8fb32SBenno Lossin /// Creates a new [`Init<T, E>`] from the given closure.
1201fbf8fb32SBenno Lossin ///
1202fbf8fb32SBenno Lossin /// # Safety
1203fbf8fb32SBenno Lossin ///
1204fbf8fb32SBenno Lossin /// The closure:
1205fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
1206fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
1207fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
1208fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
1209fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
1210fbf8fb32SBenno Lossin /// - the `slot` may move after initialization.
1211fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
1212fbf8fb32SBenno Lossin #[inline]
init_from_closure<T: ?Sized, E>( f: impl FnOnce(*mut T) -> Result<(), E>, ) -> impl Init<T, E>1213fbf8fb32SBenno Lossin pub const unsafe fn init_from_closure<T: ?Sized, E>(
1214fbf8fb32SBenno Lossin f: impl FnOnce(*mut T) -> Result<(), E>,
1215fbf8fb32SBenno Lossin ) -> impl Init<T, E> {
1216fbf8fb32SBenno Lossin __internal::InitClosure(f, PhantomData)
1217fbf8fb32SBenno Lossin }
1218fbf8fb32SBenno Lossin
1219fbf8fb32SBenno Lossin /// An initializer that leaves the memory uninitialized.
1220fbf8fb32SBenno Lossin ///
1221fbf8fb32SBenno Lossin /// The initializer is a no-op. The `slot` memory is not changed.
1222fbf8fb32SBenno Lossin #[inline]
uninit<T, E>() -> impl Init<MaybeUninit<T>, E>1223fbf8fb32SBenno Lossin pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
1224fbf8fb32SBenno Lossin // SAFETY: The memory is allowed to be uninitialized.
1225fbf8fb32SBenno Lossin unsafe { init_from_closure(|_| Ok(())) }
1226fbf8fb32SBenno Lossin }
1227fbf8fb32SBenno Lossin
1228fbf8fb32SBenno Lossin /// Initializes an array by initializing each element via the provided initializer.
1229fbf8fb32SBenno Lossin ///
1230fbf8fb32SBenno Lossin /// # Examples
1231fbf8fb32SBenno Lossin ///
12321ab10101SBenno Lossin /// ```rust
123384837cf6SBenno Lossin /// # use pin_init::*;
123484837cf6SBenno Lossin /// use pin_init::init_array_from_fn;
123584837cf6SBenno Lossin /// let array: Box<[usize; 1_000]> = Box::init(init_array_from_fn(|i| i)).unwrap();
1236fbf8fb32SBenno Lossin /// assert_eq!(array.len(), 1_000);
1237fbf8fb32SBenno 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>,1238fbf8fb32SBenno Lossin pub fn init_array_from_fn<I, const N: usize, T, E>(
1239fbf8fb32SBenno Lossin mut make_init: impl FnMut(usize) -> I,
1240fbf8fb32SBenno Lossin ) -> impl Init<[T; N], E>
1241fbf8fb32SBenno Lossin where
1242fbf8fb32SBenno Lossin I: Init<T, E>,
1243fbf8fb32SBenno Lossin {
1244fbf8fb32SBenno Lossin let init = move |slot: *mut [T; N]| {
1245fbf8fb32SBenno Lossin let slot = slot.cast::<T>();
1246fbf8fb32SBenno Lossin for i in 0..N {
1247fbf8fb32SBenno Lossin let init = make_init(i);
1248fbf8fb32SBenno Lossin // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
1249fbf8fb32SBenno Lossin let ptr = unsafe { slot.add(i) };
1250fbf8fb32SBenno Lossin // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
1251fbf8fb32SBenno Lossin // requirements.
125231547c98SBenno Lossin if let Err(e) = unsafe { init.__init(ptr) } {
125331547c98SBenno Lossin // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
125431547c98SBenno Lossin // `Err` below, `slot` will be considered uninitialized memory.
125531547c98SBenno Lossin unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
125631547c98SBenno Lossin return Err(e);
1257fbf8fb32SBenno Lossin }
125831547c98SBenno Lossin }
1259fbf8fb32SBenno Lossin Ok(())
1260fbf8fb32SBenno Lossin };
1261fbf8fb32SBenno Lossin // SAFETY: The initializer above initializes every element of the array. On failure it drops
1262fbf8fb32SBenno Lossin // any initialized elements and returns `Err`.
1263fbf8fb32SBenno Lossin unsafe { init_from_closure(init) }
1264fbf8fb32SBenno Lossin }
1265fbf8fb32SBenno Lossin
1266fbf8fb32SBenno Lossin /// Initializes an array by initializing each element via the provided initializer.
1267fbf8fb32SBenno Lossin ///
1268fbf8fb32SBenno Lossin /// # Examples
1269fbf8fb32SBenno Lossin ///
12701ab10101SBenno Lossin /// ```rust
127184837cf6SBenno Lossin /// # #![feature(allocator_api)]
127284837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
127384837cf6SBenno Lossin /// # use pin_init::*;
127484837cf6SBenno Lossin /// # use core::pin::Pin;
127584837cf6SBenno Lossin /// use pin_init::pin_init_array_from_fn;
127684837cf6SBenno Lossin /// use std::sync::Arc;
127784837cf6SBenno Lossin /// let array: Pin<Arc<[CMutex<usize>; 1_000]>> =
127884837cf6SBenno Lossin /// Arc::pin_init(pin_init_array_from_fn(|i| CMutex::new(i))).unwrap();
1279fbf8fb32SBenno Lossin /// assert_eq!(array.len(), 1_000);
1280fbf8fb32SBenno 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>,1281fbf8fb32SBenno Lossin pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
1282fbf8fb32SBenno Lossin mut make_init: impl FnMut(usize) -> I,
1283fbf8fb32SBenno Lossin ) -> impl PinInit<[T; N], E>
1284fbf8fb32SBenno Lossin where
1285fbf8fb32SBenno Lossin I: PinInit<T, E>,
1286fbf8fb32SBenno Lossin {
1287fbf8fb32SBenno Lossin let init = move |slot: *mut [T; N]| {
1288fbf8fb32SBenno Lossin let slot = slot.cast::<T>();
1289fbf8fb32SBenno Lossin for i in 0..N {
1290fbf8fb32SBenno Lossin let init = make_init(i);
1291fbf8fb32SBenno Lossin // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
1292fbf8fb32SBenno Lossin let ptr = unsafe { slot.add(i) };
1293fbf8fb32SBenno Lossin // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
1294fbf8fb32SBenno Lossin // requirements.
129531547c98SBenno Lossin if let Err(e) = unsafe { init.__pinned_init(ptr) } {
129631547c98SBenno Lossin // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
129731547c98SBenno Lossin // `Err` below, `slot` will be considered uninitialized memory.
129831547c98SBenno Lossin unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
129931547c98SBenno Lossin return Err(e);
1300fbf8fb32SBenno Lossin }
130131547c98SBenno Lossin }
1302fbf8fb32SBenno Lossin Ok(())
1303fbf8fb32SBenno Lossin };
1304fbf8fb32SBenno Lossin // SAFETY: The initializer above initializes every element of the array. On failure it drops
1305fbf8fb32SBenno Lossin // any initialized elements and returns `Err`.
1306fbf8fb32SBenno Lossin unsafe { pin_init_from_closure(init) }
1307fbf8fb32SBenno Lossin }
1308fbf8fb32SBenno Lossin
1309fbf8fb32SBenno Lossin // SAFETY: Every type can be initialized by-value.
1310fbf8fb32SBenno Lossin unsafe impl<T, E> Init<T, E> for T {
__init(self, slot: *mut T) -> Result<(), E>1311fbf8fb32SBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
1312fbf8fb32SBenno Lossin // SAFETY: TODO.
1313fbf8fb32SBenno Lossin unsafe { slot.write(self) };
1314fbf8fb32SBenno Lossin Ok(())
1315fbf8fb32SBenno Lossin }
1316fbf8fb32SBenno Lossin }
1317fbf8fb32SBenno Lossin
1318fbf8fb32SBenno Lossin // SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`.
1319fbf8fb32SBenno Lossin unsafe impl<T, E> PinInit<T, E> for T {
__pinned_init(self, slot: *mut T) -> Result<(), E>1320fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1321fbf8fb32SBenno Lossin // SAFETY: TODO.
1322fbf8fb32SBenno Lossin unsafe { self.__init(slot) }
1323fbf8fb32SBenno Lossin }
1324fbf8fb32SBenno Lossin }
1325fbf8fb32SBenno Lossin
1326fbf8fb32SBenno Lossin /// Smart pointer containing uninitialized memory and that can write a value.
1327fbf8fb32SBenno Lossin pub trait InPlaceWrite<T> {
1328fbf8fb32SBenno Lossin /// The type `Self` turns into when the contents are initialized.
1329fbf8fb32SBenno Lossin type Initialized;
1330fbf8fb32SBenno Lossin
1331fbf8fb32SBenno Lossin /// Use the given initializer to write a value into `self`.
1332fbf8fb32SBenno Lossin ///
1333fbf8fb32SBenno Lossin /// Does not drop the current value and considers it as uninitialized memory.
write_init<E>(self, init: impl Init<T, E>) -> Result<Self::Initialized, E>1334fbf8fb32SBenno Lossin fn write_init<E>(self, init: impl Init<T, E>) -> Result<Self::Initialized, E>;
1335fbf8fb32SBenno Lossin
1336fbf8fb32SBenno Lossin /// Use the given pin-initializer to write a value into `self`.
1337fbf8fb32SBenno Lossin ///
1338fbf8fb32SBenno Lossin /// Does not drop the current value and considers it as uninitialized memory.
write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E>1339fbf8fb32SBenno Lossin fn write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E>;
1340fbf8fb32SBenno Lossin }
1341fbf8fb32SBenno Lossin
1342fbf8fb32SBenno Lossin /// Trait facilitating pinned destruction.
1343fbf8fb32SBenno Lossin ///
1344fbf8fb32SBenno Lossin /// Use [`pinned_drop`] to implement this trait safely:
1345fbf8fb32SBenno Lossin ///
13461ab10101SBenno Lossin /// ```rust
134784837cf6SBenno Lossin /// # #![feature(allocator_api)]
134884837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
134984837cf6SBenno Lossin /// # use pin_init::*;
1350fbf8fb32SBenno Lossin /// use core::pin::Pin;
1351fbf8fb32SBenno Lossin /// #[pin_data(PinnedDrop)]
1352fbf8fb32SBenno Lossin /// struct Foo {
1353fbf8fb32SBenno Lossin /// #[pin]
135484837cf6SBenno Lossin /// mtx: CMutex<usize>,
1355fbf8fb32SBenno Lossin /// }
1356fbf8fb32SBenno Lossin ///
1357fbf8fb32SBenno Lossin /// #[pinned_drop]
1358fbf8fb32SBenno Lossin /// impl PinnedDrop for Foo {
1359fbf8fb32SBenno Lossin /// fn drop(self: Pin<&mut Self>) {
136084837cf6SBenno Lossin /// println!("Foo is being dropped!");
1361fbf8fb32SBenno Lossin /// }
1362fbf8fb32SBenno Lossin /// }
1363fbf8fb32SBenno Lossin /// ```
1364fbf8fb32SBenno Lossin ///
1365fbf8fb32SBenno Lossin /// # Safety
1366fbf8fb32SBenno Lossin ///
1367fbf8fb32SBenno Lossin /// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
1368fbf8fb32SBenno Lossin pub unsafe trait PinnedDrop: __internal::HasPinData {
1369fbf8fb32SBenno Lossin /// Executes the pinned destructor of this type.
1370fbf8fb32SBenno Lossin ///
1371fbf8fb32SBenno Lossin /// While this function is marked safe, it is actually unsafe to call it manually. For this
1372fbf8fb32SBenno Lossin /// reason it takes an additional parameter. This type can only be constructed by `unsafe` code
1373fbf8fb32SBenno Lossin /// and thus prevents this function from being called where it should not.
1374fbf8fb32SBenno Lossin ///
1375fbf8fb32SBenno Lossin /// This extra parameter will be generated by the `#[pinned_drop]` proc-macro attribute
1376fbf8fb32SBenno Lossin /// automatically.
drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop)1377fbf8fb32SBenno Lossin fn drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop);
1378fbf8fb32SBenno Lossin }
1379fbf8fb32SBenno Lossin
1380fbf8fb32SBenno Lossin /// Marker trait for types that can be initialized by writing just zeroes.
1381fbf8fb32SBenno Lossin ///
1382fbf8fb32SBenno Lossin /// # Safety
1383fbf8fb32SBenno Lossin ///
1384fbf8fb32SBenno Lossin /// The bit pattern consisting of only zeroes is a valid bit pattern for this type. In other words,
1385fbf8fb32SBenno Lossin /// this is not UB:
1386fbf8fb32SBenno Lossin ///
1387fbf8fb32SBenno Lossin /// ```rust,ignore
1388fbf8fb32SBenno Lossin /// let val: Self = unsafe { core::mem::zeroed() };
1389fbf8fb32SBenno Lossin /// ```
1390fbf8fb32SBenno Lossin pub unsafe trait Zeroable {}
1391fbf8fb32SBenno Lossin
13925657c3a9SBenno Lossin /// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
13935657c3a9SBenno Lossin /// `None` to that location.
13945657c3a9SBenno Lossin ///
13955657c3a9SBenno Lossin /// # Safety
13965657c3a9SBenno Lossin ///
13975657c3a9SBenno Lossin /// The implementer needs to ensure that `unsafe impl Zeroable for Option<Self> {}` is sound.
13985657c3a9SBenno Lossin pub unsafe trait ZeroableOption {}
13995657c3a9SBenno Lossin
14005657c3a9SBenno Lossin // SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
14015657c3a9SBenno Lossin unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}
14025657c3a9SBenno Lossin
1403fbf8fb32SBenno Lossin /// Create a new zeroed T.
1404fbf8fb32SBenno Lossin ///
1405fbf8fb32SBenno Lossin /// The returned initializer will write `0x00` to every byte of the given `slot`.
1406fbf8fb32SBenno Lossin #[inline]
zeroed<T: Zeroable>() -> impl Init<T>1407fbf8fb32SBenno Lossin pub fn zeroed<T: Zeroable>() -> impl Init<T> {
1408fbf8fb32SBenno Lossin // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
1409fbf8fb32SBenno Lossin // and because we write all zeroes, the memory is initialized.
1410fbf8fb32SBenno Lossin unsafe {
1411fbf8fb32SBenno Lossin init_from_closure(|slot: *mut T| {
1412fbf8fb32SBenno Lossin slot.write_bytes(0, 1);
1413fbf8fb32SBenno Lossin Ok(())
1414fbf8fb32SBenno Lossin })
1415fbf8fb32SBenno Lossin }
1416fbf8fb32SBenno Lossin }
1417fbf8fb32SBenno Lossin
1418fbf8fb32SBenno Lossin macro_rules! impl_zeroable {
1419fbf8fb32SBenno Lossin ($($({$($generics:tt)*})? $t:ty, )*) => {
1420fbf8fb32SBenno Lossin // SAFETY: Safety comments written in the macro invocation.
1421fbf8fb32SBenno Lossin $(unsafe impl$($($generics)*)? Zeroable for $t {})*
1422fbf8fb32SBenno Lossin };
1423fbf8fb32SBenno Lossin }
1424fbf8fb32SBenno Lossin
1425fbf8fb32SBenno Lossin impl_zeroable! {
1426fbf8fb32SBenno Lossin // SAFETY: All primitives that are allowed to be zero.
1427fbf8fb32SBenno Lossin bool,
1428fbf8fb32SBenno Lossin char,
1429fbf8fb32SBenno Lossin u8, u16, u32, u64, u128, usize,
1430fbf8fb32SBenno Lossin i8, i16, i32, i64, i128, isize,
1431fbf8fb32SBenno Lossin f32, f64,
1432fbf8fb32SBenno Lossin
1433fbf8fb32SBenno Lossin // Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
1434fbf8fb32SBenno Lossin // creating an instance of an uninhabited type is immediate undefined behavior. For more on
1435fbf8fb32SBenno Lossin // uninhabited/empty types, consult The Rustonomicon:
1436fbf8fb32SBenno Lossin // <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
1437fbf8fb32SBenno Lossin // also has information on undefined behavior:
1438fbf8fb32SBenno Lossin // <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
1439fbf8fb32SBenno Lossin //
1440fbf8fb32SBenno Lossin // SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
1441fbf8fb32SBenno Lossin {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
1442fbf8fb32SBenno Lossin
1443fbf8fb32SBenno Lossin // SAFETY: Type is allowed to take any value, including all zeros.
1444fbf8fb32SBenno Lossin {<T>} MaybeUninit<T>,
1445fbf8fb32SBenno Lossin
1446fbf8fb32SBenno Lossin // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.
1447fbf8fb32SBenno Lossin {<T: ?Sized + Zeroable>} UnsafeCell<T>,
1448fbf8fb32SBenno Lossin
14494e82c870SLinus Torvalds // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
1450*193b5a75SMiguel Ojeda // <https://doc.rust-lang.org/stable/std/option/index.html#representation>).
1451fbf8fb32SBenno Lossin Option<NonZeroU8>, Option<NonZeroU16>, Option<NonZeroU32>, Option<NonZeroU64>,
1452fbf8fb32SBenno Lossin Option<NonZeroU128>, Option<NonZeroUsize>,
1453fbf8fb32SBenno Lossin Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>,
1454fbf8fb32SBenno Lossin Option<NonZeroI128>, Option<NonZeroIsize>,
14554e82c870SLinus Torvalds {<T>} Option<NonNull<T>>,
1456fbf8fb32SBenno Lossin
1457fbf8fb32SBenno Lossin // SAFETY: `null` pointer is valid.
1458fbf8fb32SBenno Lossin //
1459fbf8fb32SBenno Lossin // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be
1460fbf8fb32SBenno Lossin // null.
1461fbf8fb32SBenno Lossin //
1462fbf8fb32SBenno Lossin // When `Pointee` gets stabilized, we could use
1463fbf8fb32SBenno Lossin // `T: ?Sized where <T as Pointee>::Metadata: Zeroable`
1464fbf8fb32SBenno Lossin {<T>} *mut T, {<T>} *const T,
1465fbf8fb32SBenno Lossin
1466fbf8fb32SBenno Lossin // SAFETY: `null` pointer is valid and the metadata part of these fat pointers is allowed to be
1467fbf8fb32SBenno Lossin // zero.
1468fbf8fb32SBenno Lossin {<T>} *mut [T], {<T>} *const [T], *mut str, *const str,
1469fbf8fb32SBenno Lossin
1470fbf8fb32SBenno Lossin // SAFETY: `T` is `Zeroable`.
1471fbf8fb32SBenno Lossin {<const N: usize, T: Zeroable>} [T; N], {<T: Zeroable>} Wrapping<T>,
1472fbf8fb32SBenno Lossin }
1473fbf8fb32SBenno Lossin
1474fbf8fb32SBenno Lossin macro_rules! impl_tuple_zeroable {
1475fbf8fb32SBenno Lossin ($(,)?) => {};
1476fbf8fb32SBenno Lossin ($first:ident, $($t:ident),* $(,)?) => {
1477fbf8fb32SBenno Lossin // SAFETY: All elements are zeroable and padding can be zero.
1478fbf8fb32SBenno Lossin unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}
1479fbf8fb32SBenno Lossin impl_tuple_zeroable!($($t),* ,);
1480fbf8fb32SBenno Lossin }
1481fbf8fb32SBenno Lossin }
1482fbf8fb32SBenno Lossin
1483fbf8fb32SBenno Lossin impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);
1484