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