• 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(missing_docs, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
78 #![warn(clippy::default_trait_access, clippy::wildcard_imports)]
79 #![allow(clippy::needless_doctest_main)]
80 
81 // ANDROID: Use std to allow building as a dylib.
82 extern crate std;
83 
84 #[doc(inline)]
85 pub use pin_project_internal::pin_project;
86 #[doc(inline)]
87 pub use pin_project_internal::pinned_drop;
88 
89 /// A trait used for custom implementations of [`Unpin`].
90 ///
91 /// This trait is used in conjunction with the `UnsafeUnpin` argument to
92 /// the [`#[pin_project]`][macro@pin_project] attribute.
93 ///
94 /// # Safety
95 ///
96 /// The Rust [`Unpin`] trait is safe to implement - by itself,
97 /// implementing it cannot lead to [undefined behavior][undefined-behavior].
98 /// Undefined behavior can only occur when other unsafe code is used.
99 ///
100 /// It turns out that using pin projections, which requires unsafe code,
101 /// imposes additional requirements on an [`Unpin`] impl. Normally, all of this
102 /// unsafety is contained within this crate, ensuring that it's impossible for
103 /// you to violate any of the guarantees required by pin projection.
104 ///
105 /// However, things change if you want to provide a custom [`Unpin`] impl
106 /// for your `#[pin_project]` type. As stated in [the Rust
107 /// documentation][pin-projection], you must be sure to only implement [`Unpin`]
108 /// when all of your `#[pin]` fields (i.e. structurally pinned fields) are also
109 /// [`Unpin`].
110 ///
111 /// To help highlight this unsafety, the `UnsafeUnpin` trait is provided.
112 /// Implementing this trait is logically equivalent to implementing [`Unpin`] -
113 /// this crate will generate an [`Unpin`] impl for your type that 'forwards' to
114 /// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type
115 /// uses structural pinning (otherwise, you wouldn't be using this crate!),
116 /// you must be sure that your `UnsafeUnpin` impls follows all of
117 /// the requirements for an [`Unpin`] impl of a structurally-pinned type.
118 ///
119 /// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not*
120 /// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`].
121 /// This is effectively the same thing as adding a [`PhantomPinned`] to your
122 /// type.
123 ///
124 /// Since this trait is `unsafe`, impls of it will be detected by the
125 /// `unsafe_code` lint, and by tools like [`cargo geiger`][cargo-geiger].
126 ///
127 /// # Examples
128 ///
129 /// An `UnsafeUnpin` impl which, in addition to requiring that structurally
130 /// pinned fields be [`Unpin`], imposes an additional requirement:
131 ///
132 /// ```rust
133 /// use pin_project::{pin_project, UnsafeUnpin};
134 ///
135 /// #[pin_project(UnsafeUnpin)]
136 /// struct Struct<K, V> {
137 ///     #[pin]
138 ///     field_1: K,
139 ///     field_2: V,
140 /// }
141 ///
142 /// unsafe impl<K, V> UnsafeUnpin for Struct<K, V> where K: Unpin + Clone {}
143 /// ```
144 ///
145 /// [`PhantomPinned`]: core::marker::PhantomPinned
146 /// [cargo-geiger]: https://github.com/rust-secure-code/cargo-geiger
147 /// [pin-projection]: core::pin#projections-and-structural-pinning
148 /// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
149 pub unsafe trait UnsafeUnpin {}
150 
151 // Not public API.
152 #[doc(hidden)]
153 pub mod __private {
154     use core::mem::ManuallyDrop;
155     #[doc(hidden)]
156     pub use core::{
157         marker::{PhantomData, PhantomPinned, Unpin},
158         ops::Drop,
159         pin::Pin,
160         ptr,
161     };
162 
163     #[doc(hidden)]
164     pub use pin_project_internal::__PinProjectInternalDerive;
165 
166     use super::UnsafeUnpin;
167 
168     // An internal trait used for custom implementations of [`Drop`].
169     //
170     // **Do not call or implement this trait directly.**
171     //
172     // # Why this trait is private and `#[pinned_drop]` attribute is needed?
173     //
174     // Implementing `PinnedDrop::drop` is safe, but calling it is not safe.
175     // This is because destructors can be called multiple times in safe code and
176     // [double dropping is unsound][rust-lang/rust#62360].
177     //
178     // Ideally, it would be desirable to be able to forbid manual calls in
179     // the same way as [`Drop::drop`], but the library cannot do it. So, by using
180     // macros and replacing them with private traits,
181     // this crate prevent users from calling `PinnedDrop::drop` in safe code.
182     //
183     // This allows implementing [`Drop`] safely using `#[pinned_drop]`.
184     // Also by using the [`drop`] function just like dropping a type that directly
185     // implements [`Drop`], can drop safely a type that implements `PinnedDrop`.
186     //
187     // [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360
188     #[doc(hidden)]
189     pub trait PinnedDrop {
190         #[doc(hidden)]
drop(self: Pin<&mut Self>)191         unsafe fn drop(self: Pin<&mut Self>);
192     }
193 
194     // This is an internal helper struct used by `pin-project-internal`.
195     // This allows us to force an error if the user tries to provide
196     // a regular `Unpin` impl when they specify the `UnsafeUnpin` argument.
197     // This is why we need Wrapper:
198     //
199     // Supposed we have the following code:
200     //
201     // ```rust
202     // #[pin_project(UnsafeUnpin)]
203     // struct MyStruct<T> {
204     //     #[pin] field: T
205     // }
206     //
207     // impl<T> Unpin for MyStruct<T> where MyStruct<T>: UnsafeUnpin {} // generated by pin-project-internal
208     // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
209     // ```
210     //
211     // We want this code to be rejected - the user is completely bypassing
212     // `UnsafeUnpin`, and providing an unsound Unpin impl in safe code!
213     //
214     // Unfortunately, the Rust compiler will accept the above code.
215     // Because MyStruct is declared in the same crate as the user-provided impl,
216     // the compiler will notice that `MyStruct<T>: UnsafeUnpin` never holds.
217     //
218     // The solution is to introduce the `Wrapper` struct, which is defined
219     // in the `pin-project` crate.
220     //
221     // We now have code that looks like this:
222     //
223     // ```rust
224     // impl<T> Unpin for MyStruct<T> where Wrapper<MyStruct<T>>: UnsafeUnpin {} // generated by pin-project-internal
225     // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
226     // ```
227     //
228     // We also have `unsafe impl<T> UnsafeUnpin for Wrapper<T> where T: UnsafeUnpin {}`
229     // in the `pin-project` crate.
230     //
231     // Now, our generated impl has a bound involving a type defined in another
232     // crate - Wrapper. This will cause rust to conservatively assume that
233     // `Wrapper<MyStruct<T>>: UnsafeUnpin` holds, in the interest of preserving
234     // forwards compatibility (in case such an impl is added for Wrapper<T> in
235     // a new version of the crate).
236     //
237     // This will cause rust to reject any other `Unpin` impls for MyStruct<T>,
238     // since it will assume that our generated impl could potentially apply in
239     // any situation.
240     //
241     // This achieves the desired effect - when the user writes
242     // `#[pin_project(UnsafeUnpin)]`, the user must either provide no impl of
243     // `UnsafeUnpin` (which is equivalent to making the type never implement
244     // Unpin), or provide an impl of `UnsafeUnpin`. It is impossible for them to
245     // provide an impl of `Unpin`
246     #[doc(hidden)]
247     pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T);
248 
249     unsafe impl<T: ?Sized> UnsafeUnpin for Wrapper<'_, T> where T: UnsafeUnpin {}
250 
251     // This is an internal helper struct used by `pin-project-internal`.
252     //
253     // See https://github.com/taiki-e/pin-project/pull/53 for more details.
254     #[doc(hidden)]
255     pub struct AlwaysUnpin<'a, T>(PhantomData<&'a ()>, PhantomData<T>);
256 
257     impl<T> Unpin for AlwaysUnpin<'_, T> {}
258 
259     // This is an internal helper used to ensure a value is dropped.
260     #[doc(hidden)]
261     pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T);
262 
263     impl<T: ?Sized> UnsafeDropInPlaceGuard<T> {
264         #[doc(hidden)]
new(ptr: *mut T) -> Self265         pub unsafe fn new(ptr: *mut T) -> Self {
266             Self(ptr)
267         }
268     }
269 
270     impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> {
drop(&mut self)271         fn drop(&mut self) {
272             unsafe {
273                 ptr::drop_in_place(self.0);
274             }
275         }
276     }
277 
278     // This is an internal helper used to ensure a value is overwritten without
279     // its destructor being called.
280     #[doc(hidden)]
281     pub struct UnsafeOverwriteGuard<T> {
282         target: *mut T,
283         value: ManuallyDrop<T>,
284     }
285 
286     impl<T> UnsafeOverwriteGuard<T> {
287         #[doc(hidden)]
new(target: *mut T, value: T) -> Self288         pub unsafe fn new(target: *mut T, value: T) -> Self {
289             Self { target, value: ManuallyDrop::new(value) }
290         }
291     }
292 
293     impl<T> Drop for UnsafeOverwriteGuard<T> {
drop(&mut self)294         fn drop(&mut self) {
295             unsafe {
296                 ptr::write(self.target, ptr::read(&*self.value));
297             }
298         }
299     }
300 }
301