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