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 //!
35bc5f3e0eSChristian Schrefl //! ## Nightly needed for `unsafe-pinned` feature
36bc5f3e0eSChristian Schrefl //!
37bc5f3e0eSChristian Schrefl //! This feature enables the `Wrapper` implementation on the unstable `core::pin::UnsafePinned` type.
38bc5f3e0eSChristian Schrefl //! This requires the [`unsafe_pinned` unstable feature](https://github.com/rust-lang/rust/issues/125735)
39bc5f3e0eSChristian Schrefl //! and therefore a nightly compiler. Note that this feature is not enabled by default.
40bc5f3e0eSChristian Schrefl //!
41fbf8fb32SBenno Lossin //! # Overview
42fbf8fb32SBenno Lossin //!
43fbf8fb32SBenno Lossin //! To initialize a `struct` with an in-place constructor you will need two things:
44fbf8fb32SBenno Lossin //! - an in-place constructor,
45fbf8fb32SBenno Lossin //! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
46129e97beSBenno Lossin //! [`Box<T>`] or any other smart pointer that supports this library).
47fbf8fb32SBenno Lossin //!
48fbf8fb32SBenno Lossin //! To get an in-place constructor there are generally three options:
49fbf8fb32SBenno Lossin //! - directly creating an in-place constructor using the [`pin_init!`] macro,
50fbf8fb32SBenno Lossin //! - a custom function/macro returning an in-place constructor provided by someone else,
51fbf8fb32SBenno Lossin //! - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
52fbf8fb32SBenno Lossin //!
5302c01c08SBenno Lossin //! Aside from pinned initialization, this library also supports in-place construction without
5402c01c08SBenno Lossin //! pinning, the macros/types/functions are generally named like the pinned variants without the
5502c01c08SBenno Lossin //! `pin_` prefix.
56fbf8fb32SBenno Lossin //!
57fbf8fb32SBenno Lossin //! # Examples
58fbf8fb32SBenno Lossin //!
5902c01c08SBenno Lossin //! Throughout the examples we will often make use of the `CMutex` type which can be found in
6002c01c08SBenno Lossin //! `../examples/mutex.rs`. It is essentially a userland rebuild of the `struct mutex` type from
6102c01c08SBenno Lossin //! the Linux kernel. It also uses a wait list and a basic spinlock. Importantly the wait list
6202c01c08SBenno Lossin //! requires it to be pinned to be locked and thus is a prime candidate for using this library.
6302c01c08SBenno Lossin //!
64fbf8fb32SBenno Lossin //! ## Using the [`pin_init!`] macro
65fbf8fb32SBenno Lossin //!
66fbf8fb32SBenno Lossin //! If you want to use [`PinInit`], then you will have to annotate your `struct` with
67fbf8fb32SBenno Lossin //! `#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for
68fbf8fb32SBenno Lossin //! [structurally pinned fields]. After doing this, you can then create an in-place constructor via
69fbf8fb32SBenno Lossin //! [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
70fbf8fb32SBenno Lossin //! that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
71fbf8fb32SBenno Lossin //!
721ab10101SBenno Lossin //! ```rust
73fbf8fb32SBenno Lossin //! # #![expect(clippy::disallowed_names)]
7484837cf6SBenno Lossin //! # #![feature(allocator_api)]
7584837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
76fbf8fb32SBenno Lossin //! # use core::pin::Pin;
7702c01c08SBenno Lossin //! use pin_init::{pin_data, pin_init, InPlaceInit};
7884837cf6SBenno Lossin //!
79fbf8fb32SBenno Lossin //! #[pin_data]
80fbf8fb32SBenno Lossin //! struct Foo {
81fbf8fb32SBenno Lossin //! #[pin]
8284837cf6SBenno Lossin //! a: CMutex<usize>,
83fbf8fb32SBenno Lossin //! b: u32,
84fbf8fb32SBenno Lossin //! }
85fbf8fb32SBenno Lossin //!
86fbf8fb32SBenno Lossin //! let foo = pin_init!(Foo {
8784837cf6SBenno Lossin //! a <- CMutex::new(42),
88fbf8fb32SBenno Lossin //! b: 24,
89fbf8fb32SBenno Lossin //! });
9084837cf6SBenno Lossin //! # let _ = Box::pin_init(foo);
91fbf8fb32SBenno Lossin //! ```
92fbf8fb32SBenno Lossin //!
93fbf8fb32SBenno Lossin //! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
94fbf8fb32SBenno Lossin //! (or just the stack) to actually initialize a `Foo`:
95fbf8fb32SBenno Lossin //!
961ab10101SBenno Lossin //! ```rust
97fbf8fb32SBenno Lossin //! # #![expect(clippy::disallowed_names)]
9884837cf6SBenno Lossin //! # #![feature(allocator_api)]
9984837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
10084837cf6SBenno Lossin //! # use core::{alloc::AllocError, pin::Pin};
10184837cf6SBenno Lossin //! # use pin_init::*;
10284837cf6SBenno Lossin //! #
103fbf8fb32SBenno Lossin //! # #[pin_data]
104fbf8fb32SBenno Lossin //! # struct Foo {
105fbf8fb32SBenno Lossin //! # #[pin]
10684837cf6SBenno Lossin //! # a: CMutex<usize>,
107fbf8fb32SBenno Lossin //! # b: u32,
108fbf8fb32SBenno Lossin //! # }
10984837cf6SBenno Lossin //! #
110fbf8fb32SBenno Lossin //! # let foo = pin_init!(Foo {
11184837cf6SBenno Lossin //! # a <- CMutex::new(42),
112fbf8fb32SBenno Lossin //! # b: 24,
113fbf8fb32SBenno Lossin //! # });
11484837cf6SBenno Lossin //! let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo);
115fbf8fb32SBenno Lossin //! ```
116fbf8fb32SBenno Lossin //!
117fbf8fb32SBenno Lossin //! For more information see the [`pin_init!`] macro.
118fbf8fb32SBenno Lossin //!
119fbf8fb32SBenno Lossin //! ## Using a custom function/macro that returns an initializer
120fbf8fb32SBenno Lossin //!
12102c01c08SBenno Lossin //! Many types that use this library supply a function/macro that returns an initializer, because
12202c01c08SBenno Lossin //! the above method only works for types where you can access the fields.
123fbf8fb32SBenno Lossin //!
1241ab10101SBenno Lossin //! ```rust
12584837cf6SBenno Lossin //! # #![feature(allocator_api)]
12684837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
12784837cf6SBenno Lossin //! # use pin_init::*;
12884837cf6SBenno Lossin //! # use std::sync::Arc;
12984837cf6SBenno Lossin //! # use core::pin::Pin;
13084837cf6SBenno Lossin //! let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42));
131fbf8fb32SBenno Lossin //! ```
132fbf8fb32SBenno Lossin //!
133fbf8fb32SBenno Lossin //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
134fbf8fb32SBenno Lossin //!
1351ab10101SBenno Lossin //! ```rust
13684837cf6SBenno Lossin //! # #![feature(allocator_api)]
13784837cf6SBenno Lossin //! # use pin_init::*;
13884837cf6SBenno Lossin //! # #[path = "../examples/error.rs"] mod error; use error::Error;
13984837cf6SBenno Lossin //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
140fbf8fb32SBenno Lossin //! #[pin_data]
141fbf8fb32SBenno Lossin //! struct DriverData {
142fbf8fb32SBenno Lossin //! #[pin]
14384837cf6SBenno Lossin //! status: CMutex<i32>,
14484837cf6SBenno Lossin //! buffer: Box<[u8; 1_000_000]>,
145fbf8fb32SBenno Lossin //! }
146fbf8fb32SBenno Lossin //!
147fbf8fb32SBenno Lossin //! impl DriverData {
148fbf8fb32SBenno Lossin //! fn new() -> impl PinInit<Self, Error> {
149fbf8fb32SBenno Lossin //! try_pin_init!(Self {
15084837cf6SBenno Lossin //! status <- CMutex::new(0),
15184837cf6SBenno Lossin //! buffer: Box::init(pin_init::zeroed())?,
15284837cf6SBenno Lossin //! }? Error)
153fbf8fb32SBenno Lossin //! }
154fbf8fb32SBenno Lossin //! }
155fbf8fb32SBenno Lossin //! ```
156fbf8fb32SBenno Lossin //!
157fbf8fb32SBenno Lossin //! ## Manual creation of an initializer
158fbf8fb32SBenno Lossin //!
159fbf8fb32SBenno Lossin //! Often when working with primitives the previous approaches are not sufficient. That is where
160fbf8fb32SBenno Lossin //! [`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a
161fbf8fb32SBenno Lossin //! [`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure
162fbf8fb32SBenno Lossin //! actually does the initialization in the correct way. Here are the things to look out for
163fbf8fb32SBenno Lossin //! (we are calling the parameter to the closure `slot`):
164fbf8fb32SBenno Lossin //! - when the closure returns `Ok(())`, then it has completed the initialization successfully, so
165fbf8fb32SBenno Lossin //! `slot` now contains a valid bit pattern for the type `T`,
166fbf8fb32SBenno Lossin //! - when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so
167fbf8fb32SBenno Lossin //! you need to take care to clean up anything if your initialization fails mid-way,
168fbf8fb32SBenno Lossin //! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of
169fbf8fb32SBenno Lossin //! `slot` gets called.
170fbf8fb32SBenno Lossin //!
1711ab10101SBenno Lossin //! ```rust
17284837cf6SBenno Lossin //! # #![feature(extern_types)]
17302c01c08SBenno Lossin //! use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop, pin_init_from_closure};
17484837cf6SBenno Lossin //! use core::{
17584837cf6SBenno Lossin //! ptr::addr_of_mut,
17684837cf6SBenno Lossin //! marker::PhantomPinned,
17784837cf6SBenno Lossin //! cell::UnsafeCell,
17884837cf6SBenno Lossin //! pin::Pin,
17984837cf6SBenno Lossin //! mem::MaybeUninit,
18084837cf6SBenno Lossin //! };
18184837cf6SBenno Lossin //! mod bindings {
18202c01c08SBenno Lossin //! #[repr(C)]
18302c01c08SBenno Lossin //! pub struct foo {
18402c01c08SBenno Lossin //! /* fields from C ... */
18502c01c08SBenno Lossin //! }
18684837cf6SBenno Lossin //! extern "C" {
18784837cf6SBenno Lossin //! pub fn init_foo(ptr: *mut foo);
18884837cf6SBenno Lossin //! pub fn destroy_foo(ptr: *mut foo);
18984837cf6SBenno Lossin //! #[must_use = "you must check the error return code"]
19084837cf6SBenno Lossin //! pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32;
19184837cf6SBenno Lossin //! }
19284837cf6SBenno Lossin //! }
19384837cf6SBenno Lossin //!
194fbf8fb32SBenno Lossin //! /// # Invariants
195fbf8fb32SBenno Lossin //! ///
196fbf8fb32SBenno Lossin //! /// `foo` is always initialized
197fbf8fb32SBenno Lossin //! #[pin_data(PinnedDrop)]
198fbf8fb32SBenno Lossin //! pub struct RawFoo {
199fbf8fb32SBenno Lossin //! #[pin]
200fbf8fb32SBenno Lossin //! _p: PhantomPinned,
20184837cf6SBenno Lossin //! #[pin]
20284837cf6SBenno Lossin //! foo: UnsafeCell<MaybeUninit<bindings::foo>>,
203fbf8fb32SBenno Lossin //! }
204fbf8fb32SBenno Lossin //!
205fbf8fb32SBenno Lossin //! impl RawFoo {
20684837cf6SBenno Lossin //! pub fn new(flags: u32) -> impl PinInit<Self, i32> {
207fbf8fb32SBenno Lossin //! // SAFETY:
208fbf8fb32SBenno Lossin //! // - when the closure returns `Ok(())`, then it has successfully initialized and
209fbf8fb32SBenno Lossin //! // enabled `foo`,
210fbf8fb32SBenno Lossin //! // - when it returns `Err(e)`, then it has cleaned up before
211fbf8fb32SBenno Lossin //! unsafe {
21284837cf6SBenno Lossin //! pin_init_from_closure(move |slot: *mut Self| {
213fbf8fb32SBenno Lossin //! // `slot` contains uninit memory, avoid creating a reference.
214fbf8fb32SBenno Lossin //! let foo = addr_of_mut!((*slot).foo);
21584837cf6SBenno Lossin //! let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>();
216fbf8fb32SBenno Lossin //!
217fbf8fb32SBenno Lossin //! // Initialize the `foo`
21884837cf6SBenno Lossin //! bindings::init_foo(foo);
219fbf8fb32SBenno Lossin //!
220fbf8fb32SBenno Lossin //! // Try to enable it.
22184837cf6SBenno Lossin //! let err = bindings::enable_foo(foo, flags);
222fbf8fb32SBenno Lossin //! if err != 0 {
223fbf8fb32SBenno Lossin //! // Enabling has failed, first clean up the foo and then return the error.
22484837cf6SBenno Lossin //! bindings::destroy_foo(foo);
22584837cf6SBenno Lossin //! Err(err)
22684837cf6SBenno Lossin //! } else {
227fbf8fb32SBenno Lossin //! // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
228fbf8fb32SBenno Lossin //! Ok(())
22984837cf6SBenno Lossin //! }
230fbf8fb32SBenno Lossin //! })
231fbf8fb32SBenno Lossin //! }
232fbf8fb32SBenno Lossin //! }
233fbf8fb32SBenno Lossin //! }
234fbf8fb32SBenno Lossin //!
235fbf8fb32SBenno Lossin //! #[pinned_drop]
236fbf8fb32SBenno Lossin //! impl PinnedDrop for RawFoo {
237fbf8fb32SBenno Lossin //! fn drop(self: Pin<&mut Self>) {
238fbf8fb32SBenno Lossin //! // SAFETY: Since `foo` is initialized, destroying is safe.
23984837cf6SBenno Lossin //! unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) };
240fbf8fb32SBenno Lossin //! }
241fbf8fb32SBenno Lossin //! }
242fbf8fb32SBenno Lossin //! ```
243fbf8fb32SBenno Lossin //!
24402c01c08SBenno Lossin //! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
24502c01c08SBenno Lossin //! the `kernel` crate. The [`sync`] module is a good starting point.
24602c01c08SBenno Lossin //!
24702c01c08SBenno Lossin //! [`sync`]: https://rust.docs.kernel.org/kernel/sync/index.html
248fbf8fb32SBenno Lossin //! [pinning]: https://doc.rust-lang.org/std/pin/index.html
249fbf8fb32SBenno Lossin //! [structurally pinned fields]:
250c3815aa4SChristian Schrefl //! https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning
251fbf8fb32SBenno Lossin //! [stack]: crate::stack_pin_init
2529b2299afSBenno Lossin #![cfg_attr(
2539b2299afSBenno Lossin kernel,
2549b2299afSBenno Lossin doc = "[`Arc<T>`]: https://rust.docs.kernel.org/kernel/sync/struct.Arc.html"
2559b2299afSBenno Lossin )]
2569b2299afSBenno Lossin #![cfg_attr(
2579b2299afSBenno Lossin kernel,
2589b2299afSBenno Lossin doc = "[`Box<T>`]: https://rust.docs.kernel.org/kernel/alloc/kbox/struct.Box.html"
2599b2299afSBenno Lossin )]
2609b2299afSBenno Lossin #![cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
2619b2299afSBenno Lossin #![cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
26202c01c08SBenno Lossin //! [`impl PinInit<Foo>`]: crate::PinInit
26302c01c08SBenno Lossin //! [`impl PinInit<T, E>`]: crate::PinInit
26402c01c08SBenno Lossin //! [`impl Init<T, E>`]: crate::Init
26502c01c08SBenno Lossin //! [Rust-for-Linux]: https://rust-for-linux.com/
266fbf8fb32SBenno Lossin
267dbd5058bSBenno Lossin #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
268dbd5058bSBenno Lossin #![cfg_attr(
269dbd5058bSBenno Lossin all(
270dbd5058bSBenno Lossin any(feature = "alloc", feature = "std"),
271dbd5058bSBenno Lossin not(RUSTC_NEW_UNINIT_IS_STABLE)
272dbd5058bSBenno Lossin ),
273dbd5058bSBenno Lossin feature(new_uninit)
274dbd5058bSBenno Lossin )]
275dbd5058bSBenno Lossin #![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
276dbd5058bSBenno Lossin #![cfg_attr(not(feature = "std"), no_std)]
277dbd5058bSBenno Lossin #![cfg_attr(feature = "alloc", feature(allocator_api))]
278b862aac8SChristian Schrefl #![cfg_attr(
279b862aac8SChristian Schrefl all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED),
280b862aac8SChristian Schrefl feature(unsafe_pinned)
281b862aac8SChristian Schrefl )]
282dbd5058bSBenno Lossin
283fbf8fb32SBenno Lossin use core::{
284fbf8fb32SBenno Lossin cell::UnsafeCell,
285fbf8fb32SBenno Lossin convert::Infallible,
286fbf8fb32SBenno Lossin marker::PhantomData,
287fbf8fb32SBenno Lossin mem::MaybeUninit,
288fbf8fb32SBenno Lossin num::*,
289fbf8fb32SBenno Lossin pin::Pin,
290fbf8fb32SBenno Lossin ptr::{self, NonNull},
291fbf8fb32SBenno Lossin };
292fbf8fb32SBenno Lossin
293fbf8fb32SBenno Lossin #[doc(hidden)]
294fbf8fb32SBenno Lossin pub mod __internal;
295fbf8fb32SBenno Lossin #[doc(hidden)]
296fbf8fb32SBenno Lossin pub mod macros;
297fbf8fb32SBenno Lossin
2989b2299afSBenno Lossin #[cfg(any(feature = "std", feature = "alloc"))]
2999b2299afSBenno Lossin mod alloc;
3009b2299afSBenno Lossin #[cfg(any(feature = "std", feature = "alloc"))]
3019b2299afSBenno Lossin pub use alloc::InPlaceInit;
3029b2299afSBenno Lossin
3034b11798eSBenno Lossin /// Used to specify the pinning information of the fields of a struct.
3044b11798eSBenno Lossin ///
3054b11798eSBenno Lossin /// This is somewhat similar in purpose as
3064b11798eSBenno Lossin /// [pin-project-lite](https://crates.io/crates/pin-project-lite).
3074b11798eSBenno Lossin /// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
3084b11798eSBenno Lossin /// field you want to structurally pin.
3094b11798eSBenno Lossin ///
3104b11798eSBenno Lossin /// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
3114b11798eSBenno Lossin /// then `#[pin]` directs the type of initializer that is required.
3124b11798eSBenno Lossin ///
3134b11798eSBenno Lossin /// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
3144b11798eSBenno Lossin /// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
3154b11798eSBenno Lossin /// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
3164b11798eSBenno Lossin ///
3174b11798eSBenno Lossin /// # Examples
3184b11798eSBenno Lossin ///
3191ab10101SBenno Lossin /// ```
32084837cf6SBenno Lossin /// # #![feature(allocator_api)]
32184837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
32284837cf6SBenno Lossin /// use pin_init::pin_data;
32384837cf6SBenno Lossin ///
32484837cf6SBenno Lossin /// enum Command {
32584837cf6SBenno Lossin /// /* ... */
32684837cf6SBenno Lossin /// }
32784837cf6SBenno Lossin ///
3284b11798eSBenno Lossin /// #[pin_data]
3294b11798eSBenno Lossin /// struct DriverData {
3304b11798eSBenno Lossin /// #[pin]
33184837cf6SBenno Lossin /// queue: CMutex<Vec<Command>>,
33284837cf6SBenno Lossin /// buf: Box<[u8; 1024 * 1024]>,
3334b11798eSBenno Lossin /// }
3344b11798eSBenno Lossin /// ```
3354b11798eSBenno Lossin ///
3361ab10101SBenno Lossin /// ```
33784837cf6SBenno Lossin /// # #![feature(allocator_api)]
33884837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
33984837cf6SBenno Lossin /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
34084837cf6SBenno Lossin /// use core::pin::Pin;
34184837cf6SBenno Lossin /// use pin_init::{pin_data, pinned_drop, PinnedDrop};
34284837cf6SBenno Lossin ///
34384837cf6SBenno Lossin /// enum Command {
34484837cf6SBenno Lossin /// /* ... */
34584837cf6SBenno Lossin /// }
3464b11798eSBenno Lossin ///
3474b11798eSBenno Lossin /// #[pin_data(PinnedDrop)]
3484b11798eSBenno Lossin /// struct DriverData {
3494b11798eSBenno Lossin /// #[pin]
35084837cf6SBenno Lossin /// queue: CMutex<Vec<Command>>,
35184837cf6SBenno Lossin /// buf: Box<[u8; 1024 * 1024]>,
35284837cf6SBenno Lossin /// raw_info: *mut bindings::info,
3534b11798eSBenno Lossin /// }
3544b11798eSBenno Lossin ///
3554b11798eSBenno Lossin /// #[pinned_drop]
3564b11798eSBenno Lossin /// impl PinnedDrop for DriverData {
3574b11798eSBenno Lossin /// fn drop(self: Pin<&mut Self>) {
3584b11798eSBenno Lossin /// unsafe { bindings::destroy_info(self.raw_info) };
3594b11798eSBenno Lossin /// }
3604b11798eSBenno Lossin /// }
3614b11798eSBenno Lossin /// ```
362dbd5058bSBenno Lossin pub use ::pin_init_internal::pin_data;
3634b11798eSBenno Lossin
3644b11798eSBenno Lossin /// Used to implement `PinnedDrop` safely.
3654b11798eSBenno Lossin ///
3664b11798eSBenno Lossin /// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
3674b11798eSBenno Lossin ///
3684b11798eSBenno Lossin /// # Examples
3694b11798eSBenno Lossin ///
3701ab10101SBenno Lossin /// ```
37184837cf6SBenno Lossin /// # #![feature(allocator_api)]
37284837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
37384837cf6SBenno Lossin /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} }
37484837cf6SBenno Lossin /// use core::pin::Pin;
37584837cf6SBenno Lossin /// use pin_init::{pin_data, pinned_drop, PinnedDrop};
37684837cf6SBenno Lossin ///
37784837cf6SBenno Lossin /// enum Command {
37884837cf6SBenno Lossin /// /* ... */
37984837cf6SBenno Lossin /// }
38084837cf6SBenno Lossin ///
3814b11798eSBenno Lossin /// #[pin_data(PinnedDrop)]
3824b11798eSBenno Lossin /// struct DriverData {
3834b11798eSBenno Lossin /// #[pin]
38484837cf6SBenno Lossin /// queue: CMutex<Vec<Command>>,
38584837cf6SBenno Lossin /// buf: Box<[u8; 1024 * 1024]>,
38684837cf6SBenno Lossin /// raw_info: *mut bindings::info,
3874b11798eSBenno Lossin /// }
3884b11798eSBenno Lossin ///
3894b11798eSBenno Lossin /// #[pinned_drop]
3904b11798eSBenno Lossin /// impl PinnedDrop for DriverData {
3914b11798eSBenno Lossin /// fn drop(self: Pin<&mut Self>) {
3924b11798eSBenno Lossin /// unsafe { bindings::destroy_info(self.raw_info) };
3934b11798eSBenno Lossin /// }
3944b11798eSBenno Lossin /// }
3954b11798eSBenno Lossin /// ```
396dbd5058bSBenno Lossin pub use ::pin_init_internal::pinned_drop;
3974b11798eSBenno Lossin
398*9de1a293SBenno Lossin /// Derives the [`Zeroable`] trait for the given `struct` or `union`.
3994b11798eSBenno Lossin ///
400*9de1a293SBenno Lossin /// This can only be used for `struct`s/`union`s where every field implements the [`Zeroable`]
401*9de1a293SBenno Lossin /// trait.
4024b11798eSBenno Lossin ///
4034b11798eSBenno Lossin /// # Examples
4044b11798eSBenno Lossin ///
4051ab10101SBenno Lossin /// ```
40684837cf6SBenno Lossin /// use pin_init::Zeroable;
4074b11798eSBenno Lossin ///
4084b11798eSBenno Lossin /// #[derive(Zeroable)]
4094b11798eSBenno Lossin /// pub struct DriverData {
410*9de1a293SBenno Lossin /// pub(crate) id: i64,
4114b11798eSBenno Lossin /// buf_ptr: *mut u8,
4124b11798eSBenno Lossin /// len: usize,
4134b11798eSBenno Lossin /// }
4144b11798eSBenno Lossin /// ```
415*9de1a293SBenno Lossin ///
416*9de1a293SBenno Lossin /// ```
417*9de1a293SBenno Lossin /// use pin_init::Zeroable;
418*9de1a293SBenno Lossin ///
419*9de1a293SBenno Lossin /// #[derive(Zeroable)]
420*9de1a293SBenno Lossin /// pub union SignCast {
421*9de1a293SBenno Lossin /// signed: i64,
422*9de1a293SBenno Lossin /// unsigned: u64,
423*9de1a293SBenno Lossin /// }
424*9de1a293SBenno Lossin /// ```
425dbd5058bSBenno Lossin pub use ::pin_init_internal::Zeroable;
4264b11798eSBenno Lossin
427*9de1a293SBenno Lossin /// Derives the [`Zeroable`] trait for the given `struct` or `union` if all fields implement
428*9de1a293SBenno Lossin /// [`Zeroable`].
42900fccd3eSBenno Lossin ///
43000fccd3eSBenno Lossin /// Contrary to the derive macro named [`macro@Zeroable`], this one silently fails when a field
43100fccd3eSBenno Lossin /// doesn't implement [`Zeroable`].
43200fccd3eSBenno Lossin ///
43300fccd3eSBenno Lossin /// # Examples
43400fccd3eSBenno Lossin ///
43500fccd3eSBenno Lossin /// ```
43600fccd3eSBenno Lossin /// use pin_init::MaybeZeroable;
43700fccd3eSBenno Lossin ///
43800fccd3eSBenno Lossin /// // implmements `Zeroable`
43900fccd3eSBenno Lossin /// #[derive(MaybeZeroable)]
44000fccd3eSBenno Lossin /// pub struct DriverData {
441*9de1a293SBenno Lossin /// pub(crate) id: i64,
44200fccd3eSBenno Lossin /// buf_ptr: *mut u8,
44300fccd3eSBenno Lossin /// len: usize,
44400fccd3eSBenno Lossin /// }
44500fccd3eSBenno Lossin ///
44600fccd3eSBenno Lossin /// // does not implmement `Zeroable`
44700fccd3eSBenno Lossin /// #[derive(MaybeZeroable)]
44800fccd3eSBenno Lossin /// pub struct DriverData2 {
449*9de1a293SBenno Lossin /// pub(crate) id: i64,
45000fccd3eSBenno Lossin /// buf_ptr: *mut u8,
45100fccd3eSBenno Lossin /// len: usize,
45200fccd3eSBenno Lossin /// // this field doesn't implement `Zeroable`
45300fccd3eSBenno Lossin /// other_data: &'static i32,
45400fccd3eSBenno Lossin /// }
45500fccd3eSBenno Lossin /// ```
45600fccd3eSBenno Lossin pub use ::pin_init_internal::MaybeZeroable;
45700fccd3eSBenno 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/mutex.rs"] mod mutex; use mutex::*;
46684837cf6SBenno Lossin /// # use pin_init::*;
467fbf8fb32SBenno Lossin /// # use core::pin::Pin;
468fbf8fb32SBenno Lossin /// #[pin_data]
469fbf8fb32SBenno Lossin /// struct Foo {
470fbf8fb32SBenno Lossin /// #[pin]
47184837cf6SBenno Lossin /// a: CMutex<usize>,
472fbf8fb32SBenno Lossin /// b: Bar,
473fbf8fb32SBenno Lossin /// }
474fbf8fb32SBenno Lossin ///
475fbf8fb32SBenno Lossin /// #[pin_data]
476fbf8fb32SBenno Lossin /// struct Bar {
477fbf8fb32SBenno Lossin /// x: u32,
478fbf8fb32SBenno Lossin /// }
479fbf8fb32SBenno Lossin ///
480fbf8fb32SBenno Lossin /// stack_pin_init!(let foo = pin_init!(Foo {
48184837cf6SBenno Lossin /// a <- CMutex::new(42),
482fbf8fb32SBenno Lossin /// b: Bar {
483fbf8fb32SBenno Lossin /// x: 64,
484fbf8fb32SBenno Lossin /// },
485fbf8fb32SBenno Lossin /// }));
486fbf8fb32SBenno Lossin /// let foo: Pin<&mut Foo> = foo;
48784837cf6SBenno Lossin /// println!("a: {}", &*foo.a.lock());
488fbf8fb32SBenno Lossin /// ```
489fbf8fb32SBenno Lossin ///
490fbf8fb32SBenno Lossin /// # Syntax
491fbf8fb32SBenno Lossin ///
492fbf8fb32SBenno Lossin /// A normal `let` binding with optional type annotation. The expression is expected to implement
493fbf8fb32SBenno Lossin /// [`PinInit`]/[`Init`] with the error type [`Infallible`]. If you want to use a different error
494fbf8fb32SBenno Lossin /// type, then use [`stack_try_pin_init!`].
495fbf8fb32SBenno Lossin #[macro_export]
496fbf8fb32SBenno Lossin macro_rules! stack_pin_init {
497fbf8fb32SBenno Lossin (let $var:ident $(: $t:ty)? = $val:expr) => {
498fbf8fb32SBenno Lossin let val = $val;
499dbd5058bSBenno Lossin let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
500dbd5058bSBenno Lossin let mut $var = match $crate::__internal::StackInit::init($var, val) {
501fbf8fb32SBenno Lossin Ok(res) => res,
502fbf8fb32SBenno Lossin Err(x) => {
503fbf8fb32SBenno Lossin let x: ::core::convert::Infallible = x;
504fbf8fb32SBenno Lossin match x {}
505fbf8fb32SBenno Lossin }
506fbf8fb32SBenno Lossin };
507fbf8fb32SBenno Lossin };
508fbf8fb32SBenno Lossin }
509fbf8fb32SBenno Lossin
510fbf8fb32SBenno Lossin /// Initialize and pin a type directly on the stack.
511fbf8fb32SBenno Lossin ///
512fbf8fb32SBenno Lossin /// # Examples
513fbf8fb32SBenno Lossin ///
5141ab10101SBenno Lossin /// ```rust
515fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
51684837cf6SBenno Lossin /// # #![feature(allocator_api)]
51784837cf6SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
51884837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
51984837cf6SBenno Lossin /// # use pin_init::*;
520fbf8fb32SBenno Lossin /// #[pin_data]
521fbf8fb32SBenno Lossin /// struct Foo {
522fbf8fb32SBenno Lossin /// #[pin]
52384837cf6SBenno Lossin /// a: CMutex<usize>,
52484837cf6SBenno Lossin /// b: Box<Bar>,
525fbf8fb32SBenno Lossin /// }
526fbf8fb32SBenno Lossin ///
527fbf8fb32SBenno Lossin /// struct Bar {
528fbf8fb32SBenno Lossin /// x: u32,
529fbf8fb32SBenno Lossin /// }
530fbf8fb32SBenno Lossin ///
53184837cf6SBenno Lossin /// stack_try_pin_init!(let foo: Foo = try_pin_init!(Foo {
53284837cf6SBenno Lossin /// a <- CMutex::new(42),
53384837cf6SBenno Lossin /// b: Box::try_new(Bar {
534fbf8fb32SBenno Lossin /// x: 64,
53584837cf6SBenno Lossin /// })?,
53684837cf6SBenno Lossin /// }? Error));
537fbf8fb32SBenno Lossin /// let foo = foo.unwrap();
53884837cf6SBenno Lossin /// println!("a: {}", &*foo.a.lock());
539fbf8fb32SBenno Lossin /// ```
540fbf8fb32SBenno Lossin ///
5411ab10101SBenno Lossin /// ```rust
542fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
54384837cf6SBenno Lossin /// # #![feature(allocator_api)]
54484837cf6SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
54584837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
54684837cf6SBenno Lossin /// # use pin_init::*;
547fbf8fb32SBenno Lossin /// #[pin_data]
548fbf8fb32SBenno Lossin /// struct Foo {
549fbf8fb32SBenno Lossin /// #[pin]
55084837cf6SBenno Lossin /// a: CMutex<usize>,
55184837cf6SBenno Lossin /// b: Box<Bar>,
552fbf8fb32SBenno Lossin /// }
553fbf8fb32SBenno Lossin ///
554fbf8fb32SBenno Lossin /// struct Bar {
555fbf8fb32SBenno Lossin /// x: u32,
556fbf8fb32SBenno Lossin /// }
557fbf8fb32SBenno Lossin ///
55884837cf6SBenno Lossin /// stack_try_pin_init!(let foo: Foo =? try_pin_init!(Foo {
55984837cf6SBenno Lossin /// a <- CMutex::new(42),
56084837cf6SBenno Lossin /// b: Box::try_new(Bar {
561fbf8fb32SBenno Lossin /// x: 64,
56284837cf6SBenno Lossin /// })?,
56384837cf6SBenno Lossin /// }? Error));
56484837cf6SBenno Lossin /// println!("a: {}", &*foo.a.lock());
56584837cf6SBenno Lossin /// # Ok::<_, Error>(())
566fbf8fb32SBenno Lossin /// ```
567fbf8fb32SBenno Lossin ///
568fbf8fb32SBenno Lossin /// # Syntax
569fbf8fb32SBenno Lossin ///
570fbf8fb32SBenno Lossin /// A normal `let` binding with optional type annotation. The expression is expected to implement
571fbf8fb32SBenno Lossin /// [`PinInit`]/[`Init`]. This macro assigns a result to the given variable, adding a `?` after the
572fbf8fb32SBenno Lossin /// `=` will propagate this error.
573fbf8fb32SBenno Lossin #[macro_export]
574fbf8fb32SBenno Lossin macro_rules! stack_try_pin_init {
575fbf8fb32SBenno Lossin (let $var:ident $(: $t:ty)? = $val:expr) => {
576fbf8fb32SBenno Lossin let val = $val;
577dbd5058bSBenno Lossin let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
578dbd5058bSBenno Lossin let mut $var = $crate::__internal::StackInit::init($var, val);
579fbf8fb32SBenno Lossin };
580fbf8fb32SBenno Lossin (let $var:ident $(: $t:ty)? =? $val:expr) => {
581fbf8fb32SBenno Lossin let val = $val;
582dbd5058bSBenno Lossin let mut $var = ::core::pin::pin!($crate::__internal::StackInit$(::<$t>)?::uninit());
583dbd5058bSBenno Lossin let mut $var = $crate::__internal::StackInit::init($var, val)?;
584fbf8fb32SBenno Lossin };
585fbf8fb32SBenno Lossin }
586fbf8fb32SBenno Lossin
587fbf8fb32SBenno Lossin /// Construct an in-place, pinned initializer for `struct`s.
588fbf8fb32SBenno Lossin ///
589578eb8b6SBenno Lossin /// This macro defaults the error to [`Infallible`]. If you need a different error, then use
590fbf8fb32SBenno Lossin /// [`try_pin_init!`].
591fbf8fb32SBenno Lossin ///
592fbf8fb32SBenno Lossin /// The syntax is almost identical to that of a normal `struct` initializer:
593fbf8fb32SBenno Lossin ///
5941ab10101SBenno Lossin /// ```rust
59584837cf6SBenno Lossin /// # use pin_init::*;
596fbf8fb32SBenno Lossin /// # use core::pin::Pin;
597fbf8fb32SBenno Lossin /// #[pin_data]
598fbf8fb32SBenno Lossin /// struct Foo {
599fbf8fb32SBenno Lossin /// a: usize,
600fbf8fb32SBenno Lossin /// b: Bar,
601fbf8fb32SBenno Lossin /// }
602fbf8fb32SBenno Lossin ///
603fbf8fb32SBenno Lossin /// #[pin_data]
604fbf8fb32SBenno Lossin /// struct Bar {
605fbf8fb32SBenno Lossin /// x: u32,
606fbf8fb32SBenno Lossin /// }
607fbf8fb32SBenno Lossin ///
608fbf8fb32SBenno Lossin /// # fn demo() -> impl PinInit<Foo> {
609fbf8fb32SBenno Lossin /// let a = 42;
610fbf8fb32SBenno Lossin ///
611fbf8fb32SBenno Lossin /// let initializer = pin_init!(Foo {
612fbf8fb32SBenno Lossin /// a,
613fbf8fb32SBenno Lossin /// b: Bar {
614fbf8fb32SBenno Lossin /// x: 64,
615fbf8fb32SBenno Lossin /// },
616fbf8fb32SBenno Lossin /// });
617fbf8fb32SBenno Lossin /// # initializer }
61884837cf6SBenno Lossin /// # Box::pin_init(demo()).unwrap();
619fbf8fb32SBenno Lossin /// ```
620fbf8fb32SBenno Lossin ///
621fbf8fb32SBenno Lossin /// Arbitrary Rust expressions can be used to set the value of a variable.
622fbf8fb32SBenno Lossin ///
623fbf8fb32SBenno Lossin /// The fields are initialized in the order that they appear in the initializer. So it is possible
624fbf8fb32SBenno Lossin /// to read already initialized fields using raw pointers.
625fbf8fb32SBenno Lossin ///
626fbf8fb32SBenno Lossin /// IMPORTANT: You are not allowed to create references to fields of the struct inside of the
627fbf8fb32SBenno Lossin /// initializer.
628fbf8fb32SBenno Lossin ///
629fbf8fb32SBenno Lossin /// # Init-functions
630fbf8fb32SBenno Lossin ///
63102c01c08SBenno Lossin /// When working with this library it is often desired to let others construct your types without
63202c01c08SBenno Lossin /// giving access to all fields. This is where you would normally write a plain function `new` that
63302c01c08SBenno Lossin /// would return a new instance of your type. With this library that is also possible. However,
63402c01c08SBenno Lossin /// there are a few extra things to keep in mind.
635fbf8fb32SBenno Lossin ///
636fbf8fb32SBenno Lossin /// To create an initializer function, simply declare it like this:
637fbf8fb32SBenno Lossin ///
6381ab10101SBenno Lossin /// ```rust
63984837cf6SBenno Lossin /// # use pin_init::*;
640fbf8fb32SBenno Lossin /// # use core::pin::Pin;
641fbf8fb32SBenno Lossin /// # #[pin_data]
642fbf8fb32SBenno Lossin /// # struct Foo {
643fbf8fb32SBenno Lossin /// # a: usize,
644fbf8fb32SBenno Lossin /// # b: Bar,
645fbf8fb32SBenno Lossin /// # }
646fbf8fb32SBenno Lossin /// # #[pin_data]
647fbf8fb32SBenno Lossin /// # struct Bar {
648fbf8fb32SBenno Lossin /// # x: u32,
649fbf8fb32SBenno Lossin /// # }
650fbf8fb32SBenno Lossin /// impl Foo {
651fbf8fb32SBenno Lossin /// fn new() -> impl PinInit<Self> {
652fbf8fb32SBenno Lossin /// pin_init!(Self {
653fbf8fb32SBenno Lossin /// a: 42,
654fbf8fb32SBenno Lossin /// b: Bar {
655fbf8fb32SBenno Lossin /// x: 64,
656fbf8fb32SBenno Lossin /// },
657fbf8fb32SBenno Lossin /// })
658fbf8fb32SBenno Lossin /// }
659fbf8fb32SBenno Lossin /// }
660fbf8fb32SBenno Lossin /// ```
661fbf8fb32SBenno Lossin ///
662fbf8fb32SBenno Lossin /// Users of `Foo` can now create it like this:
663fbf8fb32SBenno Lossin ///
6641ab10101SBenno Lossin /// ```rust
665fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
66684837cf6SBenno Lossin /// # use pin_init::*;
667fbf8fb32SBenno Lossin /// # use core::pin::Pin;
668fbf8fb32SBenno Lossin /// # #[pin_data]
669fbf8fb32SBenno Lossin /// # struct Foo {
670fbf8fb32SBenno Lossin /// # a: usize,
671fbf8fb32SBenno Lossin /// # b: Bar,
672fbf8fb32SBenno Lossin /// # }
673fbf8fb32SBenno Lossin /// # #[pin_data]
674fbf8fb32SBenno Lossin /// # struct Bar {
675fbf8fb32SBenno Lossin /// # x: u32,
676fbf8fb32SBenno Lossin /// # }
677fbf8fb32SBenno Lossin /// # impl Foo {
678fbf8fb32SBenno Lossin /// # fn new() -> impl PinInit<Self> {
679fbf8fb32SBenno Lossin /// # pin_init!(Self {
680fbf8fb32SBenno Lossin /// # a: 42,
681fbf8fb32SBenno Lossin /// # b: Bar {
682fbf8fb32SBenno Lossin /// # x: 64,
683fbf8fb32SBenno Lossin /// # },
684fbf8fb32SBenno Lossin /// # })
685fbf8fb32SBenno Lossin /// # }
686fbf8fb32SBenno Lossin /// # }
68784837cf6SBenno Lossin /// let foo = Box::pin_init(Foo::new());
688fbf8fb32SBenno Lossin /// ```
689fbf8fb32SBenno Lossin ///
690fbf8fb32SBenno Lossin /// They can also easily embed it into their own `struct`s:
691fbf8fb32SBenno Lossin ///
6921ab10101SBenno Lossin /// ```rust
69384837cf6SBenno Lossin /// # use pin_init::*;
694fbf8fb32SBenno Lossin /// # use core::pin::Pin;
695fbf8fb32SBenno Lossin /// # #[pin_data]
696fbf8fb32SBenno Lossin /// # struct Foo {
697fbf8fb32SBenno Lossin /// # a: usize,
698fbf8fb32SBenno Lossin /// # b: Bar,
699fbf8fb32SBenno Lossin /// # }
700fbf8fb32SBenno Lossin /// # #[pin_data]
701fbf8fb32SBenno Lossin /// # struct Bar {
702fbf8fb32SBenno Lossin /// # x: u32,
703fbf8fb32SBenno Lossin /// # }
704fbf8fb32SBenno Lossin /// # impl Foo {
705fbf8fb32SBenno Lossin /// # fn new() -> impl PinInit<Self> {
706fbf8fb32SBenno Lossin /// # pin_init!(Self {
707fbf8fb32SBenno Lossin /// # a: 42,
708fbf8fb32SBenno Lossin /// # b: Bar {
709fbf8fb32SBenno Lossin /// # x: 64,
710fbf8fb32SBenno Lossin /// # },
711fbf8fb32SBenno Lossin /// # })
712fbf8fb32SBenno Lossin /// # }
713fbf8fb32SBenno Lossin /// # }
714fbf8fb32SBenno Lossin /// #[pin_data]
715fbf8fb32SBenno Lossin /// struct FooContainer {
716fbf8fb32SBenno Lossin /// #[pin]
717fbf8fb32SBenno Lossin /// foo1: Foo,
718fbf8fb32SBenno Lossin /// #[pin]
719fbf8fb32SBenno Lossin /// foo2: Foo,
720fbf8fb32SBenno Lossin /// other: u32,
721fbf8fb32SBenno Lossin /// }
722fbf8fb32SBenno Lossin ///
723fbf8fb32SBenno Lossin /// impl FooContainer {
724fbf8fb32SBenno Lossin /// fn new(other: u32) -> impl PinInit<Self> {
725fbf8fb32SBenno Lossin /// pin_init!(Self {
726fbf8fb32SBenno Lossin /// foo1 <- Foo::new(),
727fbf8fb32SBenno Lossin /// foo2 <- Foo::new(),
728fbf8fb32SBenno Lossin /// other,
729fbf8fb32SBenno Lossin /// })
730fbf8fb32SBenno Lossin /// }
731fbf8fb32SBenno Lossin /// }
732fbf8fb32SBenno Lossin /// ```
733fbf8fb32SBenno Lossin ///
734fbf8fb32SBenno Lossin /// Here we see that when using `pin_init!` with `PinInit`, one needs to write `<-` instead of `:`.
735fbf8fb32SBenno Lossin /// This signifies that the given field is initialized in-place. As with `struct` initializers, just
736fbf8fb32SBenno Lossin /// writing the field (in this case `other`) without `:` or `<-` means `other: other,`.
737fbf8fb32SBenno Lossin ///
738fbf8fb32SBenno Lossin /// # Syntax
739fbf8fb32SBenno Lossin ///
740fbf8fb32SBenno Lossin /// As already mentioned in the examples above, inside of `pin_init!` a `struct` initializer with
741fbf8fb32SBenno Lossin /// the following modifications is expected:
742fbf8fb32SBenno Lossin /// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
743fbf8fb32SBenno Lossin /// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
744fbf8fb32SBenno Lossin /// pointer named `this` inside of the initializer.
745fbf8fb32SBenno Lossin /// - Using struct update syntax one can place `..Zeroable::zeroed()` at the very end of the
746fbf8fb32SBenno Lossin /// struct, this initializes every field with 0 and then runs all initializers specified in the
747fbf8fb32SBenno Lossin /// body. This can only be done if [`Zeroable`] is implemented for the struct.
748fbf8fb32SBenno Lossin ///
749fbf8fb32SBenno Lossin /// For instance:
750fbf8fb32SBenno Lossin ///
7511ab10101SBenno Lossin /// ```rust
75284837cf6SBenno Lossin /// # use pin_init::*;
753fbf8fb32SBenno Lossin /// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
754fbf8fb32SBenno Lossin /// #[pin_data]
755fbf8fb32SBenno Lossin /// #[derive(Zeroable)]
756fbf8fb32SBenno Lossin /// struct Buf {
757fbf8fb32SBenno Lossin /// // `ptr` points into `buf`.
758fbf8fb32SBenno Lossin /// ptr: *mut u8,
759fbf8fb32SBenno Lossin /// buf: [u8; 64],
760fbf8fb32SBenno Lossin /// #[pin]
761fbf8fb32SBenno Lossin /// pin: PhantomPinned,
762fbf8fb32SBenno Lossin /// }
76302c01c08SBenno Lossin ///
76402c01c08SBenno Lossin /// let init = pin_init!(&this in Buf {
765fbf8fb32SBenno Lossin /// buf: [0; 64],
766fbf8fb32SBenno Lossin /// // SAFETY: TODO.
767fbf8fb32SBenno Lossin /// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
768fbf8fb32SBenno Lossin /// pin: PhantomPinned,
769fbf8fb32SBenno Lossin /// });
77002c01c08SBenno Lossin /// let init = pin_init!(Buf {
771fbf8fb32SBenno Lossin /// buf: [1; 64],
772fbf8fb32SBenno Lossin /// ..Zeroable::zeroed()
773fbf8fb32SBenno Lossin /// });
774fbf8fb32SBenno Lossin /// ```
775fbf8fb32SBenno Lossin ///
776fbf8fb32SBenno Lossin /// [`NonNull<Self>`]: core::ptr::NonNull
777fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
77802c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
779fbf8fb32SBenno Lossin #[macro_export]
780fbf8fb32SBenno Lossin macro_rules! pin_init {
781fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
782fbf8fb32SBenno Lossin $($fields:tt)*
783fbf8fb32SBenno Lossin }) => {
784dbd5058bSBenno Lossin $crate::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
785c2ddbdbbSBenno Lossin $($fields)*
786c2ddbdbbSBenno Lossin }? ::core::convert::Infallible)
787fbf8fb32SBenno Lossin };
788fbf8fb32SBenno Lossin }
789fbf8fb32SBenno Lossin
790fbf8fb32SBenno Lossin /// Construct an in-place, fallible pinned initializer for `struct`s.
791fbf8fb32SBenno Lossin ///
792fbf8fb32SBenno Lossin /// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
793fbf8fb32SBenno Lossin ///
794fbf8fb32SBenno Lossin /// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
795fbf8fb32SBenno Lossin /// initialization and return the error.
796fbf8fb32SBenno Lossin ///
797fbf8fb32SBenno Lossin /// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
798fbf8fb32SBenno Lossin /// initialization fails, the memory can be safely deallocated without any further modifications.
799fbf8fb32SBenno Lossin ///
800578eb8b6SBenno Lossin /// The syntax is identical to [`pin_init!`] with the following exception: you must append `? $type`
801fbf8fb32SBenno Lossin /// after the `struct` initializer to specify the error type you want to use.
802fbf8fb32SBenno Lossin ///
803fbf8fb32SBenno Lossin /// # Examples
804fbf8fb32SBenno Lossin ///
8051ab10101SBenno Lossin /// ```rust
80684837cf6SBenno Lossin /// # #![feature(allocator_api)]
80784837cf6SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
80802c01c08SBenno Lossin /// use pin_init::{pin_data, try_pin_init, PinInit, InPlaceInit, zeroed};
80902c01c08SBenno Lossin ///
810fbf8fb32SBenno Lossin /// #[pin_data]
811fbf8fb32SBenno Lossin /// struct BigBuf {
81284837cf6SBenno Lossin /// big: Box<[u8; 1024 * 1024 * 1024]>,
813fbf8fb32SBenno Lossin /// small: [u8; 1024 * 1024],
814fbf8fb32SBenno Lossin /// ptr: *mut u8,
815fbf8fb32SBenno Lossin /// }
816fbf8fb32SBenno Lossin ///
817fbf8fb32SBenno Lossin /// impl BigBuf {
818fbf8fb32SBenno Lossin /// fn new() -> impl PinInit<Self, Error> {
819fbf8fb32SBenno Lossin /// try_pin_init!(Self {
82002c01c08SBenno Lossin /// big: Box::init(zeroed())?,
821fbf8fb32SBenno Lossin /// small: [0; 1024 * 1024],
822fbf8fb32SBenno Lossin /// ptr: core::ptr::null_mut(),
823fbf8fb32SBenno Lossin /// }? Error)
824fbf8fb32SBenno Lossin /// }
825fbf8fb32SBenno Lossin /// }
82684837cf6SBenno Lossin /// # let _ = Box::pin_init(BigBuf::new());
827fbf8fb32SBenno Lossin /// ```
828fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
82902c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
830fbf8fb32SBenno Lossin #[macro_export]
831dbd5058bSBenno Lossin macro_rules! try_pin_init {
832fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
833fbf8fb32SBenno Lossin $($fields:tt)*
834fbf8fb32SBenno Lossin }? $err:ty) => {
835fbf8fb32SBenno Lossin $crate::__init_internal!(
836fbf8fb32SBenno Lossin @this($($this)?),
837fbf8fb32SBenno Lossin @typ($t $(::<$($generics),*>)? ),
838fbf8fb32SBenno Lossin @fields($($fields)*),
839fbf8fb32SBenno Lossin @error($err),
840fbf8fb32SBenno Lossin @data(PinData, use_data),
841fbf8fb32SBenno Lossin @has_data(HasPinData, __pin_data),
842fbf8fb32SBenno Lossin @construct_closure(pin_init_from_closure),
843fbf8fb32SBenno Lossin @munch_fields($($fields)*),
844fbf8fb32SBenno Lossin )
845578eb8b6SBenno Lossin }
846fbf8fb32SBenno Lossin }
847fbf8fb32SBenno Lossin
848fbf8fb32SBenno Lossin /// Construct an in-place initializer for `struct`s.
849fbf8fb32SBenno Lossin ///
850578eb8b6SBenno Lossin /// This macro defaults the error to [`Infallible`]. If you need a different error, then use
851fbf8fb32SBenno Lossin /// [`try_init!`].
852fbf8fb32SBenno Lossin ///
853fbf8fb32SBenno Lossin /// The syntax is identical to [`pin_init!`] and its safety caveats also apply:
854fbf8fb32SBenno Lossin /// - `unsafe` code must guarantee either full initialization or return an error and allow
855fbf8fb32SBenno Lossin /// deallocation of the memory.
856fbf8fb32SBenno Lossin /// - the fields are initialized in the order given in the initializer.
857fbf8fb32SBenno Lossin /// - no references to fields are allowed to be created inside of the initializer.
858fbf8fb32SBenno Lossin ///
859fbf8fb32SBenno Lossin /// This initializer is for initializing data in-place that might later be moved. If you want to
860fbf8fb32SBenno Lossin /// pin-initialize, use [`pin_init!`].
861fbf8fb32SBenno Lossin ///
86202c01c08SBenno Lossin /// # Examples
86302c01c08SBenno Lossin ///
86402c01c08SBenno Lossin /// ```rust
86502c01c08SBenno Lossin /// # #![feature(allocator_api)]
86602c01c08SBenno Lossin /// # #[path = "../examples/error.rs"] mod error; use error::Error;
86702c01c08SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
86802c01c08SBenno Lossin /// # use pin_init::InPlaceInit;
86902c01c08SBenno Lossin /// use pin_init::{init, Init, zeroed};
87002c01c08SBenno Lossin ///
87102c01c08SBenno Lossin /// struct BigBuf {
87202c01c08SBenno Lossin /// small: [u8; 1024 * 1024],
87302c01c08SBenno Lossin /// }
87402c01c08SBenno Lossin ///
87502c01c08SBenno Lossin /// impl BigBuf {
87602c01c08SBenno Lossin /// fn new() -> impl Init<Self> {
87702c01c08SBenno Lossin /// init!(Self {
87802c01c08SBenno Lossin /// small <- zeroed(),
87902c01c08SBenno Lossin /// })
88002c01c08SBenno Lossin /// }
88102c01c08SBenno Lossin /// }
88202c01c08SBenno Lossin /// # let _ = Box::init(BigBuf::new());
88302c01c08SBenno Lossin /// ```
884fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
88502c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
886fbf8fb32SBenno Lossin #[macro_export]
887fbf8fb32SBenno Lossin macro_rules! init {
888fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
889fbf8fb32SBenno Lossin $($fields:tt)*
890fbf8fb32SBenno Lossin }) => {
891dbd5058bSBenno Lossin $crate::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
892c2ddbdbbSBenno Lossin $($fields)*
893c2ddbdbbSBenno Lossin }? ::core::convert::Infallible)
894fbf8fb32SBenno Lossin }
895fbf8fb32SBenno Lossin }
896fbf8fb32SBenno Lossin
897fbf8fb32SBenno Lossin /// Construct an in-place fallible initializer for `struct`s.
898fbf8fb32SBenno Lossin ///
899578eb8b6SBenno Lossin /// If the initialization can complete without error (or [`Infallible`]), then use
900fbf8fb32SBenno Lossin /// [`init!`].
901fbf8fb32SBenno Lossin ///
902578eb8b6SBenno Lossin /// The syntax is identical to [`try_pin_init!`]. You need to specify a custom error
903578eb8b6SBenno Lossin /// via `? $type` after the `struct` initializer.
904fbf8fb32SBenno Lossin /// The safety caveats from [`try_pin_init!`] also apply:
905fbf8fb32SBenno Lossin /// - `unsafe` code must guarantee either full initialization or return an error and allow
906fbf8fb32SBenno Lossin /// deallocation of the memory.
907fbf8fb32SBenno Lossin /// - the fields are initialized in the order given in the initializer.
908fbf8fb32SBenno Lossin /// - no references to fields are allowed to be created inside of the initializer.
909fbf8fb32SBenno Lossin ///
910fbf8fb32SBenno Lossin /// # Examples
911fbf8fb32SBenno Lossin ///
9121ab10101SBenno Lossin /// ```rust
91384837cf6SBenno Lossin /// # #![feature(allocator_api)]
91484837cf6SBenno Lossin /// # use core::alloc::AllocError;
91502c01c08SBenno Lossin /// # use pin_init::InPlaceInit;
91602c01c08SBenno Lossin /// use pin_init::{try_init, Init, zeroed};
91702c01c08SBenno Lossin ///
918fbf8fb32SBenno Lossin /// struct BigBuf {
91984837cf6SBenno Lossin /// big: Box<[u8; 1024 * 1024 * 1024]>,
920fbf8fb32SBenno Lossin /// small: [u8; 1024 * 1024],
921fbf8fb32SBenno Lossin /// }
922fbf8fb32SBenno Lossin ///
923fbf8fb32SBenno Lossin /// impl BigBuf {
92484837cf6SBenno Lossin /// fn new() -> impl Init<Self, AllocError> {
925fbf8fb32SBenno Lossin /// try_init!(Self {
92684837cf6SBenno Lossin /// big: Box::init(zeroed())?,
927fbf8fb32SBenno Lossin /// small: [0; 1024 * 1024],
92884837cf6SBenno Lossin /// }? AllocError)
929fbf8fb32SBenno Lossin /// }
930fbf8fb32SBenno Lossin /// }
93102c01c08SBenno Lossin /// # let _ = Box::init(BigBuf::new());
932fbf8fb32SBenno Lossin /// ```
933fbf8fb32SBenno Lossin // For a detailed example of how this macro works, see the module documentation of the hidden
93402c01c08SBenno Lossin // module `macros` inside of `macros.rs`.
935fbf8fb32SBenno Lossin #[macro_export]
936dbd5058bSBenno Lossin macro_rules! try_init {
937fbf8fb32SBenno Lossin ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
938fbf8fb32SBenno Lossin $($fields:tt)*
939fbf8fb32SBenno Lossin }? $err:ty) => {
940fbf8fb32SBenno Lossin $crate::__init_internal!(
941fbf8fb32SBenno Lossin @this($($this)?),
942fbf8fb32SBenno Lossin @typ($t $(::<$($generics),*>)?),
943fbf8fb32SBenno Lossin @fields($($fields)*),
944fbf8fb32SBenno Lossin @error($err),
945fbf8fb32SBenno Lossin @data(InitData, /*no use_data*/),
946fbf8fb32SBenno Lossin @has_data(HasInitData, __init_data),
947fbf8fb32SBenno Lossin @construct_closure(init_from_closure),
948fbf8fb32SBenno Lossin @munch_fields($($fields)*),
949fbf8fb32SBenno Lossin )
950578eb8b6SBenno Lossin }
951fbf8fb32SBenno Lossin }
952fbf8fb32SBenno Lossin
953fbf8fb32SBenno Lossin /// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is
954fbf8fb32SBenno Lossin /// structurally pinned.
955fbf8fb32SBenno Lossin ///
956fbf8fb32SBenno Lossin /// # Example
957fbf8fb32SBenno Lossin ///
958fbf8fb32SBenno Lossin /// This will succeed:
9591ab10101SBenno Lossin /// ```
96002c01c08SBenno Lossin /// use pin_init::{pin_data, assert_pinned};
96102c01c08SBenno Lossin ///
962fbf8fb32SBenno Lossin /// #[pin_data]
963fbf8fb32SBenno Lossin /// struct MyStruct {
964fbf8fb32SBenno Lossin /// #[pin]
965fbf8fb32SBenno Lossin /// some_field: u64,
966fbf8fb32SBenno Lossin /// }
967fbf8fb32SBenno Lossin ///
968fbf8fb32SBenno Lossin /// assert_pinned!(MyStruct, some_field, u64);
969fbf8fb32SBenno Lossin /// ```
970fbf8fb32SBenno Lossin ///
971fbf8fb32SBenno Lossin /// This will fail:
9721ab10101SBenno Lossin /// ```compile_fail
97302c01c08SBenno Lossin /// use pin_init::{pin_data, assert_pinned};
97402c01c08SBenno Lossin ///
975fbf8fb32SBenno Lossin /// #[pin_data]
976fbf8fb32SBenno Lossin /// struct MyStruct {
977fbf8fb32SBenno Lossin /// some_field: u64,
978fbf8fb32SBenno Lossin /// }
979fbf8fb32SBenno Lossin ///
980fbf8fb32SBenno Lossin /// assert_pinned!(MyStruct, some_field, u64);
981fbf8fb32SBenno Lossin /// ```
982fbf8fb32SBenno Lossin ///
983fbf8fb32SBenno Lossin /// Some uses of the macro may trigger the `can't use generic parameters from outer item` error. To
984fbf8fb32SBenno Lossin /// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
985fbf8fb32SBenno Lossin /// only be used when the macro is invoked from a function body.
9861ab10101SBenno Lossin /// ```
98702c01c08SBenno Lossin /// # use core::pin::Pin;
98802c01c08SBenno Lossin /// use pin_init::{pin_data, assert_pinned};
98902c01c08SBenno Lossin ///
990fbf8fb32SBenno Lossin /// #[pin_data]
991fbf8fb32SBenno Lossin /// struct Foo<T> {
992fbf8fb32SBenno Lossin /// #[pin]
993fbf8fb32SBenno Lossin /// elem: T,
994fbf8fb32SBenno Lossin /// }
995fbf8fb32SBenno Lossin ///
996fbf8fb32SBenno Lossin /// impl<T> Foo<T> {
997fbf8fb32SBenno Lossin /// fn project(self: Pin<&mut Self>) -> Pin<&mut T> {
998fbf8fb32SBenno Lossin /// assert_pinned!(Foo<T>, elem, T, inline);
999fbf8fb32SBenno Lossin ///
1000fbf8fb32SBenno Lossin /// // SAFETY: The field is structurally pinned.
1001fbf8fb32SBenno Lossin /// unsafe { self.map_unchecked_mut(|me| &mut me.elem) }
1002fbf8fb32SBenno Lossin /// }
1003fbf8fb32SBenno Lossin /// }
1004fbf8fb32SBenno Lossin /// ```
1005fbf8fb32SBenno Lossin #[macro_export]
1006fbf8fb32SBenno Lossin macro_rules! assert_pinned {
1007fbf8fb32SBenno Lossin ($ty:ty, $field:ident, $field_ty:ty, inline) => {
1008fbf8fb32SBenno Lossin let _ = move |ptr: *mut $field_ty| {
1009fbf8fb32SBenno Lossin // SAFETY: This code is unreachable.
1010dbd5058bSBenno Lossin let data = unsafe { <$ty as $crate::__internal::HasPinData>::__pin_data() };
1011dbd5058bSBenno Lossin let init = $crate::__internal::AlwaysFail::<$field_ty>::new();
1012fbf8fb32SBenno Lossin // SAFETY: This code is unreachable.
1013fbf8fb32SBenno Lossin unsafe { data.$field(ptr, init) }.ok();
1014fbf8fb32SBenno Lossin };
1015fbf8fb32SBenno Lossin };
1016fbf8fb32SBenno Lossin
1017fbf8fb32SBenno Lossin ($ty:ty, $field:ident, $field_ty:ty) => {
1018fbf8fb32SBenno Lossin const _: () = {
1019fbf8fb32SBenno Lossin $crate::assert_pinned!($ty, $field, $field_ty, inline);
1020fbf8fb32SBenno Lossin };
1021fbf8fb32SBenno Lossin };
1022fbf8fb32SBenno Lossin }
1023fbf8fb32SBenno Lossin
1024fbf8fb32SBenno Lossin /// A pin-initializer for the type `T`.
1025fbf8fb32SBenno Lossin ///
1026fbf8fb32SBenno Lossin /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
1027129e97beSBenno Lossin /// be [`Box<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]).
1028fbf8fb32SBenno Lossin ///
1029fbf8fb32SBenno Lossin /// Also see the [module description](self).
1030fbf8fb32SBenno Lossin ///
1031fbf8fb32SBenno Lossin /// # Safety
1032fbf8fb32SBenno Lossin ///
1033fbf8fb32SBenno Lossin /// When implementing this trait you will need to take great care. Also there are probably very few
1034fbf8fb32SBenno Lossin /// cases where a manual implementation is necessary. Use [`pin_init_from_closure`] where possible.
1035fbf8fb32SBenno Lossin ///
1036fbf8fb32SBenno Lossin /// The [`PinInit::__pinned_init`] function:
1037fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
1038fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
1039fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
1040fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
1041fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
1042fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
1043fbf8fb32SBenno Lossin ///
10449b2299afSBenno Lossin #[cfg_attr(
10459b2299afSBenno Lossin kernel,
10469b2299afSBenno Lossin doc = "[`Arc<T>`]: https://rust.docs.kernel.org/kernel/sync/struct.Arc.html"
10479b2299afSBenno Lossin )]
10489b2299afSBenno Lossin #[cfg_attr(
10499b2299afSBenno Lossin kernel,
10509b2299afSBenno Lossin doc = "[`Box<T>`]: https://rust.docs.kernel.org/kernel/alloc/kbox/struct.Box.html"
10519b2299afSBenno Lossin )]
10529b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
10539b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
1054fbf8fb32SBenno Lossin #[must_use = "An initializer must be used in order to create its value."]
1055fbf8fb32SBenno Lossin pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
1056fbf8fb32SBenno Lossin /// Initializes `slot`.
1057fbf8fb32SBenno Lossin ///
1058fbf8fb32SBenno Lossin /// # Safety
1059fbf8fb32SBenno Lossin ///
1060fbf8fb32SBenno Lossin /// - `slot` is a valid pointer to uninitialized memory.
1061fbf8fb32SBenno Lossin /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
1062fbf8fb32SBenno Lossin /// deallocate.
1063fbf8fb32SBenno Lossin /// - `slot` will not move until it is dropped, i.e. it will be pinned.
__pinned_init(self, slot: *mut T) -> Result<(), E>1064fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>;
1065fbf8fb32SBenno Lossin
1066fbf8fb32SBenno Lossin /// First initializes the value using `self` then calls the function `f` with the initialized
1067fbf8fb32SBenno Lossin /// value.
1068fbf8fb32SBenno Lossin ///
1069fbf8fb32SBenno Lossin /// If `f` returns an error the value is dropped and the initializer will forward the error.
1070fbf8fb32SBenno Lossin ///
1071fbf8fb32SBenno Lossin /// # Examples
1072fbf8fb32SBenno Lossin ///
10731ab10101SBenno Lossin /// ```rust
107484837cf6SBenno Lossin /// # #![feature(allocator_api)]
107584837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
107684837cf6SBenno Lossin /// # use pin_init::*;
107784837cf6SBenno Lossin /// let mtx_init = CMutex::new(42);
107884837cf6SBenno Lossin /// // Make the initializer print the value.
107984837cf6SBenno Lossin /// let mtx_init = mtx_init.pin_chain(|mtx| {
108084837cf6SBenno Lossin /// println!("{:?}", mtx.get_data_mut());
1081fbf8fb32SBenno Lossin /// Ok(())
1082fbf8fb32SBenno Lossin /// });
1083fbf8fb32SBenno Lossin /// ```
pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E> where F: FnOnce(Pin<&mut T>) -> Result<(), E>,1084fbf8fb32SBenno Lossin fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
1085fbf8fb32SBenno Lossin where
1086fbf8fb32SBenno Lossin F: FnOnce(Pin<&mut T>) -> Result<(), E>,
1087fbf8fb32SBenno Lossin {
1088fbf8fb32SBenno Lossin ChainPinInit(self, f, PhantomData)
1089fbf8fb32SBenno Lossin }
1090fbf8fb32SBenno Lossin }
1091fbf8fb32SBenno Lossin
1092fbf8fb32SBenno Lossin /// An initializer returned by [`PinInit::pin_chain`].
109331547c98SBenno Lossin pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
1094fbf8fb32SBenno Lossin
1095fbf8fb32SBenno Lossin // SAFETY: The `__pinned_init` function is implemented such that it
1096fbf8fb32SBenno Lossin // - returns `Ok(())` on successful initialization,
1097fbf8fb32SBenno Lossin // - returns `Err(err)` on error and in this case `slot` will be dropped.
1098fbf8fb32SBenno Lossin // - considers `slot` pinned.
1099fbf8fb32SBenno Lossin unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainPinInit<I, F, T, E>
1100fbf8fb32SBenno Lossin where
1101fbf8fb32SBenno Lossin I: PinInit<T, E>,
1102fbf8fb32SBenno Lossin F: FnOnce(Pin<&mut T>) -> Result<(), E>,
1103fbf8fb32SBenno Lossin {
__pinned_init(self, slot: *mut T) -> Result<(), E>1104fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1105fbf8fb32SBenno Lossin // SAFETY: All requirements fulfilled since this function is `__pinned_init`.
1106fbf8fb32SBenno Lossin unsafe { self.0.__pinned_init(slot)? };
1107fbf8fb32SBenno Lossin // SAFETY: The above call initialized `slot` and we still have unique access.
1108fbf8fb32SBenno Lossin let val = unsafe { &mut *slot };
1109fbf8fb32SBenno Lossin // SAFETY: `slot` is considered pinned.
1110fbf8fb32SBenno Lossin let val = unsafe { Pin::new_unchecked(val) };
1111fbf8fb32SBenno Lossin // SAFETY: `slot` was initialized above.
1112fbf8fb32SBenno Lossin (self.1)(val).inspect_err(|_| unsafe { core::ptr::drop_in_place(slot) })
1113fbf8fb32SBenno Lossin }
1114fbf8fb32SBenno Lossin }
1115fbf8fb32SBenno Lossin
1116fbf8fb32SBenno Lossin /// An initializer for `T`.
1117fbf8fb32SBenno Lossin ///
1118fbf8fb32SBenno Lossin /// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
1119129e97beSBenno Lossin /// be [`Box<T>`], [`Arc<T>`] or even the stack (see [`stack_pin_init!`]). Because
1120fbf8fb32SBenno Lossin /// [`PinInit<T, E>`] is a super trait, you can use every function that takes it as well.
1121fbf8fb32SBenno Lossin ///
1122fbf8fb32SBenno Lossin /// Also see the [module description](self).
1123fbf8fb32SBenno Lossin ///
1124fbf8fb32SBenno Lossin /// # Safety
1125fbf8fb32SBenno Lossin ///
1126fbf8fb32SBenno Lossin /// When implementing this trait you will need to take great care. Also there are probably very few
1127fbf8fb32SBenno Lossin /// cases where a manual implementation is necessary. Use [`init_from_closure`] where possible.
1128fbf8fb32SBenno Lossin ///
1129fbf8fb32SBenno Lossin /// The [`Init::__init`] function:
1130fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
1131fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
1132fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
1133fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
1134fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
1135fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
1136fbf8fb32SBenno Lossin ///
1137fbf8fb32SBenno Lossin /// The `__pinned_init` function from the supertrait [`PinInit`] needs to execute the exact same
1138fbf8fb32SBenno Lossin /// code as `__init`.
1139fbf8fb32SBenno Lossin ///
1140fbf8fb32SBenno Lossin /// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
1141fbf8fb32SBenno Lossin /// move the pointee after initialization.
1142fbf8fb32SBenno Lossin ///
11439b2299afSBenno Lossin #[cfg_attr(
11449b2299afSBenno Lossin kernel,
11459b2299afSBenno Lossin doc = "[`Arc<T>`]: https://rust.docs.kernel.org/kernel/sync/struct.Arc.html"
11469b2299afSBenno Lossin )]
11479b2299afSBenno Lossin #[cfg_attr(
11489b2299afSBenno Lossin kernel,
11499b2299afSBenno Lossin doc = "[`Box<T>`]: https://rust.docs.kernel.org/kernel/alloc/kbox/struct.Box.html"
11509b2299afSBenno Lossin )]
11519b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Arc<T>`]: alloc::alloc::sync::Arc")]
11529b2299afSBenno Lossin #[cfg_attr(not(kernel), doc = "[`Box<T>`]: alloc::alloc::boxed::Box")]
1153fbf8fb32SBenno Lossin #[must_use = "An initializer must be used in order to create its value."]
1154fbf8fb32SBenno Lossin pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
1155fbf8fb32SBenno Lossin /// Initializes `slot`.
1156fbf8fb32SBenno Lossin ///
1157fbf8fb32SBenno Lossin /// # Safety
1158fbf8fb32SBenno Lossin ///
1159fbf8fb32SBenno Lossin /// - `slot` is a valid pointer to uninitialized memory.
1160fbf8fb32SBenno Lossin /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
1161fbf8fb32SBenno Lossin /// deallocate.
__init(self, slot: *mut T) -> Result<(), E>1162fbf8fb32SBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
1163fbf8fb32SBenno Lossin
1164fbf8fb32SBenno Lossin /// First initializes the value using `self` then calls the function `f` with the initialized
1165fbf8fb32SBenno Lossin /// value.
1166fbf8fb32SBenno Lossin ///
1167fbf8fb32SBenno Lossin /// If `f` returns an error the value is dropped and the initializer will forward the error.
1168fbf8fb32SBenno Lossin ///
1169fbf8fb32SBenno Lossin /// # Examples
1170fbf8fb32SBenno Lossin ///
11711ab10101SBenno Lossin /// ```rust
1172fbf8fb32SBenno Lossin /// # #![expect(clippy::disallowed_names)]
117302c01c08SBenno Lossin /// use pin_init::{init, zeroed, Init};
117402c01c08SBenno Lossin ///
1175fbf8fb32SBenno Lossin /// struct Foo {
1176fbf8fb32SBenno Lossin /// buf: [u8; 1_000_000],
1177fbf8fb32SBenno Lossin /// }
1178fbf8fb32SBenno Lossin ///
1179fbf8fb32SBenno Lossin /// impl Foo {
1180fbf8fb32SBenno Lossin /// fn setup(&mut self) {
118102c01c08SBenno Lossin /// println!("Setting up foo");
1182fbf8fb32SBenno Lossin /// }
1183fbf8fb32SBenno Lossin /// }
1184fbf8fb32SBenno Lossin ///
1185fbf8fb32SBenno Lossin /// let foo = init!(Foo {
118684837cf6SBenno Lossin /// buf <- zeroed()
1187fbf8fb32SBenno Lossin /// }).chain(|foo| {
1188fbf8fb32SBenno Lossin /// foo.setup();
1189fbf8fb32SBenno Lossin /// Ok(())
1190fbf8fb32SBenno Lossin /// });
1191fbf8fb32SBenno Lossin /// ```
chain<F>(self, f: F) -> ChainInit<Self, F, T, E> where F: FnOnce(&mut T) -> Result<(), E>,1192fbf8fb32SBenno Lossin fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
1193fbf8fb32SBenno Lossin where
1194fbf8fb32SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
1195fbf8fb32SBenno Lossin {
1196fbf8fb32SBenno Lossin ChainInit(self, f, PhantomData)
1197fbf8fb32SBenno Lossin }
1198fbf8fb32SBenno Lossin }
1199fbf8fb32SBenno Lossin
1200fbf8fb32SBenno Lossin /// An initializer returned by [`Init::chain`].
120131547c98SBenno Lossin pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, T)>);
1202fbf8fb32SBenno Lossin
1203fbf8fb32SBenno Lossin // SAFETY: The `__init` function is implemented such that it
1204fbf8fb32SBenno Lossin // - returns `Ok(())` on successful initialization,
1205fbf8fb32SBenno Lossin // - returns `Err(err)` on error and in this case `slot` will be dropped.
1206fbf8fb32SBenno Lossin unsafe impl<T: ?Sized, E, I, F> Init<T, E> for ChainInit<I, F, T, E>
1207fbf8fb32SBenno Lossin where
1208fbf8fb32SBenno Lossin I: Init<T, E>,
1209fbf8fb32SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
1210fbf8fb32SBenno Lossin {
__init(self, slot: *mut T) -> Result<(), E>1211fbf8fb32SBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
1212fbf8fb32SBenno Lossin // SAFETY: All requirements fulfilled since this function is `__init`.
1213fbf8fb32SBenno Lossin unsafe { self.0.__pinned_init(slot)? };
1214fbf8fb32SBenno Lossin // SAFETY: The above call initialized `slot` and we still have unique access.
1215fbf8fb32SBenno Lossin (self.1)(unsafe { &mut *slot }).inspect_err(|_|
1216fbf8fb32SBenno Lossin // SAFETY: `slot` was initialized above.
1217fbf8fb32SBenno Lossin unsafe { core::ptr::drop_in_place(slot) })
1218fbf8fb32SBenno Lossin }
1219fbf8fb32SBenno Lossin }
1220fbf8fb32SBenno Lossin
1221fbf8fb32SBenno Lossin // SAFETY: `__pinned_init` behaves exactly the same as `__init`.
1222fbf8fb32SBenno Lossin unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainInit<I, F, T, E>
1223fbf8fb32SBenno Lossin where
1224fbf8fb32SBenno Lossin I: Init<T, E>,
1225fbf8fb32SBenno Lossin F: FnOnce(&mut T) -> Result<(), E>,
1226fbf8fb32SBenno Lossin {
__pinned_init(self, slot: *mut T) -> Result<(), E>1227fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1228fbf8fb32SBenno Lossin // SAFETY: `__init` has less strict requirements compared to `__pinned_init`.
1229fbf8fb32SBenno Lossin unsafe { self.__init(slot) }
1230fbf8fb32SBenno Lossin }
1231fbf8fb32SBenno Lossin }
1232fbf8fb32SBenno Lossin
1233fbf8fb32SBenno Lossin /// Creates a new [`PinInit<T, E>`] from the given closure.
1234fbf8fb32SBenno Lossin ///
1235fbf8fb32SBenno Lossin /// # Safety
1236fbf8fb32SBenno Lossin ///
1237fbf8fb32SBenno Lossin /// The closure:
1238fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
1239fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
1240fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
1241fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
1242fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
1243fbf8fb32SBenno Lossin /// - may assume that the `slot` does not move if `T: !Unpin`,
1244fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
1245fbf8fb32SBenno Lossin #[inline]
pin_init_from_closure<T: ?Sized, E>( f: impl FnOnce(*mut T) -> Result<(), E>, ) -> impl PinInit<T, E>1246fbf8fb32SBenno Lossin pub const unsafe fn pin_init_from_closure<T: ?Sized, E>(
1247fbf8fb32SBenno Lossin f: impl FnOnce(*mut T) -> Result<(), E>,
1248fbf8fb32SBenno Lossin ) -> impl PinInit<T, E> {
1249fbf8fb32SBenno Lossin __internal::InitClosure(f, PhantomData)
1250fbf8fb32SBenno Lossin }
1251fbf8fb32SBenno Lossin
1252fbf8fb32SBenno Lossin /// Creates a new [`Init<T, E>`] from the given closure.
1253fbf8fb32SBenno Lossin ///
1254fbf8fb32SBenno Lossin /// # Safety
1255fbf8fb32SBenno Lossin ///
1256fbf8fb32SBenno Lossin /// The closure:
1257fbf8fb32SBenno Lossin /// - returns `Ok(())` if it initialized every field of `slot`,
1258fbf8fb32SBenno Lossin /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
1259fbf8fb32SBenno Lossin /// - `slot` can be deallocated without UB occurring,
1260fbf8fb32SBenno Lossin /// - `slot` does not need to be dropped,
1261fbf8fb32SBenno Lossin /// - `slot` is not partially initialized.
1262fbf8fb32SBenno Lossin /// - the `slot` may move after initialization.
1263fbf8fb32SBenno Lossin /// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
1264fbf8fb32SBenno Lossin #[inline]
init_from_closure<T: ?Sized, E>( f: impl FnOnce(*mut T) -> Result<(), E>, ) -> impl Init<T, E>1265fbf8fb32SBenno Lossin pub const unsafe fn init_from_closure<T: ?Sized, E>(
1266fbf8fb32SBenno Lossin f: impl FnOnce(*mut T) -> Result<(), E>,
1267fbf8fb32SBenno Lossin ) -> impl Init<T, E> {
1268fbf8fb32SBenno Lossin __internal::InitClosure(f, PhantomData)
1269fbf8fb32SBenno Lossin }
1270fbf8fb32SBenno Lossin
127190348980SBenno Lossin /// Changes the to be initialized type.
127290348980SBenno Lossin ///
127390348980SBenno Lossin /// # Safety
127490348980SBenno Lossin ///
127590348980SBenno Lossin /// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a
127690348980SBenno Lossin /// pointer must result in a valid `U`.
127790348980SBenno Lossin #[expect(clippy::let_and_return)]
cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl PinInit<U, E>127890348980SBenno Lossin pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl PinInit<U, E> {
127990348980SBenno Lossin // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
128090348980SBenno Lossin // requirements.
128190348980SBenno Lossin let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) };
128290348980SBenno Lossin // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
128390348980SBenno Lossin // cycle when computing the type returned by this function)
128490348980SBenno Lossin res
128590348980SBenno Lossin }
128690348980SBenno Lossin
128790348980SBenno Lossin /// Changes the to be initialized type.
128890348980SBenno Lossin ///
128990348980SBenno Lossin /// # Safety
129090348980SBenno Lossin ///
129190348980SBenno Lossin /// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a
129290348980SBenno Lossin /// pointer must result in a valid `U`.
129390348980SBenno Lossin #[expect(clippy::let_and_return)]
cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E>129490348980SBenno Lossin pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> {
129590348980SBenno Lossin // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
129690348980SBenno Lossin // requirements.
129790348980SBenno Lossin let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) };
129890348980SBenno Lossin // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
129990348980SBenno Lossin // cycle when computing the type returned by this function)
130090348980SBenno Lossin res
130190348980SBenno Lossin }
130290348980SBenno Lossin
1303fbf8fb32SBenno Lossin /// An initializer that leaves the memory uninitialized.
1304fbf8fb32SBenno Lossin ///
1305fbf8fb32SBenno Lossin /// The initializer is a no-op. The `slot` memory is not changed.
1306fbf8fb32SBenno Lossin #[inline]
uninit<T, E>() -> impl Init<MaybeUninit<T>, E>1307fbf8fb32SBenno Lossin pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
1308fbf8fb32SBenno Lossin // SAFETY: The memory is allowed to be uninitialized.
1309fbf8fb32SBenno Lossin unsafe { init_from_closure(|_| Ok(())) }
1310fbf8fb32SBenno Lossin }
1311fbf8fb32SBenno Lossin
1312fbf8fb32SBenno Lossin /// Initializes an array by initializing each element via the provided initializer.
1313fbf8fb32SBenno Lossin ///
1314fbf8fb32SBenno Lossin /// # Examples
1315fbf8fb32SBenno Lossin ///
13161ab10101SBenno Lossin /// ```rust
131784837cf6SBenno Lossin /// # use pin_init::*;
131884837cf6SBenno Lossin /// use pin_init::init_array_from_fn;
131984837cf6SBenno Lossin /// let array: Box<[usize; 1_000]> = Box::init(init_array_from_fn(|i| i)).unwrap();
1320fbf8fb32SBenno Lossin /// assert_eq!(array.len(), 1_000);
1321fbf8fb32SBenno 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>,1322fbf8fb32SBenno Lossin pub fn init_array_from_fn<I, const N: usize, T, E>(
1323fbf8fb32SBenno Lossin mut make_init: impl FnMut(usize) -> I,
1324fbf8fb32SBenno Lossin ) -> impl Init<[T; N], E>
1325fbf8fb32SBenno Lossin where
1326fbf8fb32SBenno Lossin I: Init<T, E>,
1327fbf8fb32SBenno Lossin {
1328fbf8fb32SBenno Lossin let init = move |slot: *mut [T; N]| {
1329fbf8fb32SBenno Lossin let slot = slot.cast::<T>();
1330fbf8fb32SBenno Lossin for i in 0..N {
1331fbf8fb32SBenno Lossin let init = make_init(i);
1332fbf8fb32SBenno Lossin // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
1333fbf8fb32SBenno Lossin let ptr = unsafe { slot.add(i) };
1334fbf8fb32SBenno Lossin // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
1335fbf8fb32SBenno Lossin // requirements.
133631547c98SBenno Lossin if let Err(e) = unsafe { init.__init(ptr) } {
133731547c98SBenno Lossin // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
133831547c98SBenno Lossin // `Err` below, `slot` will be considered uninitialized memory.
133931547c98SBenno Lossin unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
134031547c98SBenno Lossin return Err(e);
1341fbf8fb32SBenno Lossin }
134231547c98SBenno Lossin }
1343fbf8fb32SBenno Lossin Ok(())
1344fbf8fb32SBenno Lossin };
1345fbf8fb32SBenno Lossin // SAFETY: The initializer above initializes every element of the array. On failure it drops
1346fbf8fb32SBenno Lossin // any initialized elements and returns `Err`.
1347fbf8fb32SBenno Lossin unsafe { init_from_closure(init) }
1348fbf8fb32SBenno Lossin }
1349fbf8fb32SBenno Lossin
1350fbf8fb32SBenno Lossin /// Initializes an array by initializing each element via the provided initializer.
1351fbf8fb32SBenno Lossin ///
1352fbf8fb32SBenno Lossin /// # Examples
1353fbf8fb32SBenno Lossin ///
13541ab10101SBenno Lossin /// ```rust
135584837cf6SBenno Lossin /// # #![feature(allocator_api)]
135684837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
135784837cf6SBenno Lossin /// # use pin_init::*;
135884837cf6SBenno Lossin /// # use core::pin::Pin;
135984837cf6SBenno Lossin /// use pin_init::pin_init_array_from_fn;
136084837cf6SBenno Lossin /// use std::sync::Arc;
136184837cf6SBenno Lossin /// let array: Pin<Arc<[CMutex<usize>; 1_000]>> =
136284837cf6SBenno Lossin /// Arc::pin_init(pin_init_array_from_fn(|i| CMutex::new(i))).unwrap();
1363fbf8fb32SBenno Lossin /// assert_eq!(array.len(), 1_000);
1364fbf8fb32SBenno 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>,1365fbf8fb32SBenno Lossin pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
1366fbf8fb32SBenno Lossin mut make_init: impl FnMut(usize) -> I,
1367fbf8fb32SBenno Lossin ) -> impl PinInit<[T; N], E>
1368fbf8fb32SBenno Lossin where
1369fbf8fb32SBenno Lossin I: PinInit<T, E>,
1370fbf8fb32SBenno Lossin {
1371fbf8fb32SBenno Lossin let init = move |slot: *mut [T; N]| {
1372fbf8fb32SBenno Lossin let slot = slot.cast::<T>();
1373fbf8fb32SBenno Lossin for i in 0..N {
1374fbf8fb32SBenno Lossin let init = make_init(i);
1375fbf8fb32SBenno Lossin // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
1376fbf8fb32SBenno Lossin let ptr = unsafe { slot.add(i) };
1377fbf8fb32SBenno Lossin // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
1378fbf8fb32SBenno Lossin // requirements.
137931547c98SBenno Lossin if let Err(e) = unsafe { init.__pinned_init(ptr) } {
138031547c98SBenno Lossin // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
138131547c98SBenno Lossin // `Err` below, `slot` will be considered uninitialized memory.
138231547c98SBenno Lossin unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
138331547c98SBenno Lossin return Err(e);
1384fbf8fb32SBenno Lossin }
138531547c98SBenno Lossin }
1386fbf8fb32SBenno Lossin Ok(())
1387fbf8fb32SBenno Lossin };
1388fbf8fb32SBenno Lossin // SAFETY: The initializer above initializes every element of the array. On failure it drops
1389fbf8fb32SBenno Lossin // any initialized elements and returns `Err`.
1390fbf8fb32SBenno Lossin unsafe { pin_init_from_closure(init) }
1391fbf8fb32SBenno Lossin }
1392fbf8fb32SBenno Lossin
1393fbf8fb32SBenno Lossin // SAFETY: Every type can be initialized by-value.
1394fbf8fb32SBenno Lossin unsafe impl<T, E> Init<T, E> for T {
__init(self, slot: *mut T) -> Result<(), E>1395fbf8fb32SBenno Lossin unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
1396fbf8fb32SBenno Lossin // SAFETY: TODO.
1397fbf8fb32SBenno Lossin unsafe { slot.write(self) };
1398fbf8fb32SBenno Lossin Ok(())
1399fbf8fb32SBenno Lossin }
1400fbf8fb32SBenno Lossin }
1401fbf8fb32SBenno Lossin
1402fbf8fb32SBenno Lossin // SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`.
1403fbf8fb32SBenno Lossin unsafe impl<T, E> PinInit<T, E> for T {
__pinned_init(self, slot: *mut T) -> Result<(), E>1404fbf8fb32SBenno Lossin unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
1405fbf8fb32SBenno Lossin // SAFETY: TODO.
1406fbf8fb32SBenno Lossin unsafe { self.__init(slot) }
1407fbf8fb32SBenno Lossin }
1408fbf8fb32SBenno Lossin }
1409fbf8fb32SBenno Lossin
1410fbf8fb32SBenno Lossin /// Smart pointer containing uninitialized memory and that can write a value.
1411fbf8fb32SBenno Lossin pub trait InPlaceWrite<T> {
1412fbf8fb32SBenno Lossin /// The type `Self` turns into when the contents are initialized.
1413fbf8fb32SBenno Lossin type Initialized;
1414fbf8fb32SBenno Lossin
1415fbf8fb32SBenno Lossin /// Use the given initializer to write a value into `self`.
1416fbf8fb32SBenno Lossin ///
1417fbf8fb32SBenno 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>1418fbf8fb32SBenno Lossin fn write_init<E>(self, init: impl Init<T, E>) -> Result<Self::Initialized, E>;
1419fbf8fb32SBenno Lossin
1420fbf8fb32SBenno Lossin /// Use the given pin-initializer to write a value into `self`.
1421fbf8fb32SBenno Lossin ///
1422fbf8fb32SBenno 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>1423fbf8fb32SBenno Lossin fn write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E>;
1424fbf8fb32SBenno Lossin }
1425fbf8fb32SBenno Lossin
1426fbf8fb32SBenno Lossin /// Trait facilitating pinned destruction.
1427fbf8fb32SBenno Lossin ///
1428fbf8fb32SBenno Lossin /// Use [`pinned_drop`] to implement this trait safely:
1429fbf8fb32SBenno Lossin ///
14301ab10101SBenno Lossin /// ```rust
143184837cf6SBenno Lossin /// # #![feature(allocator_api)]
143284837cf6SBenno Lossin /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*;
143384837cf6SBenno Lossin /// # use pin_init::*;
1434fbf8fb32SBenno Lossin /// use core::pin::Pin;
1435fbf8fb32SBenno Lossin /// #[pin_data(PinnedDrop)]
1436fbf8fb32SBenno Lossin /// struct Foo {
1437fbf8fb32SBenno Lossin /// #[pin]
143884837cf6SBenno Lossin /// mtx: CMutex<usize>,
1439fbf8fb32SBenno Lossin /// }
1440fbf8fb32SBenno Lossin ///
1441fbf8fb32SBenno Lossin /// #[pinned_drop]
1442fbf8fb32SBenno Lossin /// impl PinnedDrop for Foo {
1443fbf8fb32SBenno Lossin /// fn drop(self: Pin<&mut Self>) {
144484837cf6SBenno Lossin /// println!("Foo is being dropped!");
1445fbf8fb32SBenno Lossin /// }
1446fbf8fb32SBenno Lossin /// }
1447fbf8fb32SBenno Lossin /// ```
1448fbf8fb32SBenno Lossin ///
1449fbf8fb32SBenno Lossin /// # Safety
1450fbf8fb32SBenno Lossin ///
1451fbf8fb32SBenno Lossin /// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
1452fbf8fb32SBenno Lossin pub unsafe trait PinnedDrop: __internal::HasPinData {
1453fbf8fb32SBenno Lossin /// Executes the pinned destructor of this type.
1454fbf8fb32SBenno Lossin ///
1455fbf8fb32SBenno Lossin /// While this function is marked safe, it is actually unsafe to call it manually. For this
1456fbf8fb32SBenno Lossin /// reason it takes an additional parameter. This type can only be constructed by `unsafe` code
1457fbf8fb32SBenno Lossin /// and thus prevents this function from being called where it should not.
1458fbf8fb32SBenno Lossin ///
1459fbf8fb32SBenno Lossin /// This extra parameter will be generated by the `#[pinned_drop]` proc-macro attribute
1460fbf8fb32SBenno Lossin /// automatically.
drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop)1461fbf8fb32SBenno Lossin fn drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop);
1462fbf8fb32SBenno Lossin }
1463fbf8fb32SBenno Lossin
1464fbf8fb32SBenno Lossin /// Marker trait for types that can be initialized by writing just zeroes.
1465fbf8fb32SBenno Lossin ///
1466fbf8fb32SBenno Lossin /// # Safety
1467fbf8fb32SBenno Lossin ///
1468fbf8fb32SBenno Lossin /// The bit pattern consisting of only zeroes is a valid bit pattern for this type. In other words,
1469fbf8fb32SBenno Lossin /// this is not UB:
1470fbf8fb32SBenno Lossin ///
1471fbf8fb32SBenno Lossin /// ```rust,ignore
1472fbf8fb32SBenno Lossin /// let val: Self = unsafe { core::mem::zeroed() };
1473fbf8fb32SBenno Lossin /// ```
1474fbf8fb32SBenno Lossin pub unsafe trait Zeroable {}
1475fbf8fb32SBenno Lossin
14765657c3a9SBenno Lossin /// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
14775657c3a9SBenno Lossin /// `None` to that location.
14785657c3a9SBenno Lossin ///
14795657c3a9SBenno Lossin /// # Safety
14805657c3a9SBenno Lossin ///
14815657c3a9SBenno Lossin /// The implementer needs to ensure that `unsafe impl Zeroable for Option<Self> {}` is sound.
14825657c3a9SBenno Lossin pub unsafe trait ZeroableOption {}
14835657c3a9SBenno Lossin
14845657c3a9SBenno Lossin // SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
14855657c3a9SBenno Lossin unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}
14865657c3a9SBenno Lossin
1487fbf8fb32SBenno Lossin /// Create a new zeroed T.
1488fbf8fb32SBenno Lossin ///
1489fbf8fb32SBenno Lossin /// The returned initializer will write `0x00` to every byte of the given `slot`.
1490fbf8fb32SBenno Lossin #[inline]
zeroed<T: Zeroable>() -> impl Init<T>1491fbf8fb32SBenno Lossin pub fn zeroed<T: Zeroable>() -> impl Init<T> {
1492fbf8fb32SBenno Lossin // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
1493fbf8fb32SBenno Lossin // and because we write all zeroes, the memory is initialized.
1494fbf8fb32SBenno Lossin unsafe {
1495fbf8fb32SBenno Lossin init_from_closure(|slot: *mut T| {
1496fbf8fb32SBenno Lossin slot.write_bytes(0, 1);
1497fbf8fb32SBenno Lossin Ok(())
1498fbf8fb32SBenno Lossin })
1499fbf8fb32SBenno Lossin }
1500fbf8fb32SBenno Lossin }
1501fbf8fb32SBenno Lossin
1502fbf8fb32SBenno Lossin macro_rules! impl_zeroable {
1503fbf8fb32SBenno Lossin ($($({$($generics:tt)*})? $t:ty, )*) => {
1504fbf8fb32SBenno Lossin // SAFETY: Safety comments written in the macro invocation.
1505fbf8fb32SBenno Lossin $(unsafe impl$($($generics)*)? Zeroable for $t {})*
1506fbf8fb32SBenno Lossin };
1507fbf8fb32SBenno Lossin }
1508fbf8fb32SBenno Lossin
1509fbf8fb32SBenno Lossin impl_zeroable! {
1510fbf8fb32SBenno Lossin // SAFETY: All primitives that are allowed to be zero.
1511fbf8fb32SBenno Lossin bool,
1512fbf8fb32SBenno Lossin char,
1513fbf8fb32SBenno Lossin u8, u16, u32, u64, u128, usize,
1514fbf8fb32SBenno Lossin i8, i16, i32, i64, i128, isize,
1515fbf8fb32SBenno Lossin f32, f64,
1516fbf8fb32SBenno Lossin
1517fbf8fb32SBenno Lossin // Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
1518fbf8fb32SBenno Lossin // creating an instance of an uninhabited type is immediate undefined behavior. For more on
1519fbf8fb32SBenno Lossin // uninhabited/empty types, consult The Rustonomicon:
1520fbf8fb32SBenno Lossin // <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
1521fbf8fb32SBenno Lossin // also has information on undefined behavior:
1522fbf8fb32SBenno Lossin // <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
1523fbf8fb32SBenno Lossin //
1524fbf8fb32SBenno Lossin // SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
1525fbf8fb32SBenno Lossin {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
1526fbf8fb32SBenno Lossin
1527fbf8fb32SBenno Lossin // SAFETY: Type is allowed to take any value, including all zeros.
1528fbf8fb32SBenno Lossin {<T>} MaybeUninit<T>,
1529fbf8fb32SBenno Lossin
1530fbf8fb32SBenno Lossin // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.
1531fbf8fb32SBenno Lossin {<T: ?Sized + Zeroable>} UnsafeCell<T>,
1532fbf8fb32SBenno Lossin
15334e82c870SLinus Torvalds // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
1534193b5a75SMiguel Ojeda // <https://doc.rust-lang.org/stable/std/option/index.html#representation>).
1535fbf8fb32SBenno Lossin Option<NonZeroU8>, Option<NonZeroU16>, Option<NonZeroU32>, Option<NonZeroU64>,
1536fbf8fb32SBenno Lossin Option<NonZeroU128>, Option<NonZeroUsize>,
1537fbf8fb32SBenno Lossin Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>,
1538fbf8fb32SBenno Lossin Option<NonZeroI128>, Option<NonZeroIsize>,
15394e82c870SLinus Torvalds {<T>} Option<NonNull<T>>,
1540fbf8fb32SBenno Lossin
1541fbf8fb32SBenno Lossin // SAFETY: `null` pointer is valid.
1542fbf8fb32SBenno Lossin //
1543fbf8fb32SBenno Lossin // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be
1544fbf8fb32SBenno Lossin // null.
1545fbf8fb32SBenno Lossin //
1546fbf8fb32SBenno Lossin // When `Pointee` gets stabilized, we could use
1547fbf8fb32SBenno Lossin // `T: ?Sized where <T as Pointee>::Metadata: Zeroable`
1548fbf8fb32SBenno Lossin {<T>} *mut T, {<T>} *const T,
1549fbf8fb32SBenno Lossin
1550fbf8fb32SBenno Lossin // SAFETY: `null` pointer is valid and the metadata part of these fat pointers is allowed to be
1551fbf8fb32SBenno Lossin // zero.
1552fbf8fb32SBenno Lossin {<T>} *mut [T], {<T>} *const [T], *mut str, *const str,
1553fbf8fb32SBenno Lossin
1554fbf8fb32SBenno Lossin // SAFETY: `T` is `Zeroable`.
1555fbf8fb32SBenno Lossin {<const N: usize, T: Zeroable>} [T; N], {<T: Zeroable>} Wrapping<T>,
1556fbf8fb32SBenno Lossin }
1557fbf8fb32SBenno Lossin
1558fbf8fb32SBenno Lossin macro_rules! impl_tuple_zeroable {
1559fbf8fb32SBenno Lossin ($(,)?) => {};
1560fbf8fb32SBenno Lossin ($first:ident, $($t:ident),* $(,)?) => {
1561fbf8fb32SBenno Lossin // SAFETY: All elements are zeroable and padding can be zero.
1562fbf8fb32SBenno Lossin unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}
1563fbf8fb32SBenno Lossin impl_tuple_zeroable!($($t),* ,);
1564fbf8fb32SBenno Lossin }
1565fbf8fb32SBenno Lossin }
1566fbf8fb32SBenno Lossin
1567fbf8fb32SBenno Lossin impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);
15682f7c7382SChristian Schrefl
15692f7c7382SChristian Schrefl /// This trait allows creating an instance of `Self` which contains exactly one
15702f7c7382SChristian Schrefl /// [structurally pinned value](https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning).
15712f7c7382SChristian Schrefl ///
15722f7c7382SChristian Schrefl /// This is useful when using wrapper `struct`s like [`UnsafeCell`] or with new-type `struct`s.
15732f7c7382SChristian Schrefl ///
15742f7c7382SChristian Schrefl /// # Examples
15752f7c7382SChristian Schrefl ///
15762f7c7382SChristian Schrefl /// ```
15772f7c7382SChristian Schrefl /// # use core::cell::UnsafeCell;
15782f7c7382SChristian Schrefl /// # use pin_init::{pin_data, pin_init, Wrapper};
15792f7c7382SChristian Schrefl ///
15802f7c7382SChristian Schrefl /// #[pin_data]
15812f7c7382SChristian Schrefl /// struct Foo {}
15822f7c7382SChristian Schrefl ///
15832f7c7382SChristian Schrefl /// #[pin_data]
15842f7c7382SChristian Schrefl /// struct Bar {
15852f7c7382SChristian Schrefl /// #[pin]
15862f7c7382SChristian Schrefl /// content: UnsafeCell<Foo>
15872f7c7382SChristian Schrefl /// };
15882f7c7382SChristian Schrefl ///
15892f7c7382SChristian Schrefl /// let foo_initializer = pin_init!(Foo{});
15902f7c7382SChristian Schrefl /// let initializer = pin_init!(Bar {
15912f7c7382SChristian Schrefl /// content <- UnsafeCell::pin_init(foo_initializer)
15922f7c7382SChristian Schrefl /// });
15932f7c7382SChristian Schrefl /// ```
15942f7c7382SChristian Schrefl pub trait Wrapper<T> {
1595a919ba21SBenno Lossin /// Creates an pin-initializer for a [`Self`] containing `T` from the `value_init` initializer.
pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E>15962f7c7382SChristian Schrefl fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E>;
15972f7c7382SChristian Schrefl }
15982f7c7382SChristian Schrefl
15992f7c7382SChristian Schrefl impl<T> Wrapper<T> for UnsafeCell<T> {
pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E>16002f7c7382SChristian Schrefl fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
16012f7c7382SChristian Schrefl // SAFETY: `UnsafeCell<T>` has a compatible layout to `T`.
16022f7c7382SChristian Schrefl unsafe { cast_pin_init(value_init) }
16032f7c7382SChristian Schrefl }
16042f7c7382SChristian Schrefl }
16052f7c7382SChristian Schrefl
16062f7c7382SChristian Schrefl impl<T> Wrapper<T> for MaybeUninit<T> {
pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E>16072f7c7382SChristian Schrefl fn pin_init<E>(value_init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
16082f7c7382SChristian Schrefl // SAFETY: `MaybeUninit<T>` has a compatible layout to `T`.
16092f7c7382SChristian Schrefl unsafe { cast_pin_init(value_init) }
16102f7c7382SChristian Schrefl }
16112f7c7382SChristian Schrefl }
1612b862aac8SChristian Schrefl
1613b862aac8SChristian Schrefl #[cfg(all(feature = "unsafe-pinned", CONFIG_RUSTC_HAS_UNSAFE_PINNED))]
1614b862aac8SChristian Schrefl impl<T> Wrapper<T> for core::pin::UnsafePinned<T> {
pin_init<E>(init: impl PinInit<T, E>) -> impl PinInit<Self, E>1615b862aac8SChristian Schrefl fn pin_init<E>(init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
1616b862aac8SChristian Schrefl // SAFETY: `UnsafePinned<T>` has a compatible layout to `T`.
1617b862aac8SChristian Schrefl unsafe { cast_pin_init(init) }
1618b862aac8SChristian Schrefl }
1619b862aac8SChristian Schrefl }
1620