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