Chih-Hung Hsieh | 6f3e927 | 2020-05-13 16:08:03 -0700 | [diff] [blame] | 1 | //! 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 Huang | 2960bb3 | 2020-05-18 15:51:06 -0700 | [diff] [blame] | 37 | #![doc(html_root_url = "https://docs.rs/pin-project/0.4.17")] |
Chih-Hung Hsieh | 6f3e927 | 2020-05-13 16:08:03 -0700 | [diff] [blame] | 38 | #![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 Huang | 2960bb3 | 2020-05-18 15:51:06 -0700 | [diff] [blame] | 44 | // mem::take and #[non_exhaustive] requires Rust 1.40 |
| 45 | #![allow(clippy::mem_replace_with_default, clippy::manual_non_exhaustive)] |
Chih-Hung Hsieh | 6f3e927 | 2020-05-13 16:08:03 -0700 | [diff] [blame] | 46 | #![allow(clippy::needless_doctest_main)] |
| 47 | |
| 48 | #[doc(inline)] |
| 49 | pub use pin_project_internal::pin_project; |
| 50 | |
| 51 | #[doc(inline)] |
| 52 | pub use pin_project_internal::pinned_drop; |
| 53 | |
| 54 | #[doc(inline)] |
| 55 | pub use pin_project_internal::project; |
| 56 | |
| 57 | #[doc(inline)] |
| 58 | pub use pin_project_internal::project_ref; |
| 59 | |
| 60 | #[doc(inline)] |
| 61 | pub 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 |
| 117 | pub unsafe trait UnsafeUnpin {} |
| 118 | |
| 119 | // Not public API. |
| 120 | #[doc(hidden)] |
| 121 | pub 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)] |
| 236 | pub mod __reexport { |
| 237 | #[doc(hidden)] |
| 238 | pub use core::{marker, mem, ops, pin, ptr}; |
| 239 | } |