| 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
| 2 | |
| 3 | //! Implementation detail of the `pin-project` crate. - **do not use directly** |
| 4 | |
| 5 | #![doc (test( |
| 6 | no_crate_inject, |
| 7 | attr( |
| 8 | deny(warnings, rust_2018_idioms, single_use_lifetimes), |
| 9 | allow(dead_code, unused_variables) |
| 10 | ) |
| 11 | ))] |
| 12 | #![forbid (unsafe_code)] |
| 13 | #![allow (clippy::needless_doctest_main)] |
| 14 | |
| 15 | #[macro_use ] |
| 16 | mod error; |
| 17 | |
| 18 | #[macro_use ] |
| 19 | mod utils; |
| 20 | |
| 21 | mod pin_project; |
| 22 | mod pinned_drop; |
| 23 | |
| 24 | use proc_macro::TokenStream; |
| 25 | |
| 26 | /// An attribute that creates projection types covering all the fields of |
| 27 | /// struct or enum. |
| 28 | /// |
| 29 | /// This attribute creates projection types according to the following rules: |
| 30 | /// |
| 31 | /// - For the fields that use `#[pin]` attribute, create the pinned reference to |
| 32 | /// the field. |
| 33 | /// - For the other fields, create a normal reference to the field. |
| 34 | /// |
| 35 | /// And the following methods are implemented on the original type: |
| 36 | /// |
| 37 | /// ``` |
| 38 | /// # use std::pin::Pin; |
| 39 | /// # type Projection<'a> = &'a (); |
| 40 | /// # type ProjectionRef<'a> = &'a (); |
| 41 | /// # trait Dox { |
| 42 | /// fn project(self: Pin<&mut Self>) -> Projection<'_>; |
| 43 | /// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>; |
| 44 | /// # } |
| 45 | /// ``` |
| 46 | /// |
| 47 | /// By passing an argument with the same name as the method to the attribute, |
| 48 | /// you can name the projection type returned from the method. This allows you |
| 49 | /// to use pattern matching on the projected types. |
| 50 | /// |
| 51 | /// ``` |
| 52 | /// # use pin_project::pin_project; |
| 53 | /// # use std::pin::Pin; |
| 54 | /// #[pin_project(project = EnumProj)] |
| 55 | /// enum Enum<T> { |
| 56 | /// Variant(#[pin] T), |
| 57 | /// } |
| 58 | /// |
| 59 | /// impl<T> Enum<T> { |
| 60 | /// fn method(self: Pin<&mut Self>) { |
| 61 | /// let this: EnumProj<'_, T> = self.project(); |
| 62 | /// match this { |
| 63 | /// EnumProj::Variant(x) => { |
| 64 | /// let _: Pin<&mut T> = x; |
| 65 | /// } |
| 66 | /// } |
| 67 | /// } |
| 68 | /// } |
| 69 | /// ``` |
| 70 | /// |
| 71 | /// Note that the projection types returned by `project` and `project_ref` have |
| 72 | /// an additional lifetime at the beginning of generics. |
| 73 | /// |
| 74 | /// ```text |
| 75 | /// let this: EnumProj<'_, T> = self.project(); |
| 76 | /// ^^ |
| 77 | /// ``` |
| 78 | /// |
| 79 | /// The visibility of the projected types and projection methods is based on the |
| 80 | /// original type. However, if the visibility of the original type is `pub`, the |
| 81 | /// visibility of the projected types and the projection methods is downgraded |
| 82 | /// to `pub(crate)`. |
| 83 | /// |
| 84 | /// # Safety |
| 85 | /// |
| 86 | /// This attribute is completely safe. In the absence of other `unsafe` code |
| 87 | /// *that you write*, it is impossible to cause [undefined |
| 88 | /// behavior][undefined-behavior] with this attribute. |
| 89 | /// |
| 90 | /// This is accomplished by enforcing the four requirements for pin projection |
| 91 | /// stated in [the Rust documentation][pin-projection]: |
| 92 | /// |
| 93 | /// 1. The struct must only be [`Unpin`] if all the structural fields are |
| 94 | /// [`Unpin`]. |
| 95 | /// |
| 96 | /// To enforce this, this attribute will automatically generate an [`Unpin`] |
| 97 | /// implementation for you, which will require that all structurally pinned |
| 98 | /// fields be [`Unpin`]. |
| 99 | /// |
| 100 | /// If you attempt to provide an [`Unpin`] impl, the blanket impl will then |
| 101 | /// apply to your type, causing a compile-time error due to the conflict with |
| 102 | /// the second impl. |
| 103 | /// |
| 104 | /// If you wish to provide a manual [`Unpin`] impl, you can do so via the |
| 105 | /// [`UnsafeUnpin`][unsafe-unpin] argument. |
| 106 | /// |
| 107 | /// 2. The destructor of the struct must not move structural fields out of its |
| 108 | /// argument. |
| 109 | /// |
| 110 | /// To enforce this, this attribute will generate code like this: |
| 111 | /// |
| 112 | /// ``` |
| 113 | /// struct MyStruct {} |
| 114 | /// trait MyStructMustNotImplDrop {} |
| 115 | /// # #[allow (unknown_lints, drop_bounds)] |
| 116 | /// impl<T: Drop> MyStructMustNotImplDrop for T {} |
| 117 | /// impl MyStructMustNotImplDrop for MyStruct {} |
| 118 | /// ``` |
| 119 | /// |
| 120 | /// If you attempt to provide an [`Drop`] impl, the blanket impl will then |
| 121 | /// apply to your type, causing a compile-time error due to the conflict with |
| 122 | /// the second impl. |
| 123 | /// |
| 124 | /// If you wish to provide a custom [`Drop`] impl, you can annotate an impl |
| 125 | /// with [`#[pinned_drop]`][pinned-drop]. This impl takes a pinned version of |
| 126 | /// your struct - that is, [`Pin`]`<&mut MyStruct>` where `MyStruct` is the |
| 127 | /// type of your struct. |
| 128 | /// |
| 129 | /// You can call `.project()` on this type as usual, along with any other |
| 130 | /// methods you have defined. Because your code is never provided with |
| 131 | /// a `&mut MyStruct`, it is impossible to move out of pin-projectable |
| 132 | /// fields in safe code in your destructor. |
| 133 | /// |
| 134 | /// 3. You must make sure that you uphold the [`Drop` |
| 135 | /// guarantee][drop-guarantee]: once your struct is pinned, the memory that |
| 136 | /// contains the content is not overwritten or deallocated without calling |
| 137 | /// the content's destructors. |
| 138 | /// |
| 139 | /// Safe code doesn't need to worry about this - the only way to violate |
| 140 | /// this requirement is to manually deallocate memory (which is `unsafe`), |
| 141 | /// or to overwrite a field with something else. |
| 142 | /// Because your custom destructor takes [`Pin`]`<&mut MyStruct>`, it's |
| 143 | /// impossible to obtain a mutable reference to a pin-projected field in safe |
| 144 | /// code. |
| 145 | /// |
| 146 | /// 4. You must not offer any other operations that could lead to data being |
| 147 | /// moved out of the structural fields when your type is pinned. |
| 148 | /// |
| 149 | /// As with requirement 3, it is impossible for safe code to violate this. |
| 150 | /// This crate ensures that safe code can never obtain a mutable reference to |
| 151 | /// `#[pin]` fields, which prevents you from ever moving out of them in safe |
| 152 | /// code. |
| 153 | /// |
| 154 | /// Pin projections are also incompatible with [`#[repr(packed)]`][repr-packed] |
| 155 | /// types. Attempting to use this attribute on a `#[repr(packed)]` type results |
| 156 | /// in a compile-time error. |
| 157 | /// |
| 158 | /// # Examples |
| 159 | /// |
| 160 | /// `#[pin_project]` can be used on structs and enums. |
| 161 | /// |
| 162 | /// ``` |
| 163 | /// use std::pin::Pin; |
| 164 | /// |
| 165 | /// use pin_project::pin_project; |
| 166 | /// |
| 167 | /// #[pin_project] |
| 168 | /// struct Struct<T, U> { |
| 169 | /// #[pin] |
| 170 | /// pinned: T, |
| 171 | /// unpinned: U, |
| 172 | /// } |
| 173 | /// |
| 174 | /// impl<T, U> Struct<T, U> { |
| 175 | /// fn method(self: Pin<&mut Self>) { |
| 176 | /// let this = self.project(); |
| 177 | /// let _: Pin<&mut T> = this.pinned; |
| 178 | /// let _: &mut U = this.unpinned; |
| 179 | /// } |
| 180 | /// } |
| 181 | /// ``` |
| 182 | /// |
| 183 | /// ``` |
| 184 | /// use std::pin::Pin; |
| 185 | /// |
| 186 | /// use pin_project::pin_project; |
| 187 | /// |
| 188 | /// #[pin_project] |
| 189 | /// struct TupleStruct<T, U>(#[pin] T, U); |
| 190 | /// |
| 191 | /// impl<T, U> TupleStruct<T, U> { |
| 192 | /// fn method(self: Pin<&mut Self>) { |
| 193 | /// let this = self.project(); |
| 194 | /// let _: Pin<&mut T> = this.0; |
| 195 | /// let _: &mut U = this.1; |
| 196 | /// } |
| 197 | /// } |
| 198 | /// ``` |
| 199 | /// |
| 200 | /// To use `#[pin_project]` on enums, you need to name the projection type |
| 201 | /// returned from the method. |
| 202 | /// |
| 203 | /// ``` |
| 204 | /// use std::pin::Pin; |
| 205 | /// |
| 206 | /// use pin_project::pin_project; |
| 207 | /// |
| 208 | /// #[pin_project(project = EnumProj)] |
| 209 | /// enum Enum<T, U> { |
| 210 | /// Tuple(#[pin] T), |
| 211 | /// Struct { field: U }, |
| 212 | /// Unit, |
| 213 | /// } |
| 214 | /// |
| 215 | /// impl<T, U> Enum<T, U> { |
| 216 | /// fn method(self: Pin<&mut Self>) { |
| 217 | /// match self.project() { |
| 218 | /// EnumProj::Tuple(x) => { |
| 219 | /// let _: Pin<&mut T> = x; |
| 220 | /// } |
| 221 | /// EnumProj::Struct { field } => { |
| 222 | /// let _: &mut U = field; |
| 223 | /// } |
| 224 | /// EnumProj::Unit => {} |
| 225 | /// } |
| 226 | /// } |
| 227 | /// } |
| 228 | /// ``` |
| 229 | /// |
| 230 | /// When `#[pin_project]` is used on enums, only named projection types and |
| 231 | /// methods are generated because there is no way to access variants of |
| 232 | /// projected types without naming it. |
| 233 | /// For example, in the above example, only the `project` method is generated, |
| 234 | /// and the `project_ref` method is not generated. |
| 235 | /// (When `#[pin_project]` is used on structs, both methods are always generated.) |
| 236 | /// |
| 237 | /// ```compile_fail,E0599 |
| 238 | /// # use pin_project::pin_project; |
| 239 | /// # use std::pin::Pin; |
| 240 | /// # |
| 241 | /// # #[pin_project(project = EnumProj)] |
| 242 | /// # enum Enum<T, U> { |
| 243 | /// # Tuple(#[pin] T), |
| 244 | /// # Struct { field: U }, |
| 245 | /// # Unit, |
| 246 | /// # } |
| 247 | /// # |
| 248 | /// impl<T, U> Enum<T, U> { |
| 249 | /// fn call_project_ref(self: Pin<&Self>) { |
| 250 | /// let _this = self.project_ref(); |
| 251 | /// //~^ ERROR no method named `project_ref` found for struct `Pin<&Enum<T, U>>` in the current scope |
| 252 | /// } |
| 253 | /// } |
| 254 | /// ``` |
| 255 | /// |
| 256 | /// If you want to call `.project()` multiple times or later use the |
| 257 | /// original [`Pin`] type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid |
| 258 | /// consuming the [`Pin`]. |
| 259 | /// |
| 260 | /// ``` |
| 261 | /// use std::pin::Pin; |
| 262 | /// |
| 263 | /// use pin_project::pin_project; |
| 264 | /// |
| 265 | /// #[pin_project] |
| 266 | /// struct Struct<T> { |
| 267 | /// #[pin] |
| 268 | /// field: T, |
| 269 | /// } |
| 270 | /// |
| 271 | /// impl<T> Struct<T> { |
| 272 | /// fn call_project_twice(mut self: Pin<&mut Self>) { |
| 273 | /// // `project` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`. |
| 274 | /// self.as_mut().project(); |
| 275 | /// self.as_mut().project(); |
| 276 | /// } |
| 277 | /// } |
| 278 | /// ``` |
| 279 | /// |
| 280 | /// # `!Unpin` |
| 281 | /// |
| 282 | /// If you want to ensure that [`Unpin`] is not implemented, use the `!Unpin` |
| 283 | /// argument to `#[pin_project]`. |
| 284 | /// |
| 285 | /// ``` |
| 286 | /// use pin_project::pin_project; |
| 287 | /// |
| 288 | /// #[pin_project(!Unpin)] |
| 289 | /// struct Struct<T> { |
| 290 | /// field: T, |
| 291 | /// } |
| 292 | /// ``` |
| 293 | /// |
| 294 | /// This is equivalent to using `#[pin]` attribute for the [`PhantomPinned`] |
| 295 | /// field. |
| 296 | /// |
| 297 | /// ``` |
| 298 | /// use std::marker::PhantomPinned; |
| 299 | /// |
| 300 | /// use pin_project::pin_project; |
| 301 | /// |
| 302 | /// #[pin_project] |
| 303 | /// struct Struct<T> { |
| 304 | /// field: T, |
| 305 | /// #[pin] // <------ This `#[pin]` is required to make `Struct` to `!Unpin`. |
| 306 | /// _pin: PhantomPinned, |
| 307 | /// } |
| 308 | /// ``` |
| 309 | /// |
| 310 | /// Note that using [`PhantomPinned`] without `#[pin]` attribute has no effect. |
| 311 | /// |
| 312 | /// # `UnsafeUnpin` |
| 313 | /// |
| 314 | /// If you want to implement [`Unpin`] manually, you must use the `UnsafeUnpin` |
| 315 | /// argument to `#[pin_project]`. |
| 316 | /// |
| 317 | /// ``` |
| 318 | /// use pin_project::{UnsafeUnpin, pin_project}; |
| 319 | /// |
| 320 | /// #[pin_project(UnsafeUnpin)] |
| 321 | /// struct Struct<T, U> { |
| 322 | /// #[pin] |
| 323 | /// pinned: T, |
| 324 | /// unpinned: U, |
| 325 | /// } |
| 326 | /// |
| 327 | /// unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {} |
| 328 | /// ``` |
| 329 | /// |
| 330 | /// Note the usage of the unsafe [`UnsafeUnpin`] trait, instead of the usual |
| 331 | /// [`Unpin`] trait. [`UnsafeUnpin`] behaves exactly like [`Unpin`], except that |
| 332 | /// is unsafe to implement. This unsafety comes from the fact that pin |
| 333 | /// projections are being used. If you implement [`UnsafeUnpin`], you must |
| 334 | /// ensure that it is only implemented when all pin-projected fields implement |
| 335 | /// [`Unpin`]. |
| 336 | /// |
| 337 | /// See [`UnsafeUnpin`] trait for more details. |
| 338 | /// |
| 339 | /// # `#[pinned_drop]` |
| 340 | /// |
| 341 | /// In order to correctly implement pin projections, a type's [`Drop`] impl must |
| 342 | /// not move out of any structurally pinned fields. Unfortunately, |
| 343 | /// [`Drop::drop`] takes `&mut Self`, not [`Pin`]`<&mut Self>`. |
| 344 | /// |
| 345 | /// To ensure that this requirement is upheld, the `#[pin_project]` attribute |
| 346 | /// will provide a [`Drop`] impl for you. This [`Drop`] impl will delegate to |
| 347 | /// an impl block annotated with `#[pinned_drop]` if you use the `PinnedDrop` |
| 348 | /// argument to `#[pin_project]`. |
| 349 | /// |
| 350 | /// This impl block acts just like a normal [`Drop`] impl, |
| 351 | /// except for the following two: |
| 352 | /// |
| 353 | /// - `drop` method takes [`Pin`]`<&mut Self>` |
| 354 | /// - Name of the trait is `PinnedDrop`. |
| 355 | /// |
| 356 | /// ``` |
| 357 | /// # use std::pin::Pin; |
| 358 | /// pub trait PinnedDrop { |
| 359 | /// fn drop(self: Pin<&mut Self>); |
| 360 | /// } |
| 361 | /// ``` |
| 362 | /// |
| 363 | /// `#[pin_project]` implements the actual [`Drop`] trait via `PinnedDrop` you |
| 364 | /// implemented. To drop a type that implements `PinnedDrop`, use the [`drop`] |
| 365 | /// function just like dropping a type that directly implements [`Drop`]. |
| 366 | /// |
| 367 | /// In particular, it will never be called more than once, just like |
| 368 | /// [`Drop::drop`]. |
| 369 | /// |
| 370 | /// For example: |
| 371 | /// |
| 372 | /// ``` |
| 373 | /// use std::{fmt::Debug, pin::Pin}; |
| 374 | /// |
| 375 | /// use pin_project::{pin_project, pinned_drop}; |
| 376 | /// |
| 377 | /// #[pin_project(PinnedDrop)] |
| 378 | /// struct PrintOnDrop<T: Debug, U: Debug> { |
| 379 | /// #[pin] |
| 380 | /// pinned_field: T, |
| 381 | /// unpin_field: U, |
| 382 | /// } |
| 383 | /// |
| 384 | /// #[pinned_drop] |
| 385 | /// impl<T: Debug, U: Debug> PinnedDrop for PrintOnDrop<T, U> { |
| 386 | /// fn drop(self: Pin<&mut Self>) { |
| 387 | /// println!("Dropping pinned field: {:?}" , self.pinned_field); |
| 388 | /// println!("Dropping unpin field: {:?}" , self.unpin_field); |
| 389 | /// } |
| 390 | /// } |
| 391 | /// |
| 392 | /// fn main() { |
| 393 | /// let _x = PrintOnDrop { pinned_field: true, unpin_field: 40 }; |
| 394 | /// } |
| 395 | /// ``` |
| 396 | /// |
| 397 | /// See also [`#[pinned_drop]`][macro@pinned_drop] attribute. |
| 398 | /// |
| 399 | /// # `project_replace` method |
| 400 | /// |
| 401 | /// In addition to the `project` and `project_ref` methods which are always |
| 402 | /// provided when you use the `#[pin_project]` attribute, there is a third |
| 403 | /// method, `project_replace` which can be useful in some situations. It is |
| 404 | /// equivalent to [`Pin::set`], except that the unpinned fields are moved and |
| 405 | /// returned, instead of being dropped in-place. |
| 406 | /// |
| 407 | /// ``` |
| 408 | /// # use std::pin::Pin; |
| 409 | /// # type ProjectionOwned = (); |
| 410 | /// # trait Dox { |
| 411 | /// fn project_replace(self: Pin<&mut Self>, other: Self) -> ProjectionOwned; |
| 412 | /// # } |
| 413 | /// ``` |
| 414 | /// |
| 415 | /// The `ProjectionOwned` type is identical to the `Self` type, except that |
| 416 | /// all pinned fields have been replaced by equivalent [`PhantomData`] types. |
| 417 | /// |
| 418 | /// This method is opt-in, because it is only supported for [`Sized`] types, and |
| 419 | /// because it is incompatible with the [`#[pinned_drop]`][pinned-drop] |
| 420 | /// attribute described above. It can be enabled by using |
| 421 | /// `#[pin_project(project_replace)]`. |
| 422 | /// |
| 423 | /// For example: |
| 424 | /// |
| 425 | /// ``` |
| 426 | /// use std::{marker::PhantomData, pin::Pin}; |
| 427 | /// |
| 428 | /// use pin_project::pin_project; |
| 429 | /// |
| 430 | /// #[pin_project(project_replace)] |
| 431 | /// struct Struct<T, U> { |
| 432 | /// #[pin] |
| 433 | /// pinned_field: T, |
| 434 | /// unpinned_field: U, |
| 435 | /// } |
| 436 | /// |
| 437 | /// impl<T, U> Struct<T, U> { |
| 438 | /// fn method(self: Pin<&mut Self>, other: Self) { |
| 439 | /// let this = self.project_replace(other); |
| 440 | /// let _: U = this.unpinned_field; |
| 441 | /// let _: PhantomData<T> = this.pinned_field; |
| 442 | /// } |
| 443 | /// } |
| 444 | /// ``` |
| 445 | /// |
| 446 | /// By passing the value to the `project_replace` argument, you can name the |
| 447 | /// returned type of the `project_replace` method. This is necessary whenever |
| 448 | /// destructuring the return type of the `project_replace` method, and work in exactly |
| 449 | /// the same way as the `project` and `project_ref` arguments. |
| 450 | /// |
| 451 | /// ``` |
| 452 | /// use pin_project::pin_project; |
| 453 | /// |
| 454 | /// #[pin_project(project_replace = EnumProjOwn)] |
| 455 | /// enum Enum<T, U> { |
| 456 | /// A { |
| 457 | /// #[pin] |
| 458 | /// pinned_field: T, |
| 459 | /// unpinned_field: U, |
| 460 | /// }, |
| 461 | /// B, |
| 462 | /// } |
| 463 | /// |
| 464 | /// let mut x = Box::pin(Enum::A { pinned_field: 42, unpinned_field: "hello" }); |
| 465 | /// |
| 466 | /// match x.as_mut().project_replace(Enum::B) { |
| 467 | /// EnumProjOwn::A { unpinned_field, .. } => assert_eq!(unpinned_field, "hello" ), |
| 468 | /// EnumProjOwn::B => unreachable!(), |
| 469 | /// } |
| 470 | /// ``` |
| 471 | /// |
| 472 | /// [`PhantomData`]: core::marker::PhantomData |
| 473 | /// [`PhantomPinned`]: core::marker::PhantomPinned |
| 474 | /// [`Pin::as_mut`]: core::pin::Pin::as_mut |
| 475 | /// [`Pin::set`]: core::pin::Pin::set |
| 476 | /// [`Pin`]: core::pin::Pin |
| 477 | /// [`UnsafeUnpin`]: https://docs.rs/pin-project/latest/pin_project/trait.UnsafeUnpin.html |
| 478 | /// [drop-guarantee]: core::pin#drop-guarantee |
| 479 | /// [pin-projection]: core::pin#projections-and-structural-pinning |
| 480 | /// [pinned-drop]: macro@pin_project#pinned_drop |
| 481 | /// [repr-packed]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprpacked |
| 482 | /// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html |
| 483 | /// [unsafe-unpin]: macro@pin_project#unsafeunpin |
| 484 | #[proc_macro_attribute ] |
| 485 | pub fn pin_project (args: TokenStream, input: TokenStream) -> TokenStream { |
| 486 | pin_project::attribute(&args.into(), input.into()).into() |
| 487 | } |
| 488 | |
| 489 | /// An attribute used for custom implementations of [`Drop`]. |
| 490 | /// |
| 491 | /// This attribute is used in conjunction with the `PinnedDrop` argument to |
| 492 | /// the [`#[pin_project]`][macro@pin_project] attribute. |
| 493 | /// |
| 494 | /// The impl block annotated with this attribute acts just like a normal |
| 495 | /// [`Drop`] impl, except for the following two: |
| 496 | /// |
| 497 | /// - `drop` method takes [`Pin`]`<&mut Self>` |
| 498 | /// - Name of the trait is `PinnedDrop`. |
| 499 | /// |
| 500 | /// ``` |
| 501 | /// # use std::pin::Pin; |
| 502 | /// pub trait PinnedDrop { |
| 503 | /// fn drop(self: Pin<&mut Self>); |
| 504 | /// } |
| 505 | /// ``` |
| 506 | /// |
| 507 | /// `#[pin_project]` implements the actual [`Drop`] trait via `PinnedDrop` you |
| 508 | /// implemented. To drop a type that implements `PinnedDrop`, use the [`drop`] |
| 509 | /// function just like dropping a type that directly implements [`Drop`]. |
| 510 | /// |
| 511 | /// In particular, it will never be called more than once, just like |
| 512 | /// [`Drop::drop`]. |
| 513 | /// |
| 514 | /// # Examples |
| 515 | /// |
| 516 | /// ``` |
| 517 | /// use std::pin::Pin; |
| 518 | /// |
| 519 | /// use pin_project::{pin_project, pinned_drop}; |
| 520 | /// |
| 521 | /// #[pin_project(PinnedDrop)] |
| 522 | /// struct PrintOnDrop { |
| 523 | /// #[pin] |
| 524 | /// field: u8, |
| 525 | /// } |
| 526 | /// |
| 527 | /// #[pinned_drop] |
| 528 | /// impl PinnedDrop for PrintOnDrop { |
| 529 | /// fn drop(self: Pin<&mut Self>) { |
| 530 | /// println!("Dropping: {}" , self.field); |
| 531 | /// } |
| 532 | /// } |
| 533 | /// |
| 534 | /// fn main() { |
| 535 | /// let _x = PrintOnDrop { field: 50 }; |
| 536 | /// } |
| 537 | /// ``` |
| 538 | /// |
| 539 | /// See also ["pinned-drop" section of `#[pin_project]` attribute][pinned-drop]. |
| 540 | /// |
| 541 | /// # Why `#[pinned_drop]` attribute is needed? |
| 542 | /// |
| 543 | /// Implementing `PinnedDrop::drop` is safe, but calling it is not safe. |
| 544 | /// This is because destructors can be called multiple times in safe code and |
| 545 | /// [double dropping is unsound][rust-lang/rust#62360]. |
| 546 | /// |
| 547 | /// Ideally, it would be desirable to be able to forbid manual calls in |
| 548 | /// the same way as [`Drop::drop`], but the library cannot do it. So, by using |
| 549 | /// macros and replacing them with private traits like the following, |
| 550 | /// this crate prevent users from calling `PinnedDrop::drop` in safe code. |
| 551 | /// |
| 552 | /// ``` |
| 553 | /// # use std::pin::Pin; |
| 554 | /// pub trait PinnedDrop { |
| 555 | /// unsafe fn drop(self: Pin<&mut Self>); |
| 556 | /// } |
| 557 | /// ``` |
| 558 | /// |
| 559 | /// This allows implementing [`Drop`] safely using `#[pinned_drop]`. |
| 560 | /// Also by using the [`drop`] function just like dropping a type that directly |
| 561 | /// implements [`Drop`], can drop safely a type that implements `PinnedDrop`. |
| 562 | /// |
| 563 | /// [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360 |
| 564 | /// [`Pin`]: core::pin::Pin |
| 565 | /// [pinned-drop]: macro@pin_project#pinned_drop |
| 566 | #[proc_macro_attribute ] |
| 567 | pub fn pinned_drop (args: TokenStream, input: TokenStream) -> TokenStream { |
| 568 | let input: ItemImpl = syn::parse_macro_input!(input); |
| 569 | pinned_drop::attribute(&args.into(), input).into() |
| 570 | } |
| 571 | |
| 572 | // Not public API. |
| 573 | #[doc (hidden)] |
| 574 | #[proc_macro_derive (__PinProjectInternalDerive, attributes(pin))] |
| 575 | pub fn __pin_project_internal_derive(input: TokenStream) -> TokenStream { |
| 576 | pin_project::derive(input.into()).into() |
| 577 | } |
| 578 | |