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]
16mod error;
17
18#[macro_use]
19mod utils;
20
21mod pin_project;
22mod pinned_drop;
23
24use 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::{pin_project, UnsafeUnpin};
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/1/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]
485pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream {
486 pin_project::attribute(&args.into(), input: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]
567pub 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))]
575pub fn __pin_project_internal_derive(input: TokenStream) -> TokenStream {
576 pin_project::derive(input:input.into()).into()
577}
578