Skip to main content

pin_project/
lib.rs

1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3/*!
4<!-- Note: Document from sync-markdown-to-rustdoc:start through sync-markdown-to-rustdoc:end
5     is synchronized from README.md. Any changes to that range are not preserved. -->
6<!-- tidy:sync-markdown-to-rustdoc:start -->
7
8A crate for safe and ergonomic [pin-projection].
9
10## Usage
11
12Add this to your `Cargo.toml`:
13
14```toml
15[dependencies]
16pin-project = "1"
17```
18
19## Examples
20
21[`#[pin_project]`][`pin_project`] attribute creates projection types
22covering all the fields of struct or enum.
23
24```
25use std::pin::Pin;
26
27use pin_project::pin_project;
28
29#[pin_project]
30struct Struct<T, U> {
31    #[pin]
32    pinned: T,
33    unpinned: U,
34}
35
36impl<T, U> Struct<T, U> {
37    fn method(self: Pin<&mut Self>) {
38        let this = self.project();
39        let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
40        let _: &mut U = this.unpinned; // Normal reference to the field
41    }
42}
43```
44
45[*code like this will be generated*][struct-default-expanded]
46
47To use `#[pin_project]` on enums, you need to name the projection type
48returned from the method.
49
50```
51use std::pin::Pin;
52
53use pin_project::pin_project;
54
55#[pin_project(project = EnumProj)]
56enum Enum<T, U> {
57    Pinned(#[pin] T),
58    Unpinned(U),
59}
60
61impl<T, U> Enum<T, U> {
62    fn method(self: Pin<&mut Self>) {
63        match self.project() {
64            EnumProj::Pinned(x) => {
65                let _: Pin<&mut T> = x;
66            }
67            EnumProj::Unpinned(y) => {
68                let _: &mut U = y;
69            }
70        }
71    }
72}
73```
74
75[*code like this will be generated*][enum-default-expanded]
76
77See [`#[pin_project]`][`pin_project`] attribute for more details, and
78see [examples] directory for more examples and generated code.
79
80## Related Projects
81
82- [pin-project-lite]: A lightweight version of pin-project written with declarative macros.
83
84[enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs
85[examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md
86[pin-project-lite]: https://github.com/taiki-e/pin-project-lite
87[pin-projection]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning
88[struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs
89
90<!-- tidy:sync-markdown-to-rustdoc:end -->
91*/
92
93#![no_std]
94#![doc(test(
95    no_crate_inject,
96    attr(allow(
97        dead_code,
98        unused_variables,
99        clippy::undocumented_unsafe_blocks,
100        clippy::unused_trait_names,
101    ))
102))]
103#![warn(
104    // Lints that may help when writing public library.
105    missing_debug_implementations,
106    missing_docs,
107    clippy::alloc_instead_of_core,
108    clippy::exhaustive_enums,
109    clippy::exhaustive_structs,
110    clippy::impl_trait_in_params,
111    clippy::std_instead_of_alloc,
112    clippy::std_instead_of_core,
113    // clippy::missing_inline_in_public_items,
114)]
115#![allow(clippy::needless_doctest_main)]
116
117#[doc(inline)]
118pub use pin_project_internal::pin_project;
119#[doc(inline)]
120pub use pin_project_internal::pinned_drop;
121
122/// A trait used for custom implementations of [`Unpin`].
123///
124/// This trait is used in conjunction with the `UnsafeUnpin` argument to
125/// the [`#[pin_project]`][macro@pin_project] attribute.
126///
127/// # Safety
128///
129/// The Rust [`Unpin`] trait is safe to implement - by itself,
130/// implementing it cannot lead to [undefined behavior][undefined-behavior].
131/// Undefined behavior can only occur when other unsafe code is used.
132///
133/// It turns out that using pin projections, which requires unsafe code,
134/// imposes additional requirements on an [`Unpin`] impl. Normally, all of this
135/// unsafety is contained within this crate, ensuring that it's impossible for
136/// you to violate any of the guarantees required by pin projection.
137///
138/// However, things change if you want to provide a custom [`Unpin`] impl
139/// for your `#[pin_project]` type. As stated in [the Rust
140/// documentation][pin-projection], you must be sure to only implement [`Unpin`]
141/// when all of your `#[pin]` fields (i.e. structurally pinned fields) are also
142/// [`Unpin`].
143///
144/// To help highlight this unsafety, the `UnsafeUnpin` trait is provided.
145/// Implementing this trait is logically equivalent to implementing [`Unpin`] -
146/// this crate will generate an [`Unpin`] impl for your type that 'forwards' to
147/// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type
148/// uses structural pinning (otherwise, you wouldn't be using this crate!),
149/// you must be sure that your `UnsafeUnpin` impls follows all of
150/// the requirements for an [`Unpin`] impl of a structurally-pinned type.
151///
152/// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not*
153/// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`].
154/// This is effectively the same thing as adding a [`PhantomPinned`] to your
155/// type.
156///
157/// Since this trait is `unsafe`, impls of it will be detected by the
158/// `unsafe_code` lint, and by tools like [`cargo geiger`][cargo-geiger].
159///
160/// # Examples
161///
162/// An `UnsafeUnpin` impl which, in addition to requiring that structurally
163/// pinned fields be [`Unpin`], imposes an additional requirement:
164///
165/// ```
166/// use pin_project::{UnsafeUnpin, pin_project};
167///
168/// #[pin_project(UnsafeUnpin)]
169/// struct Struct<K, V> {
170///     #[pin]
171///     field_1: K,
172///     field_2: V,
173/// }
174///
175/// # #[allow(clippy::undocumented_unsafe_blocks)]
176/// unsafe impl<K, V> UnsafeUnpin for Struct<K, V> where K: Unpin + Clone {}
177/// ```
178///
179/// [`PhantomPinned`]: core::marker::PhantomPinned
180/// [cargo-geiger]: https://github.com/rust-secure-code/cargo-geiger
181/// [pin-projection]: core::pin#projections-and-structural-pinning
182/// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
183pub unsafe trait UnsafeUnpin {}
184
185// Not public API.
186#[doc(hidden)]
187#[allow(missing_debug_implementations)]
188pub mod __private {
189    use core::mem::ManuallyDrop;
190    #[doc(hidden)]
191    pub use core::{
192        marker::{PhantomData, PhantomPinned, Unpin},
193        ops::Drop,
194        pin::Pin,
195        ptr,
196    };
197
198    #[doc(hidden)]
199    pub use pin_project_internal::__PinProjectInternalDerive;
200
201    use super::UnsafeUnpin;
202
203    // An internal trait used for custom implementations of [`Drop`].
204    //
205    // **Do not call or implement this trait directly.**
206    //
207    // # Why this trait is private and `#[pinned_drop]` attribute is needed?
208    //
209    // Implementing `PinnedDrop::drop` is safe, but calling it is not safe.
210    // This is because destructors can be called multiple times in safe code and
211    // [double dropping is unsound][rust-lang/rust#62360].
212    //
213    // Ideally, it would be desirable to be able to forbid manual calls in
214    // the same way as [`Drop::drop`], but the library cannot do it. So, by using
215    // macros and replacing them with private traits,
216    // this crate prevent users from calling `PinnedDrop::drop` in safe code.
217    //
218    // This allows implementing [`Drop`] safely using `#[pinned_drop]`.
219    // Also by using the [`drop`] function just like dropping a type that directly
220    // implements [`Drop`], can drop safely a type that implements `PinnedDrop`.
221    //
222    // [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360
223    #[doc(hidden)]
224    pub trait PinnedDrop {
225        #[doc(hidden)]
226        unsafe fn drop(self: Pin<&mut Self>);
227    }
228
229    // This is an internal helper struct used by `pin-project-internal`.
230    // This allows us to force an error if the user tries to provide
231    // a regular `Unpin` impl when they specify the `UnsafeUnpin` argument.
232    // This is why we need Wrapper:
233    //
234    // Supposed we have the following code:
235    //
236    // ```
237    // #[pin_project(UnsafeUnpin)]
238    // struct MyStruct<T> {
239    //     #[pin] field: T
240    // }
241    //
242    // impl<T> Unpin for MyStruct<T> where MyStruct<T>: UnsafeUnpin {} // generated by pin-project-internal
243    // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
244    // ```
245    //
246    // We want this code to be rejected - the user is completely bypassing
247    // `UnsafeUnpin`, and providing an unsound Unpin impl in safe code!
248    //
249    // Unfortunately, the Rust compiler will accept the above code.
250    // Because MyStruct is declared in the same crate as the user-provided impl,
251    // the compiler will notice that `MyStruct<T>: UnsafeUnpin` never holds.
252    //
253    // The solution is to introduce the `Wrapper` struct, which is defined
254    // in the `pin-project` crate.
255    //
256    // We now have code that looks like this:
257    //
258    // ```
259    // impl<T> Unpin for MyStruct<T> where Wrapper<MyStruct<T>>: UnsafeUnpin {} // generated by pin-project-internal
260    // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
261    // ```
262    //
263    // We also have `unsafe impl<T> UnsafeUnpin for Wrapper<T> where T: UnsafeUnpin {}`
264    // in the `pin-project` crate.
265    //
266    // Now, our generated impl has a bound involving a type defined in another
267    // crate - Wrapper. This will cause rust to conservatively assume that
268    // `Wrapper<MyStruct<T>>: UnsafeUnpin` holds, in the interest of preserving
269    // forwards compatibility (in case such an impl is added for Wrapper<T> in
270    // a new version of the crate).
271    //
272    // This will cause rust to reject any other `Unpin` impls for MyStruct<T>,
273    // since it will assume that our generated impl could potentially apply in
274    // any situation.
275    //
276    // This achieves the desired effect - when the user writes
277    // `#[pin_project(UnsafeUnpin)]`, the user must either provide no impl of
278    // `UnsafeUnpin` (which is equivalent to making the type never implement
279    // Unpin), or provide an impl of `UnsafeUnpin`. It is impossible for them to
280    // provide an impl of `Unpin`
281    #[doc(hidden)]
282    #[allow(dead_code)]
283    pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T);
284    // SAFETY: `T` implements UnsafeUnpin.
285    unsafe impl<T: ?Sized + UnsafeUnpin> UnsafeUnpin for Wrapper<'_, T> {}
286
287    // Workaround for issue on unstable negative_impls feature that allows unsound overlapping Unpin
288    // implementations and rustc bug that leaks unstable negative_impls into stable.
289    // See https://github.com/taiki-e/pin-project/issues/340#issuecomment-2432146009 for details.
290    #[doc(hidden)]
291    pub type PinnedFieldsOf<T> =
292        <PinnedFieldsOfHelperStruct<T> as PinnedFieldsOfHelperTrait>::Actual;
293    // We cannot use <Option<T> as IntoIterator>::Item or similar since we should allow ?Sized in T.
294    #[doc(hidden)]
295    pub trait PinnedFieldsOfHelperTrait {
296        type Actual: ?Sized;
297    }
298    #[doc(hidden)]
299    pub struct PinnedFieldsOfHelperStruct<T: ?Sized>(T);
300    impl<T: ?Sized> PinnedFieldsOfHelperTrait for PinnedFieldsOfHelperStruct<T> {
301        type Actual = T;
302    }
303
304    // This is an internal helper struct used by `pin-project-internal`.
305    //
306    // See https://github.com/taiki-e/pin-project/pull/53 for more details.
307    #[doc(hidden)]
308    pub struct AlwaysUnpin<'a, T>(PhantomData<&'a ()>, PhantomData<T>);
309    impl<T> Unpin for AlwaysUnpin<'_, T> {}
310
311    // This is an internal helper used to ensure a value is dropped.
312    #[doc(hidden)]
313    pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T);
314    impl<T: ?Sized> UnsafeDropInPlaceGuard<T> {
315        #[doc(hidden)]
316        pub unsafe fn new(ptr: *mut T) -> Self {
317            Self(ptr)
318        }
319    }
320    impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> {
321        fn drop(&mut self) {
322            // SAFETY: the caller of `UnsafeDropInPlaceGuard::new` must guarantee
323            // that `ptr` is valid for drop when this guard is destructed.
324            unsafe {
325                ptr::drop_in_place(self.0);
326            }
327        }
328    }
329
330    // This is an internal helper used to ensure a value is overwritten without
331    // its destructor being called.
332    #[doc(hidden)]
333    pub struct UnsafeOverwriteGuard<T> {
334        target: *mut T,
335        value: ManuallyDrop<T>,
336    }
337    impl<T> UnsafeOverwriteGuard<T> {
338        #[doc(hidden)]
339        pub unsafe fn new(target: *mut T, value: T) -> Self {
340            Self { target, value: ManuallyDrop::new(value) }
341        }
342    }
343    impl<T> Drop for UnsafeOverwriteGuard<T> {
344        fn drop(&mut self) {
345            // SAFETY: the caller of `UnsafeOverwriteGuard::new` must guarantee
346            // that `target` is valid for writes when this guard is destructed.
347            unsafe {
348                ptr::write(self.target, ptr::read(&*self.value));
349            }
350        }
351    }
352}