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