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)]
22extern crate proc_macro;
23
24#[macro_use]
25mod utils;
26
27mod pin_project;
28mod pinned_drop;
29
30use 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]
491pub 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]
573pub 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))]
581pub fn __pin_project_internal_derive(input: TokenStream) -> TokenStream {
582 pin_project::derive(input.into()).into()
583}
584