]>
Commit | Line | Data |
---|---|---|
5869c6ff XL |
1 | //! A lightweight version of [pin-project] written with declarative macros. |
2 | //! | |
3 | //! # Examples | |
4 | //! | |
5 | //! [`pin_project!`] macro creates a projection type covering all the fields of struct. | |
6 | //! | |
7 | //! ```rust | |
5869c6ff XL |
8 | //! use std::pin::Pin; |
9 | //! | |
6a06907d XL |
10 | //! use pin_project_lite::pin_project; |
11 | //! | |
5869c6ff XL |
12 | //! pin_project! { |
13 | //! struct Struct<T, U> { | |
14 | //! #[pin] | |
15 | //! pinned: T, | |
16 | //! unpinned: U, | |
17 | //! } | |
18 | //! } | |
19 | //! | |
20 | //! impl<T, U> Struct<T, U> { | |
21 | //! fn method(self: Pin<&mut Self>) { | |
22 | //! let this = self.project(); | |
23 | //! let _: Pin<&mut T> = this.pinned; // Pinned reference to the field | |
24 | //! let _: &mut U = this.unpinned; // Normal reference to the field | |
25 | //! } | |
26 | //! } | |
27 | //! ``` | |
28 | //! | |
29 | //! To use [`pin_project!`] on enums, you need to name the projection type | |
30 | //! returned from the method. | |
31 | //! | |
32 | //! ```rust | |
5869c6ff XL |
33 | //! use std::pin::Pin; |
34 | //! | |
6a06907d XL |
35 | //! use pin_project_lite::pin_project; |
36 | //! | |
5869c6ff XL |
37 | //! pin_project! { |
38 | //! #[project = EnumProj] | |
39 | //! enum Enum<T, U> { | |
40 | //! Variant { #[pin] pinned: T, unpinned: U }, | |
5099ac24 | 41 | //! } |
5869c6ff XL |
42 | //! } |
43 | //! | |
44 | //! impl<T, U> Enum<T, U> { | |
45 | //! fn method(self: Pin<&mut Self>) { | |
46 | //! match self.project() { | |
47 | //! EnumProj::Variant { pinned, unpinned } => { | |
48 | //! let _: Pin<&mut T> = pinned; | |
49 | //! let _: &mut U = unpinned; | |
50 | //! } | |
51 | //! } | |
52 | //! } | |
53 | //! } | |
54 | //! ``` | |
55 | //! | |
56 | //! # [pin-project] vs pin-project-lite | |
57 | //! | |
58 | //! Here are some similarities and differences compared to [pin-project]. | |
59 | //! | |
60 | //! ## Similar: Safety | |
61 | //! | |
62 | //! pin-project-lite guarantees safety in much the same way as [pin-project]. | |
63 | //! Both are completely safe unless you write other unsafe code. | |
64 | //! | |
65 | //! ## Different: Minimal design | |
66 | //! | |
67 | //! This library does not tackle as expansive of a range of use cases as | |
68 | //! [pin-project] does. If your use case is not already covered, please use | |
69 | //! [pin-project]. | |
70 | //! | |
71 | //! ## Different: No proc-macro related dependencies | |
72 | //! | |
73 | //! This is the **only** reason to use this crate. However, **if you already | |
74 | //! have proc-macro related dependencies in your crate's dependency graph, there | |
75 | //! is no benefit from using this crate.** (Note: There is almost no difference | |
76 | //! in the amount of code generated between [pin-project] and pin-project-lite.) | |
77 | //! | |
78 | //! ## Different: No useful error messages | |
79 | //! | |
80 | //! This macro does not handle any invalid input. So error messages are not to | |
81 | //! be useful in most cases. If you do need useful error messages, then upon | |
82 | //! error you can pass the same input to [pin-project] to receive a helpful | |
83 | //! description of the compile error. | |
84 | //! | |
5869c6ff XL |
85 | //! ## Different: No support for custom Unpin implementation |
86 | //! | |
87 | //! pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin]. | |
88 | //! | |
89 | //! ## Different: No support for tuple structs and tuple variants | |
90 | //! | |
91 | //! pin-project supports this. | |
92 | //! | |
93 | //! [not-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin | |
94 | //! [pin-project]: https://github.com/taiki-e/pin-project | |
5869c6ff XL |
95 | //! [unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin |
96 | ||
97 | #![no_std] | |
98 | #![doc(test( | |
99 | no_crate_inject, | |
100 | attr( | |
101 | deny(warnings, rust_2018_idioms, single_use_lifetimes), | |
102 | allow(dead_code, unused_variables) | |
103 | ) | |
104 | ))] | |
5099ac24 | 105 | #![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)] |
136023e0 | 106 | #![warn(clippy::default_trait_access, clippy::wildcard_imports)] |
5869c6ff XL |
107 | |
108 | /// A macro that creates a projection type covering all the fields of struct. | |
109 | /// | |
110 | /// This macro creates a projection type according to the following rules: | |
111 | /// | |
5099ac24 FG |
112 | /// - For the field that uses `#[pin]` attribute, makes the pinned reference to the field. |
113 | /// - For the other fields, makes the unpinned reference to the field. | |
5869c6ff XL |
114 | /// |
115 | /// And the following methods are implemented on the original type: | |
116 | /// | |
117 | /// ```rust | |
118 | /// # use std::pin::Pin; | |
119 | /// # type Projection<'a> = &'a (); | |
120 | /// # type ProjectionRef<'a> = &'a (); | |
121 | /// # trait Dox { | |
122 | /// fn project(self: Pin<&mut Self>) -> Projection<'_>; | |
123 | /// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>; | |
124 | /// # } | |
125 | /// ``` | |
126 | /// | |
127 | /// By passing an attribute with the same name as the method to the macro, | |
128 | /// you can name the projection type returned from the method. This allows you | |
129 | /// to use pattern matching on the projected types. | |
130 | /// | |
131 | /// ```rust | |
132 | /// # use pin_project_lite::pin_project; | |
133 | /// # use std::pin::Pin; | |
134 | /// pin_project! { | |
135 | /// #[project = EnumProj] | |
136 | /// enum Enum<T> { | |
137 | /// Variant { #[pin] field: T }, | |
138 | /// } | |
139 | /// } | |
140 | /// | |
141 | /// impl<T> Enum<T> { | |
142 | /// fn method(self: Pin<&mut Self>) { | |
143 | /// let this: EnumProj<'_, T> = self.project(); | |
144 | /// match this { | |
145 | /// EnumProj::Variant { field } => { | |
146 | /// let _: Pin<&mut T> = field; | |
147 | /// } | |
148 | /// } | |
149 | /// } | |
150 | /// } | |
151 | /// ``` | |
152 | /// | |
153 | /// By passing the `#[project_replace = MyProjReplace]` attribute you may create an additional | |
154 | /// method which allows the contents of `Pin<&mut Self>` to be replaced while simultaneously moving | |
155 | /// out all unpinned fields in `Self`. | |
156 | /// | |
157 | /// ```rust | |
158 | /// # use std::pin::Pin; | |
159 | /// # type MyProjReplace = (); | |
160 | /// # trait Dox { | |
161 | /// fn project_replace(self: Pin<&mut Self>, replacement: Self) -> MyProjReplace; | |
162 | /// # } | |
163 | /// ``` | |
164 | /// | |
5869c6ff XL |
165 | /// Also, note that the projection types returned by `project` and `project_ref` have |
166 | /// an additional lifetime at the beginning of generics. | |
167 | /// | |
168 | /// ```text | |
169 | /// let this: EnumProj<'_, T> = self.project(); | |
170 | /// ^^ | |
171 | /// ``` | |
172 | /// | |
173 | /// The visibility of the projected types and projection methods is based on the | |
174 | /// original type. However, if the visibility of the original type is `pub`, the | |
175 | /// visibility of the projected types and the projection methods is downgraded | |
176 | /// to `pub(crate)`. | |
177 | /// | |
178 | /// # Safety | |
179 | /// | |
180 | /// `pin_project!` macro guarantees safety in much the same way as [pin-project] crate. | |
181 | /// Both are completely safe unless you write other unsafe code. | |
182 | /// | |
183 | /// See [pin-project] crate for more details. | |
184 | /// | |
185 | /// # Examples | |
186 | /// | |
187 | /// ```rust | |
5869c6ff XL |
188 | /// use std::pin::Pin; |
189 | /// | |
6a06907d XL |
190 | /// use pin_project_lite::pin_project; |
191 | /// | |
5869c6ff XL |
192 | /// pin_project! { |
193 | /// struct Struct<T, U> { | |
194 | /// #[pin] | |
195 | /// pinned: T, | |
196 | /// unpinned: U, | |
197 | /// } | |
198 | /// } | |
199 | /// | |
200 | /// impl<T, U> Struct<T, U> { | |
201 | /// fn method(self: Pin<&mut Self>) { | |
202 | /// let this = self.project(); | |
203 | /// let _: Pin<&mut T> = this.pinned; // Pinned reference to the field | |
204 | /// let _: &mut U = this.unpinned; // Normal reference to the field | |
205 | /// } | |
206 | /// } | |
207 | /// ``` | |
208 | /// | |
209 | /// To use `pin_project!` on enums, you need to name the projection type | |
210 | /// returned from the method. | |
211 | /// | |
212 | /// ```rust | |
5869c6ff XL |
213 | /// use std::pin::Pin; |
214 | /// | |
6a06907d XL |
215 | /// use pin_project_lite::pin_project; |
216 | /// | |
5869c6ff XL |
217 | /// pin_project! { |
218 | /// #[project = EnumProj] | |
219 | /// enum Enum<T> { | |
220 | /// Struct { | |
221 | /// #[pin] | |
222 | /// field: T, | |
223 | /// }, | |
224 | /// Unit, | |
225 | /// } | |
226 | /// } | |
227 | /// | |
228 | /// impl<T> Enum<T> { | |
229 | /// fn method(self: Pin<&mut Self>) { | |
230 | /// match self.project() { | |
231 | /// EnumProj::Struct { field } => { | |
232 | /// let _: Pin<&mut T> = field; | |
233 | /// } | |
234 | /// EnumProj::Unit => {} | |
235 | /// } | |
236 | /// } | |
237 | /// } | |
238 | /// ``` | |
239 | /// | |
240 | /// If you want to call the `project()` method multiple times or later use the | |
241 | /// original [`Pin`] type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid | |
242 | /// consuming the [`Pin`]. | |
243 | /// | |
244 | /// ```rust | |
5869c6ff XL |
245 | /// use std::pin::Pin; |
246 | /// | |
6a06907d XL |
247 | /// use pin_project_lite::pin_project; |
248 | /// | |
5869c6ff XL |
249 | /// pin_project! { |
250 | /// struct Struct<T> { | |
251 | /// #[pin] | |
252 | /// field: T, | |
253 | /// } | |
254 | /// } | |
255 | /// | |
256 | /// impl<T> Struct<T> { | |
257 | /// fn call_project_twice(mut self: Pin<&mut Self>) { | |
258 | /// // `project` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`. | |
259 | /// self.as_mut().project(); | |
260 | /// self.as_mut().project(); | |
261 | /// } | |
262 | /// } | |
263 | /// ``` | |
264 | /// | |
265 | /// # `!Unpin` | |
266 | /// | |
267 | /// If you want to ensure that [`Unpin`] is not implemented, use `#[pin]` | |
268 | /// attribute for a [`PhantomPinned`] field. | |
269 | /// | |
270 | /// ```rust | |
5869c6ff XL |
271 | /// use std::marker::PhantomPinned; |
272 | /// | |
6a06907d XL |
273 | /// use pin_project_lite::pin_project; |
274 | /// | |
5869c6ff XL |
275 | /// pin_project! { |
276 | /// struct Struct<T> { | |
277 | /// field: T, | |
278 | /// #[pin] // <------ This `#[pin]` is required to make `Struct` to `!Unpin`. | |
279 | /// _pin: PhantomPinned, | |
280 | /// } | |
281 | /// } | |
282 | /// ``` | |
283 | /// | |
284 | /// Note that using [`PhantomPinned`] without `#[pin]` attribute has no effect. | |
285 | /// | |
286 | /// [`PhantomPinned`]: core::marker::PhantomPinned | |
287 | /// [`Pin::as_mut`]: core::pin::Pin::as_mut | |
288 | /// [`Pin`]: core::pin::Pin | |
289 | /// [pin-project]: https://github.com/taiki-e/pin-project | |
290 | #[macro_export] | |
291 | macro_rules! pin_project { | |
6a06907d | 292 | ($($tt:tt)*) => { |
5869c6ff | 293 | $crate::__pin_project_internal! { |
6a06907d | 294 | [][][][] |
5869c6ff XL |
295 | $($tt)* |
296 | } | |
297 | }; | |
298 | } | |
299 | ||
300 | // limitations: | |
5099ac24 FG |
301 | // - no support for tuple structs and tuple variant (wontfix). |
302 | // - no support for multiple trait/lifetime bounds. | |
303 | // - no support for `Self` in where clauses. (wontfix) | |
304 | // - no support for overlapping lifetime names. (wontfix) | |
305 | // - no interoperability with other field attributes. | |
306 | // - no useful error messages. (wontfix) | |
5869c6ff XL |
307 | // etc... |
308 | ||
5869c6ff XL |
309 | #[doc(hidden)] |
310 | #[macro_export] | |
923072b8 FG |
311 | macro_rules! __pin_project_expand { |
312 | ( | |
5869c6ff XL |
313 | [$($proj_mut_ident:ident)?] |
314 | [$($proj_ref_ident:ident)?] | |
315 | [$($proj_replace_ident:ident)?] | |
316 | [$proj_vis:vis] | |
5099ac24 | 317 | [$(#[$attrs:meta])* $vis:vis $struct_ty_ident:ident $ident:ident] |
5869c6ff XL |
318 | [$($def_generics:tt)*] |
319 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
320 | { | |
5099ac24 | 321 | $($body_data:tt)* |
5869c6ff | 322 | } |
136023e0 | 323 | $(impl $($pinned_drop:tt)*)? |
5869c6ff | 324 | ) => { |
923072b8 | 325 | $crate::__pin_project_reconstruct! { |
5099ac24 FG |
326 | [$(#[$attrs])* $vis $struct_ty_ident $ident] |
327 | [$($def_generics)*] [$($impl_generics)*] | |
328 | [$($ty_generics)*] [$(where $($where_clause)*)?] | |
329 | { | |
330 | $($body_data)* | |
331 | } | |
5869c6ff XL |
332 | } |
333 | ||
923072b8 | 334 | $crate::__pin_project_make_proj_ty! { |
5869c6ff | 335 | [$($proj_mut_ident)?] |
5099ac24 | 336 | [$proj_vis $struct_ty_ident $ident] |
923072b8 | 337 | [__pin_project_make_proj_field_mut] |
5869c6ff XL |
338 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
339 | { | |
5099ac24 | 340 | $($body_data)* |
5869c6ff XL |
341 | } |
342 | } | |
923072b8 | 343 | $crate::__pin_project_make_proj_ty! { |
5869c6ff | 344 | [$($proj_ref_ident)?] |
5099ac24 | 345 | [$proj_vis $struct_ty_ident $ident] |
923072b8 | 346 | [__pin_project_make_proj_field_ref] |
5869c6ff XL |
347 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
348 | { | |
5099ac24 | 349 | $($body_data)* |
5869c6ff XL |
350 | } |
351 | } | |
923072b8 | 352 | $crate::__pin_project_make_proj_replace_ty! { |
5869c6ff | 353 | [$($proj_replace_ident)?] |
5099ac24 | 354 | [$proj_vis $struct_ty_ident] |
923072b8 | 355 | [__pin_project_make_proj_field_replace] |
5869c6ff XL |
356 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
357 | { | |
5099ac24 | 358 | $($body_data)* |
5869c6ff XL |
359 | } |
360 | } | |
361 | ||
923072b8 | 362 | $crate::__pin_project_constant! { |
5099ac24 FG |
363 | [$(#[$attrs])* $vis $struct_ty_ident $ident] |
364 | [$($proj_mut_ident)?] [$($proj_ref_ident)?] [$($proj_replace_ident)?] | |
365 | [$proj_vis] | |
366 | [$($def_generics)*] [$($impl_generics)*] | |
367 | [$($ty_generics)*] [$(where $($where_clause)*)?] | |
368 | { | |
369 | $($body_data)* | |
370 | } | |
371 | $(impl $($pinned_drop)*)? | |
372 | } | |
373 | }; | |
923072b8 FG |
374 | } |
375 | ||
376 | #[doc(hidden)] | |
377 | #[macro_export] | |
378 | macro_rules! __pin_project_constant { | |
379 | ( | |
5099ac24 FG |
380 | [$(#[$attrs:meta])* $vis:vis struct $ident:ident] |
381 | [$($proj_mut_ident:ident)?] [$($proj_ref_ident:ident)?] [$($proj_replace_ident:ident)?] | |
382 | [$proj_vis:vis] | |
383 | [$($def_generics:tt)*] | |
384 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
385 | { | |
386 | $( | |
387 | $(#[$pin:ident])? | |
388 | $field_vis:vis $field:ident: $field_ty:ty | |
389 | ),+ $(,)? | |
390 | } | |
391 | $(impl $($pinned_drop:tt)*)? | |
392 | ) => { | |
5869c6ff XL |
393 | #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993 |
394 | #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 | |
395 | // This lint warns of `clippy::*` generated by external macros. | |
396 | // We allow this lint for compatibility with older compilers. | |
397 | #[allow(clippy::unknown_clippy_lints)] | |
398 | #[allow(clippy::redundant_pub_crate)] // This lint warns `pub(crate)` field in private struct. | |
399 | #[allow(clippy::used_underscore_binding)] | |
400 | const _: () = { | |
923072b8 | 401 | $crate::__pin_project_make_proj_ty! { |
5099ac24 FG |
402 | [$($proj_mut_ident)? Projection] |
403 | [$proj_vis struct $ident] | |
923072b8 | 404 | [__pin_project_make_proj_field_mut] |
5869c6ff XL |
405 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
406 | { | |
407 | $( | |
408 | $(#[$pin])? | |
409 | $field_vis $field: $field_ty | |
410 | ),+ | |
411 | } | |
412 | } | |
923072b8 | 413 | $crate::__pin_project_make_proj_ty! { |
5099ac24 FG |
414 | [$($proj_ref_ident)? ProjectionRef] |
415 | [$proj_vis struct $ident] | |
923072b8 | 416 | [__pin_project_make_proj_field_ref] |
5869c6ff XL |
417 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
418 | { | |
419 | $( | |
420 | $(#[$pin])? | |
421 | $field_vis $field: $field_ty | |
422 | ),+ | |
423 | } | |
424 | } | |
425 | ||
426 | impl <$($impl_generics)*> $ident <$($ty_generics)*> | |
427 | $(where | |
428 | $($where_clause)*)? | |
429 | { | |
923072b8 | 430 | $crate::__pin_project_struct_make_proj_method! { |
5099ac24 | 431 | [$($proj_mut_ident)? Projection] |
5869c6ff | 432 | [$proj_vis] |
5869c6ff XL |
433 | [project get_unchecked_mut mut] |
434 | [$($ty_generics)*] | |
435 | { | |
436 | $( | |
437 | $(#[$pin])? | |
438 | $field_vis $field | |
439 | ),+ | |
440 | } | |
441 | } | |
923072b8 | 442 | $crate::__pin_project_struct_make_proj_method! { |
5099ac24 | 443 | [$($proj_ref_ident)? ProjectionRef] |
5869c6ff | 444 | [$proj_vis] |
5869c6ff XL |
445 | [project_ref get_ref] |
446 | [$($ty_generics)*] | |
447 | { | |
448 | $( | |
449 | $(#[$pin])? | |
450 | $field_vis $field | |
451 | ),+ | |
452 | } | |
453 | } | |
923072b8 | 454 | $crate::__pin_project_struct_make_proj_replace_method! { |
5099ac24 | 455 | [$($proj_replace_ident)?] |
5869c6ff | 456 | [$proj_vis] |
5099ac24 | 457 | [ProjectionReplace] |
5869c6ff XL |
458 | [$($ty_generics)*] |
459 | { | |
460 | $( | |
461 | $(#[$pin])? | |
462 | $field_vis $field | |
463 | ),+ | |
464 | } | |
465 | } | |
466 | } | |
467 | ||
923072b8 | 468 | $crate::__pin_project_make_unpin_impl! { |
5869c6ff XL |
469 | [$vis $ident] |
470 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] | |
471 | $( | |
923072b8 | 472 | $field: $crate::__pin_project_make_unpin_bound!( |
5869c6ff XL |
473 | $(#[$pin])? $field_ty |
474 | ) | |
475 | ),+ | |
476 | } | |
477 | ||
923072b8 | 478 | $crate::__pin_project_make_drop_impl! { |
5869c6ff XL |
479 | [$ident] |
480 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] | |
136023e0 | 481 | $(impl $($pinned_drop)*)? |
5869c6ff XL |
482 | } |
483 | ||
484 | // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct. | |
485 | // | |
6a06907d XL |
486 | // Taking a reference to a packed field is UB, and applying |
487 | // `#[forbid(unaligned_references)]` makes sure that doing this is a hard error. | |
5869c6ff XL |
488 | // |
489 | // If the struct ends up having #[repr(packed)] applied somehow, | |
490 | // this will generate an (unfriendly) error message. Under all reasonable | |
491 | // circumstances, we'll detect the #[repr(packed)] attribute, and generate | |
492 | // a much nicer error above. | |
493 | // | |
494 | // See https://github.com/taiki-e/pin-project/pull/34 for more details. | |
6a06907d XL |
495 | // |
496 | // Note: | |
497 | // - Lint-based tricks aren't perfect, but they're much better than nothing: | |
498 | // https://github.com/taiki-e/pin-project-lite/issues/26 | |
499 | // | |
500 | // - Enable both unaligned_references and safe_packed_borrows lints | |
501 | // because unaligned_references lint does not exist in older compilers: | |
502 | // https://github.com/taiki-e/pin-project-lite/pull/55 | |
503 | // https://github.com/rust-lang/rust/pull/82525 | |
504 | #[forbid(unaligned_references, safe_packed_borrows)] | |
5869c6ff XL |
505 | fn __assert_not_repr_packed <$($impl_generics)*> (this: &$ident <$($ty_generics)*>) |
506 | $(where | |
507 | $($where_clause)*)? | |
508 | { | |
509 | $( | |
510 | let _ = &this.$field; | |
511 | )+ | |
512 | } | |
513 | }; | |
514 | }; | |
923072b8 | 515 | ( |
5869c6ff | 516 | [$(#[$attrs:meta])* $vis:vis enum $ident:ident] |
5099ac24 FG |
517 | [$($proj_mut_ident:ident)?] [$($proj_ref_ident:ident)?] [$($proj_replace_ident:ident)?] |
518 | [$proj_vis:vis] | |
5869c6ff XL |
519 | [$($def_generics:tt)*] |
520 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
521 | { | |
522 | $( | |
523 | $(#[$variant_attrs:meta])* | |
524 | $variant:ident $({ | |
525 | $( | |
526 | $(#[$pin:ident])? | |
527 | $field:ident: $field_ty:ty | |
5099ac24 | 528 | ),+ $(,)? |
5869c6ff | 529 | })? |
5099ac24 | 530 | ),+ $(,)? |
5869c6ff | 531 | } |
136023e0 | 532 | $(impl $($pinned_drop:tt)*)? |
5869c6ff | 533 | ) => { |
5869c6ff XL |
534 | #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 |
535 | // This lint warns of `clippy::*` generated by external macros. | |
536 | // We allow this lint for compatibility with older compilers. | |
537 | #[allow(clippy::unknown_clippy_lints)] | |
538 | #[allow(clippy::used_underscore_binding)] | |
539 | const _: () = { | |
540 | impl <$($impl_generics)*> $ident <$($ty_generics)*> | |
541 | $(where | |
542 | $($where_clause)*)? | |
543 | { | |
923072b8 | 544 | $crate::__pin_project_enum_make_proj_method! { |
5869c6ff | 545 | [$($proj_mut_ident)?] |
5099ac24 | 546 | [$proj_vis] |
5869c6ff XL |
547 | [project get_unchecked_mut mut] |
548 | [$($ty_generics)*] | |
549 | { | |
550 | $( | |
551 | $variant $({ | |
552 | $( | |
553 | $(#[$pin])? | |
554 | $field | |
555 | ),+ | |
556 | })? | |
557 | ),+ | |
558 | } | |
559 | } | |
923072b8 | 560 | $crate::__pin_project_enum_make_proj_method! { |
5869c6ff | 561 | [$($proj_ref_ident)?] |
5099ac24 | 562 | [$proj_vis] |
5869c6ff XL |
563 | [project_ref get_ref] |
564 | [$($ty_generics)*] | |
565 | { | |
566 | $( | |
567 | $variant $({ | |
568 | $( | |
569 | $(#[$pin])? | |
570 | $field | |
571 | ),+ | |
572 | })? | |
573 | ),+ | |
574 | } | |
575 | } | |
923072b8 | 576 | $crate::__pin_project_enum_make_proj_replace_method! { |
5869c6ff | 577 | [$($proj_replace_ident)?] |
5099ac24 | 578 | [$proj_vis] |
5869c6ff XL |
579 | [$($ty_generics)*] |
580 | { | |
581 | $( | |
582 | $variant $({ | |
583 | $( | |
584 | $(#[$pin])? | |
585 | $field | |
586 | ),+ | |
587 | })? | |
588 | ),+ | |
589 | } | |
590 | } | |
591 | } | |
592 | ||
923072b8 | 593 | $crate::__pin_project_make_unpin_impl! { |
5869c6ff XL |
594 | [$vis $ident] |
595 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] | |
596 | $( | |
597 | $variant: ($( | |
598 | $( | |
923072b8 | 599 | $crate::__pin_project_make_unpin_bound!( |
5869c6ff XL |
600 | $(#[$pin])? $field_ty |
601 | ) | |
602 | ),+ | |
603 | )?) | |
604 | ),+ | |
605 | } | |
606 | ||
923072b8 | 607 | $crate::__pin_project_make_drop_impl! { |
5869c6ff XL |
608 | [$ident] |
609 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] | |
136023e0 | 610 | $(impl $($pinned_drop)*)? |
5869c6ff XL |
611 | } |
612 | ||
613 | // We don't need to check for '#[repr(packed)]', | |
614 | // since it does not apply to enums. | |
615 | }; | |
616 | }; | |
923072b8 | 617 | } |
5869c6ff | 618 | |
923072b8 FG |
619 | #[doc(hidden)] |
620 | #[macro_export] | |
621 | macro_rules! __pin_project_reconstruct { | |
622 | ( | |
5099ac24 FG |
623 | [$(#[$attrs:meta])* $vis:vis struct $ident:ident] |
624 | [$($def_generics:tt)*] [$($impl_generics:tt)*] | |
625 | [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
626 | { | |
627 | $( | |
628 | $(#[$pin:ident])? | |
629 | $field_vis:vis $field:ident: $field_ty:ty | |
630 | ),+ $(,)? | |
631 | } | |
5869c6ff | 632 | ) => { |
5099ac24 FG |
633 | $(#[$attrs])* |
634 | $vis struct $ident $($def_generics)* | |
635 | $(where | |
636 | $($where_clause)*)? | |
637 | { | |
638 | $( | |
639 | $field_vis $field: $field_ty | |
640 | ),+ | |
5869c6ff XL |
641 | } |
642 | }; | |
923072b8 | 643 | ( |
5099ac24 FG |
644 | [$(#[$attrs:meta])* $vis:vis enum $ident:ident] |
645 | [$($def_generics:tt)*] [$($impl_generics:tt)*] | |
646 | [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
5869c6ff XL |
647 | { |
648 | $( | |
5099ac24 FG |
649 | $(#[$variant_attrs:meta])* |
650 | $variant:ident $({ | |
651 | $( | |
652 | $(#[$pin:ident])? | |
653 | $field:ident: $field_ty:ty | |
654 | ),+ $(,)? | |
655 | })? | |
656 | ),+ $(,)? | |
657 | } | |
658 | ) => { | |
659 | $(#[$attrs])* | |
660 | $vis enum $ident $($def_generics)* | |
661 | $(where | |
662 | $($where_clause)*)? | |
663 | { | |
664 | $( | |
665 | $(#[$variant_attrs])* | |
666 | $variant $({ | |
667 | $( | |
668 | $field: $field_ty | |
669 | ),+ | |
670 | })? | |
5869c6ff XL |
671 | ),+ |
672 | } | |
5099ac24 | 673 | }; |
923072b8 FG |
674 | } |
675 | ||
676 | #[doc(hidden)] | |
677 | #[macro_export] | |
678 | macro_rules! __pin_project_make_proj_ty { | |
679 | ([] $($field:tt)*) => {}; | |
680 | ( | |
5099ac24 FG |
681 | [$proj_ty_ident:ident $default_ident:ident] |
682 | [$proj_vis:vis struct $ident:ident] | |
683 | $($field:tt)* | |
684 | ) => {}; | |
923072b8 | 685 | ( |
5099ac24 FG |
686 | [$proj_ty_ident:ident] |
687 | [$proj_vis:vis struct $ident:ident] | |
923072b8 FG |
688 | [$__pin_project_make_proj_field:ident] |
689 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
5869c6ff XL |
690 | { |
691 | $( | |
5099ac24 FG |
692 | $(#[$pin:ident])? |
693 | $field_vis:vis $field:ident: $field_ty:ty | |
694 | ),+ $(,)? | |
695 | } | |
696 | ) => { | |
923072b8 | 697 | $crate::__pin_project_make_proj_ty_body! { |
5099ac24 FG |
698 | [$proj_ty_ident] |
699 | [$proj_vis struct $ident] | |
923072b8 | 700 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
5099ac24 FG |
701 | [ |
702 | $( | |
923072b8 | 703 | $field_vis $field: $crate::$__pin_project_make_proj_field!( |
5099ac24 FG |
704 | $(#[$pin])? $field_ty |
705 | ) | |
706 | ),+ | |
707 | ] | |
708 | } | |
709 | }; | |
923072b8 | 710 | ( |
5869c6ff | 711 | [$proj_ty_ident:ident] |
5099ac24 | 712 | [$proj_vis:vis enum $ident:ident] |
923072b8 FG |
713 | [$__pin_project_make_proj_field:ident] |
714 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
5869c6ff XL |
715 | { |
716 | $( | |
5099ac24 | 717 | $(#[$variant_attrs:meta])* |
5869c6ff XL |
718 | $variant:ident $({ |
719 | $( | |
720 | $(#[$pin:ident])? | |
721 | $field:ident: $field_ty:ty | |
5099ac24 | 722 | ),+ $(,)? |
5869c6ff | 723 | })? |
5099ac24 | 724 | ),+ $(,)? |
5869c6ff XL |
725 | } |
726 | ) => { | |
923072b8 | 727 | $crate::__pin_project_make_proj_ty_body! { |
5099ac24 FG |
728 | [$proj_ty_ident] |
729 | [$proj_vis enum $ident] | |
923072b8 | 730 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
5099ac24 FG |
731 | [ |
732 | $( | |
733 | $variant $({ | |
734 | $( | |
923072b8 | 735 | $field: $crate::$__pin_project_make_proj_field!( |
5099ac24 FG |
736 | $(#[$pin])? $field_ty |
737 | ) | |
738 | ),+ | |
739 | })? | |
740 | ),+ | |
741 | ] | |
5869c6ff XL |
742 | } |
743 | }; | |
923072b8 FG |
744 | } |
745 | ||
746 | #[doc(hidden)] | |
747 | #[macro_export] | |
748 | macro_rules! __pin_project_make_proj_ty_body { | |
749 | ( | |
750 | [$proj_ty_ident:ident] | |
751 | [$proj_vis:vis $struct_ty_ident:ident $ident:ident] | |
752 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
753 | [$($body_data:tt)+] | |
754 | ) => { | |
755 | #[allow(dead_code)] // This lint warns unused fields/variants. | |
756 | #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 | |
757 | // This lint warns of `clippy::*` generated by external macros. | |
758 | // We allow this lint for compatibility with older compilers. | |
759 | #[allow(clippy::unknown_clippy_lints)] | |
760 | #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project) | |
761 | #[allow(clippy::redundant_pub_crate)] // This lint warns `pub(crate)` field in private struct. | |
762 | #[allow(clippy::ref_option_ref)] // This lint warns `&Option<&<ty>>`. (only needed for project_ref) | |
763 | #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326 | |
764 | $proj_vis $struct_ty_ident $proj_ty_ident <'__pin, $($impl_generics)*> | |
765 | where | |
766 | $ident <$($ty_generics)*>: '__pin | |
767 | $(, $($where_clause)*)? | |
768 | { | |
769 | $($body_data)+ | |
770 | } | |
771 | }; | |
772 | } | |
773 | ||
774 | #[doc(hidden)] | |
775 | #[macro_export] | |
776 | macro_rules! __pin_project_make_proj_replace_ty { | |
777 | ([] $($field:tt)*) => {}; | |
778 | ( | |
779 | [$proj_ty_ident:ident] | |
780 | [$proj_vis:vis struct] | |
781 | [$__pin_project_make_proj_field:ident] | |
782 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
783 | { | |
784 | $( | |
785 | $(#[$pin:ident])? | |
786 | $field_vis:vis $field:ident: $field_ty:ty | |
787 | ),+ $(,)? | |
788 | } | |
789 | ) => { | |
790 | $crate::__pin_project_make_proj_replace_ty_body! { | |
791 | [$proj_ty_ident] | |
792 | [$proj_vis struct] | |
793 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] | |
794 | [ | |
795 | $( | |
796 | $field_vis $field: $crate::$__pin_project_make_proj_field!( | |
797 | $(#[$pin])? $field_ty | |
798 | ) | |
799 | ),+ | |
800 | ] | |
801 | } | |
802 | }; | |
803 | ( | |
5869c6ff | 804 | [$proj_ty_ident:ident] |
5099ac24 | 805 | [$proj_vis:vis enum] |
923072b8 FG |
806 | [$__pin_project_make_proj_field:ident] |
807 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
5869c6ff XL |
808 | { |
809 | $( | |
5099ac24 | 810 | $(#[$variant_attrs:meta])* |
5869c6ff XL |
811 | $variant:ident $({ |
812 | $( | |
813 | $(#[$pin:ident])? | |
814 | $field:ident: $field_ty:ty | |
5099ac24 | 815 | ),+ $(,)? |
5869c6ff | 816 | })? |
5099ac24 | 817 | ),+ $(,)? |
5869c6ff XL |
818 | } |
819 | ) => { | |
923072b8 | 820 | $crate::__pin_project_make_proj_replace_ty_body! { |
5099ac24 FG |
821 | [$proj_ty_ident] |
822 | [$proj_vis enum] | |
923072b8 | 823 | [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] |
5099ac24 FG |
824 | [ |
825 | $( | |
826 | $variant $({ | |
827 | $( | |
923072b8 | 828 | $field: $crate::$__pin_project_make_proj_field!( |
5099ac24 FG |
829 | $(#[$pin])? $field_ty |
830 | ) | |
831 | ),+ | |
832 | })? | |
833 | ),+ | |
834 | ] | |
5869c6ff XL |
835 | } |
836 | }; | |
923072b8 FG |
837 | } |
838 | ||
839 | #[doc(hidden)] | |
840 | #[macro_export] | |
841 | macro_rules! __pin_project_make_proj_replace_ty_body { | |
842 | ( | |
843 | [$proj_ty_ident:ident] | |
844 | [$proj_vis:vis $struct_ty_ident:ident] | |
845 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] | |
846 | [$($body_data:tt)+] | |
847 | ) => { | |
848 | #[allow(dead_code)] // This lint warns unused fields/variants. | |
849 | #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 | |
850 | #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project) | |
851 | #[allow(clippy::redundant_pub_crate)] // This lint warns `pub(crate)` field in private struct. | |
852 | #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326 | |
853 | $proj_vis $struct_ty_ident $proj_ty_ident <$($impl_generics)*> | |
854 | where | |
855 | $($($where_clause)*)? | |
856 | { | |
857 | $($body_data)+ | |
858 | } | |
859 | }; | |
860 | } | |
861 | ||
862 | #[doc(hidden)] | |
863 | #[macro_export] | |
864 | macro_rules! __pin_project_make_proj_replace_block { | |
865 | ( | |
866 | [$($proj_path:tt)+] | |
5869c6ff XL |
867 | { |
868 | $( | |
869 | $(#[$pin:ident])? | |
870 | $field_vis:vis $field:ident | |
871 | ),+ | |
872 | } | |
873 | ) => { | |
874 | let result = $($proj_path)* { | |
875 | $( | |
923072b8 | 876 | $field: $crate::__pin_project_make_replace_field_proj!( |
5869c6ff XL |
877 | $(#[$pin])? $field |
878 | ) | |
879 | ),+ | |
880 | }; | |
881 | ||
882 | { | |
883 | ( $( | |
923072b8 | 884 | $crate::__pin_project_make_unsafe_drop_in_place_guard!( |
5869c6ff XL |
885 | $(#[$pin])? $field |
886 | ), | |
887 | )* ); | |
888 | } | |
889 | ||
890 | result | |
891 | }; | |
923072b8 FG |
892 | ([$($proj_path:tt)+]) => { $($proj_path)* }; |
893 | } | |
5869c6ff | 894 | |
923072b8 FG |
895 | #[doc(hidden)] |
896 | #[macro_export] | |
897 | macro_rules! __pin_project_struct_make_proj_method { | |
898 | ([] $($variant:tt)*) => {}; | |
899 | ( | |
5099ac24 FG |
900 | [$proj_ty_ident:ident $_ignored_default_arg:ident] |
901 | [$proj_vis:vis] | |
902 | [$method_ident:ident $get_method:ident $($mut:ident)?] | |
903 | [$($ty_generics:tt)*] | |
904 | $($variant:tt)* | |
905 | ) => { | |
923072b8 | 906 | $crate::__pin_project_struct_make_proj_method! { |
5099ac24 FG |
907 | [$proj_ty_ident] |
908 | [$proj_vis] | |
909 | [$method_ident $get_method $($mut)?] | |
910 | [$($ty_generics)*] | |
911 | $($variant)* | |
912 | } | |
913 | }; | |
923072b8 | 914 | ( |
5099ac24 | 915 | [$proj_ty_ident:ident] |
5869c6ff | 916 | [$proj_vis:vis] |
5869c6ff XL |
917 | [$method_ident:ident $get_method:ident $($mut:ident)?] |
918 | [$($ty_generics:tt)*] | |
919 | { | |
920 | $( | |
921 | $(#[$pin:ident])? | |
922 | $field_vis:vis $field:ident | |
923 | ),+ | |
924 | } | |
925 | ) => { | |
926 | $proj_vis fn $method_ident<'__pin>( | |
927 | self: $crate::__private::Pin<&'__pin $($mut)? Self>, | |
928 | ) -> $proj_ty_ident <'__pin, $($ty_generics)*> { | |
929 | unsafe { | |
930 | let Self { $($field),* } = self.$get_method(); | |
931 | $proj_ty_ident { | |
932 | $( | |
923072b8 | 933 | $field: $crate::__pin_project_make_unsafe_field_proj!( |
5869c6ff XL |
934 | $(#[$pin])? $field |
935 | ) | |
936 | ),+ | |
937 | } | |
938 | } | |
939 | } | |
940 | }; | |
923072b8 | 941 | } |
5869c6ff | 942 | |
923072b8 FG |
943 | #[doc(hidden)] |
944 | #[macro_export] | |
945 | macro_rules! __pin_project_struct_make_proj_replace_method { | |
946 | ([] $($field:tt)*) => {}; | |
947 | ( | |
5099ac24 | 948 | [$proj_ty_ident:ident] |
5869c6ff | 949 | [$proj_vis:vis] |
5099ac24 | 950 | [$_proj_ty_ident:ident] |
5869c6ff XL |
951 | [$($ty_generics:tt)*] |
952 | { | |
953 | $( | |
954 | $(#[$pin:ident])? | |
955 | $field_vis:vis $field:ident | |
956 | ),+ | |
957 | } | |
958 | ) => { | |
959 | $proj_vis fn project_replace( | |
960 | self: $crate::__private::Pin<&mut Self>, | |
961 | replacement: Self, | |
962 | ) -> $proj_ty_ident <$($ty_generics)*> { | |
963 | unsafe { | |
964 | let __self_ptr: *mut Self = self.get_unchecked_mut(); | |
965 | ||
966 | // Destructors will run in reverse order, so next create a guard to overwrite | |
967 | // `self` with the replacement value without calling destructors. | |
5099ac24 | 968 | let __guard = $crate::__private::UnsafeOverwriteGuard::new(__self_ptr, replacement); |
5869c6ff XL |
969 | |
970 | let Self { $($field),* } = &mut *__self_ptr; | |
971 | ||
923072b8 | 972 | $crate::__pin_project_make_proj_replace_block! { |
5869c6ff XL |
973 | [$proj_ty_ident] |
974 | { | |
975 | $( | |
976 | $(#[$pin])? | |
977 | $field | |
978 | ),+ | |
979 | } | |
980 | } | |
981 | } | |
982 | } | |
983 | }; | |
923072b8 FG |
984 | } |
985 | ||
986 | #[doc(hidden)] | |
987 | #[macro_export] | |
988 | macro_rules! __pin_project_enum_make_proj_method { | |
989 | ([] $($variant:tt)*) => {}; | |
990 | ( | |
5869c6ff | 991 | [$proj_ty_ident:ident] |
5099ac24 | 992 | [$proj_vis:vis] |
5869c6ff XL |
993 | [$method_ident:ident $get_method:ident $($mut:ident)?] |
994 | [$($ty_generics:tt)*] | |
995 | { | |
996 | $( | |
997 | $variant:ident $({ | |
998 | $( | |
999 | $(#[$pin:ident])? | |
1000 | $field:ident | |
1001 | ),+ | |
1002 | })? | |
1003 | ),+ | |
1004 | } | |
1005 | ) => { | |
1006 | $proj_vis fn $method_ident<'__pin>( | |
1007 | self: $crate::__private::Pin<&'__pin $($mut)? Self>, | |
1008 | ) -> $proj_ty_ident <'__pin, $($ty_generics)*> { | |
1009 | unsafe { | |
1010 | match self.$get_method() { | |
1011 | $( | |
1012 | Self::$variant $({ | |
1013 | $($field),+ | |
1014 | })? => { | |
1015 | $proj_ty_ident::$variant $({ | |
1016 | $( | |
923072b8 | 1017 | $field: $crate::__pin_project_make_unsafe_field_proj!( |
5869c6ff XL |
1018 | $(#[$pin])? $field |
1019 | ) | |
1020 | ),+ | |
1021 | })? | |
1022 | } | |
1023 | ),+ | |
1024 | } | |
1025 | } | |
1026 | } | |
1027 | }; | |
923072b8 FG |
1028 | } |
1029 | ||
1030 | #[doc(hidden)] | |
1031 | #[macro_export] | |
1032 | macro_rules! __pin_project_enum_make_proj_replace_method { | |
1033 | ([] $($field:tt)*) => {}; | |
1034 | ( | |
5869c6ff | 1035 | [$proj_ty_ident:ident] |
5099ac24 | 1036 | [$proj_vis:vis] |
5869c6ff XL |
1037 | [$($ty_generics:tt)*] |
1038 | { | |
1039 | $( | |
1040 | $variant:ident $({ | |
1041 | $( | |
1042 | $(#[$pin:ident])? | |
1043 | $field:ident | |
1044 | ),+ | |
1045 | })? | |
1046 | ),+ | |
1047 | } | |
1048 | ) => { | |
1049 | $proj_vis fn project_replace( | |
1050 | self: $crate::__private::Pin<&mut Self>, | |
1051 | replacement: Self, | |
1052 | ) -> $proj_ty_ident <$($ty_generics)*> { | |
1053 | unsafe { | |
1054 | let __self_ptr: *mut Self = self.get_unchecked_mut(); | |
1055 | ||
1056 | // Destructors will run in reverse order, so next create a guard to overwrite | |
1057 | // `self` with the replacement value without calling destructors. | |
5099ac24 | 1058 | let __guard = $crate::__private::UnsafeOverwriteGuard::new(__self_ptr, replacement); |
5869c6ff XL |
1059 | |
1060 | match &mut *__self_ptr { | |
1061 | $( | |
1062 | Self::$variant $({ | |
1063 | $($field),+ | |
1064 | })? => { | |
923072b8 | 1065 | $crate::__pin_project_make_proj_replace_block! { |
5869c6ff XL |
1066 | [$proj_ty_ident :: $variant] |
1067 | $({ | |
1068 | $( | |
1069 | $(#[$pin])? | |
1070 | $field | |
1071 | ),+ | |
1072 | })? | |
1073 | } | |
1074 | } | |
1075 | ),+ | |
1076 | } | |
1077 | } | |
1078 | } | |
1079 | }; | |
923072b8 FG |
1080 | } |
1081 | ||
1082 | #[doc(hidden)] | |
1083 | #[macro_export] | |
1084 | macro_rules! __pin_project_make_unpin_impl { | |
1085 | ( | |
5869c6ff | 1086 | [$vis:vis $ident:ident] |
923072b8 | 1087 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] |
5869c6ff XL |
1088 | $($field:tt)* |
1089 | ) => { | |
1090 | // Automatically create the appropriate conditional `Unpin` implementation. | |
1091 | // | |
1092 | // Basically this is equivalent to the following code: | |
1093 | // ```rust | |
1094 | // impl<T, U> Unpin for Struct<T, U> where T: Unpin {} | |
1095 | // ``` | |
1096 | // | |
1097 | // However, if struct is public and there is a private type field, | |
1098 | // this would cause an E0446 (private type in public interface). | |
1099 | // | |
1100 | // When RFC 2145 is implemented (rust-lang/rust#48054), | |
1101 | // this will become a lint, rather then a hard error. | |
1102 | // | |
1103 | // As a workaround for this, we generate a new struct, containing all of the pinned | |
136023e0 | 1104 | // fields from our #[pin_project] type. This struct is declared within |
5869c6ff | 1105 | // a function, which makes it impossible to be named by user code. |
136023e0 | 1106 | // This guarantees that it will use the default auto-trait impl for Unpin - |
5869c6ff | 1107 | // that is, it will implement Unpin iff all of its fields implement Unpin. |
136023e0 | 1108 | // This type can be safely declared as 'public', satisfying the privacy |
5869c6ff XL |
1109 | // checker without actually allowing user code to access it. |
1110 | // | |
1111 | // This allows users to apply the #[pin_project] attribute to types | |
1112 | // regardless of the privacy of the types of their fields. | |
1113 | // | |
1114 | // See also https://github.com/taiki-e/pin-project/pull/53. | |
1115 | #[allow(non_snake_case)] | |
1116 | $vis struct __Origin <'__pin, $($impl_generics)*> | |
1117 | $(where | |
1118 | $($where_clause)*)? | |
1119 | { | |
1120 | __dummy_lifetime: $crate::__private::PhantomData<&'__pin ()>, | |
1121 | $($field)* | |
1122 | } | |
1123 | impl <'__pin, $($impl_generics)*> $crate::__private::Unpin for $ident <$($ty_generics)*> | |
1124 | where | |
1125 | __Origin <'__pin, $($ty_generics)*>: $crate::__private::Unpin | |
1126 | $(, $($where_clause)*)? | |
1127 | { | |
1128 | } | |
1129 | }; | |
923072b8 | 1130 | } |
5869c6ff | 1131 | |
923072b8 FG |
1132 | #[doc(hidden)] |
1133 | #[macro_export] | |
1134 | macro_rules! __pin_project_make_drop_impl { | |
1135 | ( | |
136023e0 | 1136 | [$_ident:ident] |
923072b8 | 1137 | [$($_impl_generics:tt)*] [$($_ty_generics:tt)*] [$(where $($_where_clause:tt)*)?] |
136023e0 XL |
1138 | impl $(< |
1139 | $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)? | |
1140 | $( $generics:ident | |
1141 | $(: $generics_bound:path)? | |
1142 | $(: ?$generics_unsized_bound:path)? | |
1143 | $(: $generics_lifetime_bound:lifetime)? | |
1144 | ),* | |
1145 | >)? PinnedDrop for $self_ty:ty | |
1146 | $(where | |
1147 | $( $where_clause_ty:ty | |
1148 | $(: $where_clause_bound:path)? | |
1149 | $(: ?$where_clause_unsized_bound:path)? | |
1150 | $(: $where_clause_lifetime_bound:lifetime)? | |
5099ac24 | 1151 | ),* $(,)? |
136023e0 XL |
1152 | )? |
1153 | { | |
1154 | fn drop($($arg:ident)+: Pin<&mut Self>) { | |
1155 | $($tt:tt)* | |
1156 | } | |
1157 | } | |
1158 | ) => { | |
1159 | impl $(< | |
1160 | $( $lifetime $(: $lifetime_bound)? ,)* | |
1161 | $( $generics | |
1162 | $(: $generics_bound)? | |
1163 | $(: ?$generics_unsized_bound)? | |
1164 | $(: $generics_lifetime_bound)? | |
1165 | ),* | |
1166 | >)? $crate::__private::Drop for $self_ty | |
1167 | $(where | |
1168 | $( $where_clause_ty | |
1169 | $(: $where_clause_bound)? | |
1170 | $(: ?$where_clause_unsized_bound)? | |
1171 | $(: $where_clause_lifetime_bound)? | |
1172 | ),* | |
1173 | )? | |
1174 | { | |
1175 | fn drop(&mut self) { | |
1176 | // Implementing `__DropInner::__drop_inner` is safe, but calling it is not safe. | |
1177 | // This is because destructors can be called multiple times in safe code and | |
1178 | // [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360). | |
1179 | // | |
1180 | // `__drop_inner` is defined as a safe method, but this is fine since | |
1181 | // `__drop_inner` is not accessible by the users and we call `__drop_inner` only | |
1182 | // once. | |
1183 | // | |
1184 | // Users can implement [`Drop`] safely using `pin_project!` and can drop a | |
1185 | // type that implements `PinnedDrop` using the [`drop`] function safely. | |
1186 | fn __drop_inner $(< | |
1187 | $( $lifetime $(: $lifetime_bound)? ,)* | |
1188 | $( $generics | |
1189 | $(: $generics_bound)? | |
1190 | $(: ?$generics_unsized_bound)? | |
1191 | $(: $generics_lifetime_bound)? | |
1192 | ),* | |
1193 | >)? ( | |
1194 | $($arg)+: $crate::__private::Pin<&mut $self_ty>, | |
1195 | ) | |
1196 | $(where | |
1197 | $( $where_clause_ty | |
1198 | $(: $where_clause_bound)? | |
1199 | $(: ?$where_clause_unsized_bound)? | |
1200 | $(: $where_clause_lifetime_bound)? | |
1201 | ),* | |
1202 | )? | |
1203 | { | |
1204 | // A dummy `__drop_inner` function to prevent users call outer `__drop_inner`. | |
1205 | fn __drop_inner() {} | |
1206 | $($tt)* | |
1207 | } | |
1208 | ||
1209 | // Safety - we're in 'drop', so we know that 'self' will | |
1210 | // never move again. | |
1211 | let pinned_self: $crate::__private::Pin<&mut Self> | |
1212 | = unsafe { $crate::__private::Pin::new_unchecked(self) }; | |
1213 | // We call `__drop_inner` only once. Since `__DropInner::__drop_inner` | |
1214 | // is not accessible by the users, it is never called again. | |
1215 | __drop_inner(pinned_self); | |
1216 | } | |
1217 | } | |
1218 | }; | |
923072b8 | 1219 | ( |
5869c6ff | 1220 | [$ident:ident] |
923072b8 | 1221 | [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?] |
5869c6ff XL |
1222 | ) => { |
1223 | // Ensure that struct does not implement `Drop`. | |
1224 | // | |
1225 | // There are two possible cases: | |
1226 | // 1. The user type does not implement Drop. In this case, | |
1227 | // the first blanked impl will not apply to it. This code | |
1228 | // will compile, as there is only one impl of MustNotImplDrop for the user type | |
1229 | // 2. The user type does impl Drop. This will make the blanket impl applicable, | |
136023e0 | 1230 | // which will then conflict with the explicit MustNotImplDrop impl below. |
5869c6ff XL |
1231 | // This will result in a compilation error, which is exactly what we want. |
1232 | trait MustNotImplDrop {} | |
1233 | #[allow(clippy::drop_bounds, drop_bounds)] | |
1234 | impl<T: $crate::__private::Drop> MustNotImplDrop for T {} | |
1235 | impl <$($impl_generics)*> MustNotImplDrop for $ident <$($ty_generics)*> | |
1236 | $(where | |
1237 | $($where_clause)*)? | |
1238 | { | |
1239 | } | |
1240 | }; | |
923072b8 | 1241 | } |
5869c6ff | 1242 | |
923072b8 FG |
1243 | #[doc(hidden)] |
1244 | #[macro_export] | |
1245 | macro_rules! __pin_project_make_unpin_bound { | |
1246 | (#[pin] $field_ty:ty) => { | |
5869c6ff XL |
1247 | $field_ty |
1248 | }; | |
923072b8 | 1249 | ($field_ty:ty) => { |
5869c6ff XL |
1250 | $crate::__private::AlwaysUnpin<$field_ty> |
1251 | }; | |
923072b8 | 1252 | } |
5869c6ff | 1253 | |
923072b8 FG |
1254 | #[doc(hidden)] |
1255 | #[macro_export] | |
1256 | macro_rules! __pin_project_make_unsafe_field_proj { | |
1257 | (#[pin] $field:ident) => { | |
5869c6ff XL |
1258 | $crate::__private::Pin::new_unchecked($field) |
1259 | }; | |
923072b8 | 1260 | ($field:ident) => { |
5869c6ff XL |
1261 | $field |
1262 | }; | |
923072b8 | 1263 | } |
5869c6ff | 1264 | |
923072b8 FG |
1265 | #[doc(hidden)] |
1266 | #[macro_export] | |
1267 | macro_rules! __pin_project_make_replace_field_proj { | |
1268 | (#[pin] $field:ident) => { | |
5869c6ff XL |
1269 | $crate::__private::PhantomData |
1270 | }; | |
923072b8 | 1271 | ($field:ident) => { |
5869c6ff XL |
1272 | $crate::__private::ptr::read($field) |
1273 | }; | |
923072b8 | 1274 | } |
5869c6ff | 1275 | |
923072b8 FG |
1276 | #[doc(hidden)] |
1277 | #[macro_export] | |
1278 | macro_rules! __pin_project_make_unsafe_drop_in_place_guard { | |
1279 | (#[pin] $field:ident) => { | |
5099ac24 | 1280 | $crate::__private::UnsafeDropInPlaceGuard::new($field) |
5869c6ff | 1281 | }; |
923072b8 | 1282 | ($field:ident) => { |
5869c6ff XL |
1283 | () |
1284 | }; | |
923072b8 | 1285 | } |
5869c6ff | 1286 | |
923072b8 FG |
1287 | #[doc(hidden)] |
1288 | #[macro_export] | |
1289 | macro_rules! __pin_project_make_proj_field_mut { | |
1290 | (#[pin] $field_ty:ty) => { | |
5869c6ff XL |
1291 | $crate::__private::Pin<&'__pin mut ($field_ty)> |
1292 | }; | |
923072b8 | 1293 | ($field_ty:ty) => { |
5869c6ff XL |
1294 | &'__pin mut ($field_ty) |
1295 | }; | |
923072b8 FG |
1296 | } |
1297 | ||
1298 | #[doc(hidden)] | |
1299 | #[macro_export] | |
1300 | macro_rules! __pin_project_make_proj_field_ref { | |
1301 | (#[pin] $field_ty:ty) => { | |
5869c6ff XL |
1302 | $crate::__private::Pin<&'__pin ($field_ty)> |
1303 | }; | |
923072b8 | 1304 | ($field_ty:ty) => { |
5869c6ff XL |
1305 | &'__pin ($field_ty) |
1306 | }; | |
923072b8 | 1307 | } |
5869c6ff | 1308 | |
923072b8 FG |
1309 | #[doc(hidden)] |
1310 | #[macro_export] | |
1311 | macro_rules! __pin_project_make_proj_field_replace { | |
1312 | (#[pin] $field_ty:ty) => { | |
5869c6ff XL |
1313 | $crate::__private::PhantomData<$field_ty> |
1314 | }; | |
923072b8 | 1315 | ($field_ty:ty) => { |
5869c6ff XL |
1316 | $field_ty |
1317 | }; | |
923072b8 | 1318 | } |
5869c6ff | 1319 | |
923072b8 FG |
1320 | #[doc(hidden)] |
1321 | #[macro_export] | |
1322 | macro_rules! __pin_project_internal { | |
5099ac24 | 1323 | // parsing proj_mut_ident |
6a06907d XL |
1324 | ( |
1325 | [] | |
1326 | [$($proj_ref_ident:ident)?] | |
1327 | [$($proj_replace_ident:ident)?] | |
1328 | [$($attrs:tt)*] | |
1329 | ||
1330 | #[project = $proj_mut_ident:ident] | |
1331 | $($tt:tt)* | |
1332 | ) => { | |
1333 | $crate::__pin_project_internal! { | |
1334 | [$proj_mut_ident] | |
1335 | [$($proj_ref_ident)?] | |
1336 | [$($proj_replace_ident)?] | |
1337 | [$($attrs)*] | |
1338 | $($tt)* | |
1339 | } | |
1340 | }; | |
5099ac24 | 1341 | // parsing proj_ref_ident |
923072b8 | 1342 | ( |
6a06907d XL |
1343 | [$($proj_mut_ident:ident)?] |
1344 | [] | |
1345 | [$($proj_replace_ident:ident)?] | |
1346 | [$($attrs:tt)*] | |
1347 | ||
1348 | #[project_ref = $proj_ref_ident:ident] | |
1349 | $($tt:tt)* | |
923072b8 | 1350 | ) => { |
6a06907d XL |
1351 | $crate::__pin_project_internal! { |
1352 | [$($proj_mut_ident)?] | |
1353 | [$proj_ref_ident] | |
1354 | [$($proj_replace_ident)?] | |
1355 | [$($attrs)*] | |
1356 | $($tt)* | |
1357 | } | |
1358 | }; | |
5099ac24 | 1359 | // parsing proj_replace_ident |
923072b8 | 1360 | ( |
6a06907d XL |
1361 | [$($proj_mut_ident:ident)?] |
1362 | [$($proj_ref_ident:ident)?] | |
1363 | [] | |
1364 | [$($attrs:tt)*] | |
1365 | ||
1366 | #[project_replace = $proj_replace_ident:ident] | |
1367 | $($tt:tt)* | |
923072b8 | 1368 | ) => { |
6a06907d XL |
1369 | $crate::__pin_project_internal! { |
1370 | [$($proj_mut_ident)?] | |
1371 | [$($proj_ref_ident)?] | |
1372 | [$proj_replace_ident] | |
1373 | [$($attrs)*] | |
1374 | $($tt)* | |
1375 | } | |
1376 | }; | |
5099ac24 FG |
1377 | // this is actually part of a recursive step that picks off a single non-`pin_project_lite` attribute |
1378 | // there could be more to parse | |
923072b8 | 1379 | ( |
6a06907d XL |
1380 | [$($proj_mut_ident:ident)?] |
1381 | [$($proj_ref_ident:ident)?] | |
1382 | [$($proj_replace_ident:ident)?] | |
1383 | [$($attrs:tt)*] | |
1384 | ||
1385 | #[$($attr:tt)*] | |
1386 | $($tt:tt)* | |
923072b8 | 1387 | ) => { |
6a06907d XL |
1388 | $crate::__pin_project_internal! { |
1389 | [$($proj_mut_ident)?] | |
1390 | [$($proj_ref_ident)?] | |
1391 | [$($proj_replace_ident)?] | |
1392 | [$($attrs)* #[$($attr)*]] | |
1393 | $($tt)* | |
1394 | } | |
1395 | }; | |
5099ac24 FG |
1396 | // now determine visibility |
1397 | // if public, downgrade | |
923072b8 | 1398 | ( |
5869c6ff XL |
1399 | [$($proj_mut_ident:ident)?] |
1400 | [$($proj_ref_ident:ident)?] | |
1401 | [$($proj_replace_ident:ident)?] | |
6a06907d | 1402 | [$($attrs:tt)*] |
5099ac24 FG |
1403 | pub $struct_ty_ident:ident $ident:ident |
1404 | $($tt:tt)* | |
923072b8 FG |
1405 | ) => { |
1406 | $crate::__pin_project_parse_generics! { | |
5869c6ff XL |
1407 | [$($proj_mut_ident)?] |
1408 | [$($proj_ref_ident)?] | |
1409 | [$($proj_replace_ident)?] | |
5099ac24 FG |
1410 | [$($attrs)*] |
1411 | [pub $struct_ty_ident $ident pub(crate)] | |
1412 | $($tt)* | |
5869c6ff XL |
1413 | } |
1414 | }; | |
923072b8 | 1415 | ( |
5869c6ff XL |
1416 | [$($proj_mut_ident:ident)?] |
1417 | [$($proj_ref_ident:ident)?] | |
1418 | [$($proj_replace_ident:ident)?] | |
6a06907d | 1419 | [$($attrs:tt)*] |
5099ac24 FG |
1420 | $vis:vis $struct_ty_ident:ident $ident:ident |
1421 | $($tt:tt)* | |
923072b8 FG |
1422 | ) => { |
1423 | $crate::__pin_project_parse_generics! { | |
5869c6ff XL |
1424 | [$($proj_mut_ident)?] |
1425 | [$($proj_ref_ident)?] | |
1426 | [$($proj_replace_ident)?] | |
5099ac24 FG |
1427 | [$($attrs)*] |
1428 | [$vis $struct_ty_ident $ident $vis] | |
1429 | $($tt)* | |
5869c6ff XL |
1430 | } |
1431 | }; | |
923072b8 FG |
1432 | } |
1433 | ||
1434 | #[doc(hidden)] | |
1435 | #[macro_export] | |
1436 | macro_rules! __pin_project_parse_generics { | |
5869c6ff XL |
1437 | ( |
1438 | [$($proj_mut_ident:ident)?] | |
1439 | [$($proj_ref_ident:ident)?] | |
1440 | [$($proj_replace_ident:ident)?] | |
6a06907d | 1441 | [$($attrs:tt)*] |
5099ac24 FG |
1442 | [$vis:vis $struct_ty_ident:ident $ident:ident $proj_ty_vis:vis] |
1443 | $(< | |
5869c6ff XL |
1444 | $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)? |
1445 | $( $generics:ident | |
1446 | $(: $generics_bound:path)? | |
1447 | $(: ?$generics_unsized_bound:path)? | |
1448 | $(: $generics_lifetime_bound:lifetime)? | |
1449 | $(= $generics_default:ty)? | |
1450 | ),* $(,)? | |
1451 | >)? | |
1452 | $(where | |
1453 | $( $where_clause_ty:ty | |
1454 | $(: $where_clause_bound:path)? | |
1455 | $(: ?$where_clause_unsized_bound:path)? | |
1456 | $(: $where_clause_lifetime_bound:lifetime)? | |
1457 | ),* $(,)? | |
1458 | )? | |
1459 | { | |
5099ac24 | 1460 | $($body_data:tt)* |
5869c6ff | 1461 | } |
136023e0 | 1462 | $(impl $($pinned_drop:tt)*)? |
5869c6ff | 1463 | ) => { |
923072b8 | 1464 | $crate::__pin_project_expand! { |
5869c6ff XL |
1465 | [$($proj_mut_ident)?] |
1466 | [$($proj_ref_ident)?] | |
1467 | [$($proj_replace_ident)?] | |
5099ac24 FG |
1468 | [$proj_ty_vis] |
1469 | [$($attrs)* $vis $struct_ty_ident $ident] | |
5869c6ff XL |
1470 | [$(< |
1471 | $( $lifetime $(: $lifetime_bound)? ,)* | |
1472 | $( $generics | |
1473 | $(: $generics_bound)? | |
1474 | $(: ?$generics_unsized_bound)? | |
1475 | $(: $generics_lifetime_bound)? | |
1476 | $(= $generics_default)? | |
1477 | ),* | |
1478 | >)?] | |
1479 | [$( | |
1480 | $( $lifetime $(: $lifetime_bound)? ,)* | |
1481 | $( $generics | |
1482 | $(: $generics_bound)? | |
1483 | $(: ?$generics_unsized_bound)? | |
1484 | $(: $generics_lifetime_bound)? | |
1485 | ),* | |
1486 | )?] | |
1487 | [$( $( $lifetime ,)* $( $generics ),* )?] | |
1488 | [$(where $( $where_clause_ty | |
1489 | $(: $where_clause_bound)? | |
1490 | $(: ?$where_clause_unsized_bound)? | |
1491 | $(: $where_clause_lifetime_bound)? | |
1492 | ),* )?] | |
1493 | { | |
5099ac24 | 1494 | $($body_data)* |
5869c6ff | 1495 | } |
136023e0 | 1496 | $(impl $($pinned_drop)*)? |
5869c6ff XL |
1497 | } |
1498 | }; | |
1499 | } | |
1500 | ||
5869c6ff XL |
1501 | #[doc(hidden)] |
1502 | pub mod __private { | |
5099ac24 | 1503 | use core::mem::ManuallyDrop; |
5869c6ff XL |
1504 | #[doc(hidden)] |
1505 | pub use core::{ | |
1506 | marker::{PhantomData, Unpin}, | |
5869c6ff XL |
1507 | ops::Drop, |
1508 | pin::Pin, | |
1509 | ptr, | |
1510 | }; | |
1511 | ||
1512 | // This is an internal helper struct used by `pin_project!`. | |
1513 | #[doc(hidden)] | |
1514 | pub struct AlwaysUnpin<T: ?Sized>(PhantomData<T>); | |
1515 | ||
1516 | impl<T: ?Sized> Unpin for AlwaysUnpin<T> {} | |
1517 | ||
1518 | // This is an internal helper used to ensure a value is dropped. | |
1519 | #[doc(hidden)] | |
5099ac24 FG |
1520 | pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T); |
1521 | ||
1522 | impl<T: ?Sized> UnsafeDropInPlaceGuard<T> { | |
1523 | #[doc(hidden)] | |
1524 | pub unsafe fn new(ptr: *mut T) -> Self { | |
1525 | Self(ptr) | |
1526 | } | |
1527 | } | |
5869c6ff XL |
1528 | |
1529 | impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> { | |
1530 | fn drop(&mut self) { | |
1531 | unsafe { | |
1532 | ptr::drop_in_place(self.0); | |
1533 | } | |
1534 | } | |
1535 | } | |
1536 | ||
1537 | // This is an internal helper used to ensure a value is overwritten without | |
1538 | // its destructor being called. | |
1539 | #[doc(hidden)] | |
1540 | pub struct UnsafeOverwriteGuard<T> { | |
5099ac24 FG |
1541 | target: *mut T, |
1542 | value: ManuallyDrop<T>, | |
1543 | } | |
1544 | ||
1545 | impl<T> UnsafeOverwriteGuard<T> { | |
1546 | #[doc(hidden)] | |
1547 | pub unsafe fn new(target: *mut T, value: T) -> Self { | |
1548 | Self { target, value: ManuallyDrop::new(value) } | |
1549 | } | |
5869c6ff XL |
1550 | } |
1551 | ||
1552 | impl<T> Drop for UnsafeOverwriteGuard<T> { | |
1553 | fn drop(&mut self) { | |
1554 | unsafe { | |
1555 | ptr::write(self.target, ptr::read(&*self.value)); | |
1556 | } | |
1557 | } | |
1558 | } | |
1559 | } |