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