1 use proc_macro2::{Delimiter, Group, Span, TokenStream};
2 use quote::{format_ident, quote, quote_spanned, ToTokens};
3 use syn::{
4     parse::{Parse, ParseStream},
5     spanned::Spanned,
6     visit_mut::VisitMut,
7     *,
8 };
9 
10 use super::PIN;
11 use crate::utils::{
12     determine_lifetime_name, determine_visibility, insert_lifetime_and_bound, ParseBufferExt,
13     ProjKind, ReplaceReceiver, SliceExt, Variants,
14 };
15 
parse_derive(input: TokenStream) -> Result<TokenStream>16 pub(super) fn parse_derive(input: TokenStream) -> Result<TokenStream> {
17     let mut input: DeriveInput = syn::parse2(input)?;
18 
19     let ident = &input.ident;
20     let ty_generics = input.generics.split_for_impl().1;
21     let self_ty = parse_quote!(#ident #ty_generics);
22     let mut visitor = ReplaceReceiver(&self_ty);
23     visitor.visit_generics_mut(&mut input.generics);
24     visitor.visit_data_mut(&mut input.data);
25 
26     let mut cx = Context::new(&input.attrs, &input.vis, &input.ident, &mut input.generics)?;
27     let packed_check;
28 
29     let (mut items, scoped_items) = match &input.data {
30         Data::Struct(data) => {
31             // Do this first for a better error message.
32             packed_check = Some(cx.ensure_not_packed(&data.fields)?);
33             cx.parse_struct(data)?
34         }
35         Data::Enum(data) => {
36             // We don't need to check for `#[repr(packed)]`,
37             // since it does not apply to enums.
38             packed_check = None;
39             cx.parse_enum(data)?
40         }
41         Data::Union(_) => {
42             return Err(error!(
43                 input,
44                 "#[pin_project] attribute may only be used on structs or enums"
45             ));
46         }
47     };
48 
49     let unpin_impl = cx.make_unpin_impl();
50     let drop_impl = cx.make_drop_impl();
51     let dummy_const = if cfg!(underscore_consts) {
52         format_ident!("_")
53     } else {
54         format_ident!("__SCOPE_{}", ident)
55     };
56     items.extend(quote! {
57         // All items except projected types are generated inside a `const` scope.
58         // This makes it impossible for user code to refer to these types.
59         // However, this prevents Rustdoc from displaying docs for any
60         // of our types. In particular, users cannot see the
61         // automatically generated `Unpin` impl for the '__UnpinStruct' types
62         //
63         // Previously, we provided a flag to correctly document the
64         // automatically generated `Unpin` impl by using def-site hygiene,
65         // but it is now removed.
66         //
67         // Refs:
68         // * https://github.com/rust-lang/rust/issues/63281
69         // * https://github.com/taiki-e/pin-project/pull/53#issuecomment-525906867
70         // * https://github.com/taiki-e/pin-project/pull/70
71         #[doc(hidden)]
72         #[allow(non_upper_case_globals)]
73         #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
74         #[allow(clippy::used_underscore_binding)]
75         const #dummy_const: () = {
76             #scoped_items
77             #unpin_impl
78             #drop_impl
79             #packed_check
80         };
81     });
82     Ok(items)
83 }
84 
validate_struct(ident: &Ident, fields: &Fields) -> Result<()>85 fn validate_struct(ident: &Ident, fields: &Fields) -> Result<()> {
86     if fields.is_empty() {
87         let msg = "#[pin_project] attribute may not be used on structs with zero fields";
88         if let Fields::Unit = fields { Err(error!(ident, msg)) } else { Err(error!(fields, msg)) }
89     } else {
90         Ok(())
91     }
92 }
93 
validate_enum(brace_token: token::Brace, variants: &Variants) -> Result<()>94 fn validate_enum(brace_token: token::Brace, variants: &Variants) -> Result<()> {
95     if variants.is_empty() {
96         return Err(Error::new(
97             brace_token.span,
98             "#[pin_project] attribute may not be used on enums without variants",
99         ));
100     }
101     let has_field = variants.iter().try_fold(false, |has_field, v| {
102         if let Some((_, e)) = &v.discriminant {
103             Err(error!(e, "#[pin_project] attribute may not be used on enums with discriminants"))
104         } else if let Some(attr) = v.attrs.find(PIN) {
105             Err(error!(attr, "#[pin] attribute may only be used on fields of structs or variants"))
106         } else if v.fields.is_empty() {
107             Ok(has_field)
108         } else {
109             Ok(true)
110         }
111     })?;
112     if has_field {
113         Ok(())
114     } else {
115         Err(error!(variants, "#[pin_project] attribute may not be used on enums with zero fields"))
116     }
117 }
118 
119 struct Args {
120     /// `PinnedDrop` argument.
121     pinned_drop: Option<Span>,
122     /// `UnsafeUnpin` or `!Unpin` argument.
123     unpin_impl: UnpinImpl,
124     /// `project = <ident>` argument.
125     project: Option<Ident>,
126     /// `project_ref = <ident>` argument.
127     project_ref: Option<Ident>,
128     /// `project_replace [= <ident>]` or `Replace` argument.
129     project_replace: ProjReplace,
130 }
131 
132 enum ProjReplace {
133     None,
134     /// `project_replace` or `Replace`.
135     Unnamed {
136         span: Span,
137     },
138     /// `project_replace = <ident>`.
139     Named {
140         span: Span,
141         ident: Ident,
142     },
143 }
144 
145 impl ProjReplace {
span(&self) -> Option<Span>146     fn span(&self) -> Option<Span> {
147         match self {
148             ProjReplace::None => None,
149             ProjReplace::Named { span, .. } | ProjReplace::Unnamed { span, .. } => Some(*span),
150         }
151     }
152 
ident(&self) -> Option<&Ident>153     fn ident(&self) -> Option<&Ident> {
154         if let ProjReplace::Named { ident, .. } = self { Some(ident) } else { None }
155     }
156 }
157 
158 const DUPLICATE_PIN: &str = "duplicate #[pin] attribute";
159 
160 impl Args {
get(attrs: &[Attribute]) -> Result<Self>161     fn get(attrs: &[Attribute]) -> Result<Self> {
162         // `(__private(<args>))` -> `<args>`
163         struct Input(Option<TokenStream>);
164 
165         impl Parse for Input {
166             fn parse(input: ParseStream<'_>) -> Result<Self> {
167                 Ok(Self((|| {
168                     let content = input.parenthesized().ok()?;
169                     let private = content.parse::<Ident>().ok()?;
170                     if private == "__private" {
171                         content.parenthesized().ok()?.parse::<TokenStream>().ok()
172                     } else {
173                         None
174                     }
175                 })()))
176             }
177         }
178 
179         if let Some(attr) = attrs.find("pin_project") {
180             return Err(error!(attr, "duplicate #[pin_project] attribute"));
181         }
182 
183         let mut attrs = attrs.iter().filter(|attr| attr.path.is_ident(PIN));
184 
185         let prev = if let Some(attr) = attrs.next() {
186             (attr, syn::parse2::<Input>(attr.tokens.clone()).unwrap().0)
187         } else {
188             // This only fails if another macro removes `#[pin]`.
189             return Err(error!(TokenStream::new(), "#[pin_project] attribute has been removed"));
190         };
191 
192         if let Some(attr) = attrs.next() {
193             let (prev_attr, prev_res) = &prev;
194             // As the `#[pin]` attribute generated by `#[pin_project]`
195             // has the same span as `#[pin_project]`, it is possible
196             // that a useless error message will be generated.
197             let res = syn::parse2::<Input>(attr.tokens.clone()).unwrap().0;
198             let span = match (&prev_res, res) {
199                 (Some(_), _) => attr,
200                 (_, Some(_)) => prev_attr,
201                 (None, None) => prev_attr,
202             };
203             Err(error!(span, DUPLICATE_PIN))
204         } else {
205             // This `unwrap` only fails if another macro removes `#[pin]` and inserts own `#[pin]`.
206             syn::parse2(prev.1.unwrap())
207         }
208     }
209 }
210 
211 impl Parse for Args {
parse(input: ParseStream<'_>) -> Result<Self>212     fn parse(input: ParseStream<'_>) -> Result<Self> {
213         mod kw {
214             syn::custom_keyword!(Unpin);
215         }
216 
217         // Parses `= <value>` in `<name> = <value>` and returns value and span of name-value pair.
218         fn parse_value(
219             input: ParseStream<'_>,
220             name: &Ident,
221             has_prev: bool,
222         ) -> Result<(Ident, TokenStream)> {
223             if input.is_empty() {
224                 return Err(error!(name, "expected `{0} = <identifier>`, found `{0}`", name));
225             }
226             let eq_token: Token![=] = input.parse()?;
227             if input.is_empty() {
228                 let span = quote!(#name #eq_token);
229                 return Err(error!(span, "expected `{0} = <identifier>`, found `{0} =`", name));
230             }
231             let value: Ident = input.parse()?;
232             let span = quote!(#name #value);
233             if has_prev {
234                 Err(error!(span, "duplicate `{}` argument", name))
235             } else {
236                 Ok((value, span))
237             }
238         }
239 
240         let mut pinned_drop = None;
241         let mut unsafe_unpin = None;
242         let mut not_unpin = None;
243         let mut project = None;
244         let mut project_ref = None;
245 
246         let mut replace = None;
247         let mut project_replace_value = None;
248         let mut project_replace_span = None;
249 
250         while !input.is_empty() {
251             if input.peek(Token![!]) {
252                 let bang: Token![!] = input.parse()?;
253                 if input.is_empty() {
254                     return Err(error!(bang, "expected `!Unpin`, found `!`"));
255                 }
256                 let unpin: kw::Unpin = input.parse()?;
257                 let span = quote!(#bang #unpin);
258                 if not_unpin.replace(span.span()).is_some() {
259                     return Err(error!(span, "duplicate `!Unpin` argument"));
260                 }
261             } else {
262                 let token = input.parse::<Ident>()?;
263                 match &*token.to_string() {
264                     "PinnedDrop" => {
265                         if pinned_drop.replace(token.span()).is_some() {
266                             return Err(error!(token, "duplicate `PinnedDrop` argument"));
267                         }
268                     }
269                     "UnsafeUnpin" => {
270                         if unsafe_unpin.replace(token.span()).is_some() {
271                             return Err(error!(token, "duplicate `UnsafeUnpin` argument"));
272                         }
273                     }
274                     "project" => {
275                         project = Some(parse_value(input, &token, project.is_some())?.0);
276                     }
277                     "project_ref" => {
278                         project_ref = Some(parse_value(input, &token, project_ref.is_some())?.0);
279                     }
280                     "project_replace" => {
281                         if input.peek(Token![=]) {
282                             let (value, span) =
283                                 parse_value(input, &token, project_replace_span.is_some())?;
284                             project_replace_value = Some(value);
285                             project_replace_span = Some(span.span());
286                         } else if project_replace_span.is_some() {
287                             return Err(error!(token, "duplicate `project_replace` argument"));
288                         } else {
289                             project_replace_span = Some(token.span());
290                         }
291                     }
292                     "Replace" => {
293                         if replace.replace(token.span()).is_some() {
294                             return Err(error!(token, "duplicate `Replace` argument"));
295                         }
296                     }
297                     _ => return Err(error!(token, "unexpected argument: {}", token)),
298                 }
299             }
300 
301             if input.is_empty() {
302                 break;
303             }
304             let _: Token![,] = input.parse()?;
305         }
306 
307         if project.is_some() || project_ref.is_some() {
308             if project == project_ref {
309                 return Err(error!(
310                     project_ref,
311                     "name `{}` is already specified by `project` argument",
312                     project_ref.as_ref().unwrap()
313                 ));
314             }
315             if let Some(ident) = &project_replace_value {
316                 if project == project_replace_value {
317                     return Err(error!(
318                         ident,
319                         "name `{}` is already specified by `project` argument", ident
320                     ));
321                 } else if project_ref == project_replace_value {
322                     return Err(error!(
323                         ident,
324                         "name `{}` is already specified by `project_ref` argument", ident
325                     ));
326                 }
327             }
328         }
329 
330         if let Some(span) = pinned_drop {
331             if project_replace_span.is_some() {
332                 return Err(Error::new(
333                     span,
334                     "arguments `PinnedDrop` and `project_replace` are mutually exclusive",
335                 ));
336             } else if replace.is_some() {
337                 return Err(Error::new(
338                     span,
339                     "arguments `PinnedDrop` and `Replace` are mutually exclusive",
340                 ));
341             }
342         }
343         let project_replace = match (project_replace_span, project_replace_value, replace) {
344             (None, _, None) => ProjReplace::None,
345             // If both `project_replace` and `Replace` are specified,
346             // We always prefer `project_replace`'s span,
347             (Some(span), Some(ident), _) => ProjReplace::Named { ident, span },
348             (Some(span), ..) | (None, _, Some(span)) => ProjReplace::Unnamed { span },
349         };
350         let unpin_impl = match (unsafe_unpin, not_unpin) {
351             (None, None) => UnpinImpl::Default,
352             (Some(span), None) => UnpinImpl::Unsafe(span),
353             (None, Some(span)) => UnpinImpl::Negative(span),
354             (Some(span), Some(_)) => {
355                 return Err(Error::new(
356                     span,
357                     "arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive",
358                 ));
359             }
360         };
361 
362         Ok(Self { pinned_drop, unpin_impl, project, project_ref, project_replace })
363     }
364 }
365 
366 struct OriginalType<'a> {
367     /// Attributes of the original type.
368     attrs: &'a [Attribute],
369     /// Visibility of the original type.
370     vis: &'a Visibility,
371     /// Name of the original type.
372     ident: &'a Ident,
373     /// Generics of the original type.
374     generics: &'a Generics,
375 }
376 
377 struct ProjectedType {
378     /// Visibility of the projected types.
379     vis: Visibility,
380     /// Name of the projected type returned by `project` method.
381     mut_ident: Ident,
382     /// Name of the projected type returned by `project_ref` method.
383     ref_ident: Ident,
384     /// Name of the projected type returned by `project_replace` method.
385     own_ident: Ident,
386     /// Lifetime on the generated projected types.
387     lifetime: Lifetime,
388     /// Generics of the projected types.
389     generics: Generics,
390     /// `where` clause of the projected types. This has an additional
391     /// bound generated by `insert_lifetime_and_bound`
392     where_clause: WhereClause,
393 }
394 
395 struct ProjectedVariants {
396     proj_variants: TokenStream,
397     proj_ref_variants: TokenStream,
398     proj_own_variants: TokenStream,
399     proj_arms: TokenStream,
400     proj_ref_arms: TokenStream,
401     proj_own_arms: TokenStream,
402 }
403 
404 #[derive(Default)]
405 struct ProjectedFields {
406     proj_pat: TokenStream,
407     proj_body: TokenStream,
408     proj_own_body: TokenStream,
409     proj_fields: TokenStream,
410     proj_ref_fields: TokenStream,
411     proj_own_fields: TokenStream,
412 }
413 
414 struct Context<'a> {
415     /// The original type.
416     orig: OriginalType<'a>,
417     /// The projected types.
418     proj: ProjectedType,
419     /// Types of the pinned fields.
420     pinned_fields: Vec<Type>,
421 
422     /// `PinnedDrop` argument.
423     pinned_drop: Option<Span>,
424     /// `UnsafeUnpin` or `!Unpin` argument.
425     unpin_impl: UnpinImpl,
426     /// `project` argument.
427     project: bool,
428     /// `project_ref` argument.
429     project_ref: bool,
430     /// `project_replace [= <ident>]` or `Replace` argument.
431     project_replace: ProjReplace,
432 }
433 
434 #[derive(Clone, Copy)]
435 enum UnpinImpl {
436     Default,
437     /// `UnsafeUnpin`.
438     Unsafe(Span),
439     /// `!Unpin`.
440     Negative(Span),
441 }
442 
443 impl<'a> Context<'a> {
new( attrs: &'a [Attribute], vis: &'a Visibility, ident: &'a Ident, generics: &'a mut Generics, ) -> Result<Self>444     fn new(
445         attrs: &'a [Attribute],
446         vis: &'a Visibility,
447         ident: &'a Ident,
448         generics: &'a mut Generics,
449     ) -> Result<Self> {
450         let Args { pinned_drop, unpin_impl, project, project_ref, project_replace } =
451             Args::get(attrs)?;
452 
453         let mut lifetime_name = String::from("'pin");
454         determine_lifetime_name(&mut lifetime_name, generics);
455         let lifetime = Lifetime::new(&lifetime_name, Span::call_site());
456 
457         let ty_generics = generics.split_for_impl().1;
458         let ty_generics_as_generics = parse_quote!(#ty_generics);
459         let mut proj_generics = generics.clone();
460         let pred = insert_lifetime_and_bound(
461             &mut proj_generics,
462             lifetime.clone(),
463             &ty_generics_as_generics,
464             ident,
465         );
466         let mut where_clause = generics.make_where_clause().clone();
467         where_clause.predicates.push(pred);
468 
469         let own_ident =
470             project_replace.ident().cloned().unwrap_or_else(|| ProjKind::Owned.proj_ident(ident));
471 
472         Ok(Self {
473             pinned_drop,
474             unpin_impl,
475             project: project.is_some(),
476             project_ref: project_ref.is_some(),
477             project_replace,
478             proj: ProjectedType {
479                 vis: determine_visibility(vis),
480                 mut_ident: project.unwrap_or_else(|| ProjKind::Mutable.proj_ident(ident)),
481                 ref_ident: project_ref.unwrap_or_else(|| ProjKind::Immutable.proj_ident(ident)),
482                 own_ident,
483                 lifetime,
484                 generics: proj_generics,
485                 where_clause,
486             },
487             orig: OriginalType { attrs, vis, ident, generics },
488             pinned_fields: Vec::new(),
489         })
490     }
491 
492     /// Returns attributes used on projected types.
proj_attrs(&self) -> (TokenStream, TokenStream, TokenStream)493     fn proj_attrs(&self) -> (TokenStream, TokenStream, TokenStream) {
494         // If the user gave it a name, it should appear in the document.
495         let doc_attr = quote!(#[doc(hidden)]);
496         let doc_proj = if self.project { None } else { Some(&doc_attr) };
497         let doc_proj_ref = if self.project_ref { None } else { Some(&doc_attr) };
498         let doc_proj_own =
499             if self.project_replace.ident().is_some() { None } else { Some(&doc_attr) };
500 
501         let proj_mut = quote! {
502             #doc_proj
503             #[allow(dead_code)] // This lint warns unused fields/variants.
504             #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
505             #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
506             #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326}
507         };
508         let proj_ref = quote! {
509             #doc_proj_ref
510             #[allow(dead_code)] // This lint warns unused fields/variants.
511             #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
512             #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
513         };
514         let proj_own = quote! {
515             #doc_proj_own
516             #[allow(dead_code)] // This lint warns unused fields/variants.
517             #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
518             #[allow(unreachable_pub)] // This lint warns `pub` field in private struct.
519         };
520         (proj_mut, proj_ref, proj_own)
521     }
522 
523     fn parse_struct(
524         &mut self,
525         DataStruct { fields, .. }: &DataStruct,
526     ) -> Result<(TokenStream, TokenStream)> {
527         validate_struct(self.orig.ident, fields)?;
528 
529         let ProjectedFields {
530             proj_pat,
531             proj_body,
532             proj_fields,
533             proj_ref_fields,
534             proj_own_fields,
535             proj_own_body,
536         } = match fields {
537             Fields::Named(_) => self.visit_fields(None, fields, Delimiter::Brace)?,
538             Fields::Unnamed(_) => self.visit_fields(None, fields, Delimiter::Parenthesis)?,
539             Fields::Unit => unreachable!(),
540         };
541 
542         let proj_ident = &self.proj.mut_ident;
543         let proj_ref_ident = &self.proj.ref_ident;
544         let proj_own_ident = &self.proj.own_ident;
545         let vis = &self.proj.vis;
546         let mut orig_generics = self.orig.generics.clone();
547         let orig_where_clause = orig_generics.where_clause.take();
548         let proj_generics = &self.proj.generics;
549         let proj_where_clause = &self.proj.where_clause;
550 
551         // For tuple structs, we need to generate `(T1, T2) where Foo: Bar`
552         // For non-tuple structs, we need to generate `where Foo: Bar { field1: T }`
553         let (where_clause_fields, where_clause_ref_fields, where_clause_own_fields) = match fields {
554             Fields::Named(_) => (
555                 quote!(#proj_where_clause #proj_fields),
556                 quote!(#proj_where_clause #proj_ref_fields),
557                 quote!(#orig_where_clause #proj_own_fields),
558             ),
559             Fields::Unnamed(_) => (
560                 quote!(#proj_fields #proj_where_clause;),
561                 quote!(#proj_ref_fields #proj_where_clause;),
562                 quote!(#proj_own_fields #orig_where_clause;),
563             ),
564             Fields::Unit => unreachable!(),
565         };
566 
567         let (proj_attrs, proj_ref_attrs, proj_own_attrs) = self.proj_attrs();
568         let mut proj_items = quote! {
569             #proj_attrs
570             #vis struct #proj_ident #proj_generics #where_clause_fields
571             #proj_ref_attrs
572             #vis struct #proj_ref_ident #proj_generics #where_clause_ref_fields
573         };
574         if self.project_replace.span().is_some() {
575             proj_items.extend(quote! {
576                 #proj_own_attrs
577                 #vis struct #proj_own_ident #orig_generics #where_clause_own_fields
578             });
579         }
580 
581         let proj_mut_body = quote! {
582             let Self #proj_pat = self.get_unchecked_mut();
583             #proj_ident #proj_body
584         };
585         let proj_ref_body = quote! {
586             let Self #proj_pat = self.get_ref();
587             #proj_ref_ident #proj_body
588         };
589         let proj_own_body = quote! {
590             let __self_ptr: *mut Self = self.get_unchecked_mut();
591             let Self #proj_pat = &mut *__self_ptr;
592             #proj_own_body
593         };
594         let proj_impl = self.make_proj_impl(&proj_mut_body, &proj_ref_body, &proj_own_body);
595 
596         Ok((proj_items, proj_impl))
597     }
598 
599     fn parse_enum(
600         &mut self,
601         DataEnum { brace_token, variants, .. }: &DataEnum,
602     ) -> Result<(TokenStream, TokenStream)> {
603         validate_enum(*brace_token, variants)?;
604 
605         let ProjectedVariants {
606             proj_variants,
607             proj_ref_variants,
608             proj_own_variants,
609             proj_arms,
610             proj_ref_arms,
611             proj_own_arms,
612         } = self.visit_variants(variants)?;
613 
614         let proj_ident = &self.proj.mut_ident;
615         let proj_ref_ident = &self.proj.ref_ident;
616         let proj_own_ident = &self.proj.own_ident;
617         let vis = &self.proj.vis;
618         let mut orig_generics = self.orig.generics.clone();
619         let orig_where_clause = orig_generics.where_clause.take();
620         let proj_generics = &self.proj.generics;
621         let proj_where_clause = &self.proj.where_clause;
622 
623         let (proj_attrs, proj_ref_attrs, proj_own_attrs) = self.proj_attrs();
624         let mut proj_items = quote! {
625             #proj_attrs
626             #vis enum #proj_ident #proj_generics #proj_where_clause {
627                 #proj_variants
628             }
629             #proj_ref_attrs
630             #vis enum #proj_ref_ident #proj_generics #proj_where_clause {
631                 #proj_ref_variants
632             }
633         };
634         if self.project_replace.span().is_some() {
635             proj_items.extend(quote! {
636                 #proj_own_attrs
637                 #vis enum #proj_own_ident #orig_generics #orig_where_clause {
638                     #proj_own_variants
639                 }
640             });
641         }
642 
643         let proj_mut_body = quote! {
644             match self.get_unchecked_mut() {
645                 #proj_arms
646             }
647         };
648         let proj_ref_body = quote! {
649             match self.get_ref() {
650                 #proj_ref_arms
651             }
652         };
653         let proj_own_body = quote! {
654             let __self_ptr: *mut Self = self.get_unchecked_mut();
655             match &mut *__self_ptr {
656                 #proj_own_arms
657             }
658         };
659         let proj_impl = self.make_proj_impl(&proj_mut_body, &proj_ref_body, &proj_own_body);
660 
661         Ok((proj_items, proj_impl))
662     }
663 
visit_variants(&mut self, variants: &Variants) -> Result<ProjectedVariants>664     fn visit_variants(&mut self, variants: &Variants) -> Result<ProjectedVariants> {
665         let mut proj_variants = TokenStream::new();
666         let mut proj_ref_variants = TokenStream::new();
667         let mut proj_own_variants = TokenStream::new();
668         let mut proj_arms = TokenStream::new();
669         let mut proj_ref_arms = TokenStream::new();
670         let mut proj_own_arms = TokenStream::new();
671 
672         for Variant { ident, fields, .. } in variants {
673             let ProjectedFields {
674                 proj_pat,
675                 proj_body,
676                 proj_fields,
677                 proj_ref_fields,
678                 proj_own_fields,
679                 proj_own_body,
680             } = match fields {
681                 Fields::Named(_) => self.visit_fields(Some(ident), fields, Delimiter::Brace)?,
682                 Fields::Unnamed(_) => {
683                     self.visit_fields(Some(ident), fields, Delimiter::Parenthesis)?
684                 }
685                 Fields::Unit => ProjectedFields {
686                     proj_own_body: self.proj_own_body(Some(ident), None, &[]),
687                     ..ProjectedFields::default()
688                 },
689             };
690 
691             let orig_ident = self.orig.ident;
692             let proj_ident = &self.proj.mut_ident;
693             let proj_ref_ident = &self.proj.ref_ident;
694             proj_variants.extend(quote! {
695                 #ident #proj_fields,
696             });
697             proj_ref_variants.extend(quote! {
698                 #ident #proj_ref_fields,
699             });
700             proj_own_variants.extend(quote! {
701                 #ident #proj_own_fields,
702             });
703             proj_arms.extend(quote! {
704                 #orig_ident::#ident #proj_pat => {
705                     #proj_ident::#ident #proj_body
706                 }
707             });
708             proj_ref_arms.extend(quote! {
709                 #orig_ident::#ident #proj_pat => {
710                     #proj_ref_ident::#ident #proj_body
711                 }
712             });
713             proj_own_arms.extend(quote! {
714                 #orig_ident::#ident #proj_pat => {
715                     #proj_own_body
716                 }
717             });
718         }
719 
720         Ok(ProjectedVariants {
721             proj_variants,
722             proj_ref_variants,
723             proj_own_variants,
724             proj_arms,
725             proj_ref_arms,
726             proj_own_arms,
727         })
728     }
729 
visit_fields( &mut self, variant_ident: Option<&Ident>, fields: &Fields, delim: Delimiter, ) -> Result<ProjectedFields>730     fn visit_fields(
731         &mut self,
732         variant_ident: Option<&Ident>,
733         fields: &Fields,
734         delim: Delimiter,
735     ) -> Result<ProjectedFields> {
736         let mut proj_pat = TokenStream::new();
737         let mut proj_body = TokenStream::new();
738         let mut proj_fields = TokenStream::new();
739         let mut proj_ref_fields = TokenStream::new();
740         let mut proj_own_fields = TokenStream::new();
741         let mut proj_move = TokenStream::new();
742         let mut pinned_bindings = Vec::with_capacity(fields.len());
743 
744         for (i, Field { attrs, vis, ident, colon_token, ty, .. }) in fields.iter().enumerate() {
745             let binding = ident.clone().unwrap_or_else(|| format_ident!("_{}", i));
746             proj_pat.extend(quote!(#binding,));
747             if attrs.position_exact(PIN)?.is_some() {
748                 let lifetime = &self.proj.lifetime;
749                 proj_fields.extend(quote! {
750                     #vis #ident #colon_token ::pin_project::__private::Pin<&#lifetime mut (#ty)>,
751                 });
752                 proj_ref_fields.extend(quote! {
753                     #vis #ident #colon_token ::pin_project::__private::Pin<&#lifetime (#ty)>,
754                 });
755                 proj_own_fields.extend(quote! {
756                     #vis #ident #colon_token ::pin_project::__private::PhantomData<#ty>,
757                 });
758                 proj_body.extend(quote! {
759                     #ident #colon_token ::pin_project::__private::Pin::new_unchecked(#binding),
760                 });
761                 proj_move.extend(quote! {
762                     #ident #colon_token ::pin_project::__private::PhantomData,
763                 });
764 
765                 self.pinned_fields.push(ty.clone());
766                 pinned_bindings.push(binding);
767             } else {
768                 let lifetime = &self.proj.lifetime;
769                 proj_fields.extend(quote! {
770                     #vis #ident #colon_token &#lifetime mut (#ty),
771                 });
772                 proj_ref_fields.extend(quote! {
773                     #vis #ident #colon_token &#lifetime (#ty),
774                 });
775                 proj_own_fields.extend(quote! {
776                     #vis #ident #colon_token #ty,
777                 });
778                 proj_body.extend(quote! {
779                     #binding,
780                 });
781                 proj_move.extend(quote! {
782                     #ident #colon_token ::pin_project::__private::ptr::read(#binding),
783                 });
784             }
785         }
786 
787         fn surround(delim: Delimiter, tokens: TokenStream) -> TokenStream {
788             Group::new(delim, tokens).into_token_stream()
789         }
790 
791         let proj_pat = surround(delim, proj_pat);
792         let proj_body = surround(delim, proj_body);
793         let proj_fields = surround(delim, proj_fields);
794         let proj_ref_fields = surround(delim, proj_ref_fields);
795         let proj_own_fields = surround(delim, proj_own_fields);
796 
797         let proj_move = Group::new(delim, proj_move);
798         let proj_own_body = self.proj_own_body(variant_ident, Some(proj_move), &pinned_bindings);
799 
800         Ok(ProjectedFields {
801             proj_pat,
802             proj_body,
803             proj_own_body,
804             proj_fields,
805             proj_ref_fields,
806             proj_own_fields,
807         })
808     }
809 
810     /// Generates the processing that `project_replace` does for the struct or each variant.
811     ///
812     /// Note: `pinned_fields` must be in declaration order.
proj_own_body( &self, variant_ident: Option<&'a Ident>, proj_move: Option<Group>, pinned_fields: &[Ident], ) -> TokenStream813     fn proj_own_body(
814         &self,
815         variant_ident: Option<&'a Ident>,
816         proj_move: Option<Group>,
817         pinned_fields: &[Ident],
818     ) -> TokenStream {
819         let ident = &self.proj.own_ident;
820         let proj_own = match variant_ident {
821             Some(variant_ident) => quote!(#ident::#variant_ident),
822             None => quote!(#ident),
823         };
824         // The fields of the struct and the active enum variant are dropped
825         // in declaration order.
826         // Refs: https://doc.rust-lang.org/reference/destructors.html
827         let pinned_fields = pinned_fields.iter().rev();
828 
829         quote! {
830             // First, extract all the unpinned fields.
831             let __result = #proj_own #proj_move;
832 
833             // Destructors will run in reverse order, so next create a guard to overwrite
834             // `self` with the replacement value without calling destructors.
835             let __guard = ::pin_project::__private::UnsafeOverwriteGuard {
836                 target: __self_ptr,
837                 value: ::pin_project::__private::ManuallyDrop::new(__replacement),
838             };
839 
840             // Now create guards to drop all the pinned fields.
841             //
842             // Due to a compiler bug (https://github.com/rust-lang/rust/issues/47949)
843             // this must be in its own scope, or else `__result` will not be dropped
844             // if any of the destructors panic.
845             {
846                 #(
847                     let __guard = ::pin_project::__private::UnsafeDropInPlaceGuard(#pinned_fields);
848                 )*
849             }
850 
851             // Finally, return the result.
852             __result
853         }
854     }
855 
856     /// Creates `Unpin` implementation for original type.
make_unpin_impl(&self) -> TokenStream857     fn make_unpin_impl(&self) -> TokenStream {
858         match self.unpin_impl {
859             UnpinImpl::Unsafe(span) => {
860                 let mut proj_generics = self.proj.generics.clone();
861                 let orig_ident = self.orig.ident;
862                 let lifetime = &self.proj.lifetime;
863 
864                 // Make the error message highlight `UnsafeUnpin` argument.
865                 proj_generics.make_where_clause().predicates.push(parse_quote_spanned! { span =>
866                     ::pin_project::__private::Wrapper<#lifetime, Self>: ::pin_project::UnsafeUnpin
867                 });
868 
869                 let (impl_generics, _, where_clause) = proj_generics.split_for_impl();
870                 let ty_generics = self.orig.generics.split_for_impl().1;
871 
872                 quote_spanned! { span =>
873                     impl #impl_generics ::pin_project::__private::Unpin for #orig_ident #ty_generics
874                     #where_clause
875                     {
876                     }
877                 }
878             }
879             UnpinImpl::Negative(span) => {
880                 let mut proj_generics = self.proj.generics.clone();
881                 let orig_ident = self.orig.ident;
882                 let lifetime = &self.proj.lifetime;
883 
884                 proj_generics.make_where_clause().predicates.push(parse_quote! {
885                     ::pin_project::__private::Wrapper<
886                         #lifetime, ::pin_project::__private::PhantomPinned
887                     >: ::pin_project::__private::Unpin
888                 });
889 
890                 let (proj_impl_generics, _, proj_where_clause) = proj_generics.split_for_impl();
891                 let (impl_generics, ty_generics, orig_where_clause) =
892                     self.orig.generics.split_for_impl();
893 
894                 // For interoperability with `forbid(unsafe_code)`, `unsafe` token should be
895                 // call-site span.
896                 let unsafety = <Token![unsafe]>::default();
897                 quote_spanned! { span =>
898                     impl #proj_impl_generics ::pin_project::__private::Unpin
899                         for #orig_ident #ty_generics
900                     #proj_where_clause
901                     {
902                     }
903 
904                     // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
905                     //
906                     // To ensure that users don't accidentally write a non-functional `UnsafeUnpin`
907                     // impls, we emit one ourselves. If the user ends up writing an `UnsafeUnpin`
908                     // impl, they'll get a "conflicting implementations of trait" error when
909                     // coherence checks are run.
910                     #unsafety impl #impl_generics ::pin_project::UnsafeUnpin
911                         for #orig_ident #ty_generics
912                     #orig_where_clause
913                     {
914                     }
915                 }
916             }
917             UnpinImpl::Default => {
918                 let mut full_where_clause = self.orig.generics.where_clause.clone().unwrap();
919 
920                 // Generate a field in our new struct for every
921                 // pinned field in the original type.
922                 let fields = self.pinned_fields.iter().enumerate().map(|(i, ty)| {
923                     let field_ident = format_ident!("__field{}", i);
924                     quote!(#field_ident: #ty)
925                 });
926 
927                 // We could try to determine the subset of type parameters
928                 // and lifetimes that are actually used by the pinned fields
929                 // (as opposed to those only used by unpinned fields).
930                 // However, this would be tricky and error-prone, since
931                 // it's possible for users to create types that would alias
932                 // with generic parameters (e.g. 'struct T').
933                 //
934                 // Instead, we generate a use of every single type parameter
935                 // and lifetime used in the original struct. For type parameters,
936                 // we generate code like this:
937                 //
938                 // ```rust
939                 // struct AlwaysUnpin<T: ?Sized>(PhantomData<T>) {}
940                 // impl<T: ?Sized> Unpin for AlwaysUnpin<T> {}
941                 //
942                 // ...
943                 // _field: AlwaysUnpin<(A, B, C)>
944                 // ```
945                 //
946                 // This ensures that any unused type parameters
947                 // don't end up with `Unpin` bounds.
948                 let lifetime_fields = self.orig.generics.lifetimes().enumerate().map(
949                     |(i, LifetimeDef { lifetime, .. })| {
950                         let field_ident = format_ident!("__lifetime{}", i);
951                         quote!(#field_ident: &#lifetime ())
952                     },
953                 );
954 
955                 let orig_ident = self.orig.ident;
956                 let struct_ident = format_ident!("__{}", orig_ident);
957                 let vis = self.orig.vis;
958                 let lifetime = &self.proj.lifetime;
959                 let type_params = self.orig.generics.type_params().map(|t| &t.ident);
960                 let proj_generics = &self.proj.generics;
961                 let (proj_impl_generics, proj_ty_generics, _) = proj_generics.split_for_impl();
962                 let (impl_generics, ty_generics, where_clause) =
963                     self.orig.generics.split_for_impl();
964 
965                 full_where_clause.predicates.push(parse_quote! {
966                     #struct_ident #proj_ty_generics: ::pin_project::__private::Unpin
967                 });
968 
969                 quote! {
970                     // This needs to have the same visibility as the original type,
971                     // due to the limitations of the 'public in private' error.
972                     //
973                     // Our goal is to implement the public trait `Unpin` for
974                     // a potentially public user type. Because of this, rust
975                     // requires that any types mentioned in the where clause of
976                     // our `Unpin` impl also be public. This means that our generated
977                     // `__UnpinStruct` type must also be public.
978                     // However, we ensure that the user can never actually reference
979                     // this 'public' type by creating this type in the inside of `const`.
980                     #vis struct #struct_ident #proj_generics #where_clause {
981                         __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<
982                             #lifetime, (#(::pin_project::__private::PhantomData<#type_params>),*)
983                         >,
984 
985                         #(#fields,)*
986                         #(#lifetime_fields,)*
987                     }
988 
989                     impl #proj_impl_generics ::pin_project::__private::Unpin
990                         for #orig_ident #ty_generics
991                     #full_where_clause
992                     {
993                     }
994 
995                     // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
996                     //
997                     // To ensure that users don't accidentally write a non-functional `UnsafeUnpin`
998                     // impls, we emit one ourselves. If the user ends up writing an `UnsafeUnpin`
999                     // impl, they'll get a "conflicting implementations of trait" error when
1000                     // coherence checks are run.
1001                     unsafe impl #impl_generics ::pin_project::UnsafeUnpin
1002                         for #orig_ident #ty_generics
1003                     #where_clause
1004                     {
1005                     }
1006                 }
1007             }
1008         }
1009     }
1010 
1011     /// Creates `Drop` implementation for original type.
make_drop_impl(&self) -> TokenStream1012     fn make_drop_impl(&self) -> TokenStream {
1013         let ident = self.orig.ident;
1014         let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
1015 
1016         if let Some(span) = self.pinned_drop {
1017             // For interoperability with `forbid(unsafe_code)`, `unsafe` token should be
1018             // call-site span.
1019             let unsafety = <Token![unsafe]>::default();
1020             quote_spanned! { span =>
1021                 impl #impl_generics ::pin_project::__private::Drop for #ident #ty_generics
1022                 #where_clause
1023                 {
1024                     fn drop(&mut self) {
1025                         // Safety - we're in 'drop', so we know that 'self' will
1026                         // never move again.
1027                         let pinned_self = #unsafety {
1028                             ::pin_project::__private::Pin::new_unchecked(self)
1029                         };
1030                         // We call `pinned_drop` only once. Since `PinnedDrop::drop`
1031                         // is an unsafe method and a private API, it is never called again in safe
1032                         // code *unless the user uses a maliciously crafted macro*.
1033                         #unsafety {
1034                             ::pin_project::__private::PinnedDrop::drop(pinned_self);
1035                         }
1036                     }
1037                 }
1038             }
1039         } else {
1040             // If the user does not provide a `PinnedDrop` impl,
1041             // we need to ensure that they don't provide a `Drop` impl of their
1042             // own.
1043             // Based on https://github.com/upsuper/assert-impl/blob/f503255b292ab0ba8d085b657f4065403cfa46eb/src/lib.rs#L80-L87
1044             //
1045             // We create a new identifier for each struct, so that the traits
1046             // for different types do not conflict with each other.
1047             //
1048             // Another approach would be to provide an empty Drop impl,
1049             // which would conflict with a user-provided Drop impl.
1050             // However, this would trigger the compiler's special handling
1051             // of Drop types (e.g. fields cannot be moved out of a Drop type).
1052             // This approach prevents the creation of needless Drop impls,
1053             // giving users more flexibility.
1054             let trait_ident = format_ident!("{}MustNotImplDrop", ident);
1055 
1056             quote! {
1057                 // There are two possible cases:
1058                 // 1. The user type does not implement Drop. In this case,
1059                 // the first blanked impl will not apply to it. This code
1060                 // will compile, as there is only one impl of MustNotImplDrop for the user type
1061                 // 2. The user type does impl Drop. This will make the blanket impl applicable,
1062                 // which will then conflict with the explicit MustNotImplDrop impl below.
1063                 // This will result in a compilation error, which is exactly what we want.
1064                 trait #trait_ident {}
1065                 #[allow(clippy::drop_bounds, drop_bounds)]
1066                 impl<T: ::pin_project::__private::Drop> #trait_ident for T {}
1067                 impl #impl_generics #trait_ident for #ident #ty_generics #where_clause {}
1068 
1069                 // A dummy impl of `PinnedDrop`, to ensure that the user cannot implement it.
1070                 // Since the user did not pass `PinnedDrop` to `#[pin_project]`, any `PinnedDrop`
1071                 // impl will not actually be called. Unfortunately, we can't detect this situation
1072                 // directly from either the `#[pin_project]` or `#[pinned_drop]` attributes, since
1073                 // we don't know what other attirbutes/impl may exist.
1074                 //
1075                 // To ensure that users don't accidentally write a non-functional `PinnedDrop`
1076                 // impls, we emit one ourselves. If the user ends up writing a `PinnedDrop` impl,
1077                 // they'll get a "conflicting implementations of trait" error when coherence
1078                 // checks are run.
1079                 impl #impl_generics ::pin_project::__private::PinnedDrop for #ident #ty_generics
1080                 #where_clause
1081                 {
1082                     unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
1083                 }
1084             }
1085         }
1086     }
1087 
1088     /// Creates an implementation of the projection method.
make_proj_impl( &self, proj_body: &TokenStream, proj_ref_body: &TokenStream, proj_own_body: &TokenStream, ) -> TokenStream1089     fn make_proj_impl(
1090         &self,
1091         proj_body: &TokenStream,
1092         proj_ref_body: &TokenStream,
1093         proj_own_body: &TokenStream,
1094     ) -> TokenStream {
1095         let vis = &self.proj.vis;
1096         let lifetime = &self.proj.lifetime;
1097         let orig_ident = self.orig.ident;
1098         let proj_ident = &self.proj.mut_ident;
1099         let proj_ref_ident = &self.proj.ref_ident;
1100         let proj_own_ident = &self.proj.own_ident;
1101 
1102         let orig_ty_generics = self.orig.generics.split_for_impl().1;
1103         let proj_ty_generics = self.proj.generics.split_for_impl().1;
1104         let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
1105 
1106         let replace_impl = self.project_replace.span().map(|span| {
1107             // For interoperability with `forbid(unsafe_code)`, `unsafe` token should be
1108             // call-site span.
1109             let unsafety = <Token![unsafe]>::default();
1110             quote_spanned! { span =>
1111                 #vis fn project_replace(
1112                     self: ::pin_project::__private::Pin<&mut Self>,
1113                     __replacement: Self,
1114                 ) -> #proj_own_ident #orig_ty_generics {
1115                     #unsafety {
1116                         #proj_own_body
1117                     }
1118                 }
1119             }
1120         });
1121 
1122         quote! {
1123             impl #impl_generics #orig_ident #ty_generics #where_clause {
1124                 #vis fn project<#lifetime>(
1125                     self: ::pin_project::__private::Pin<&#lifetime mut Self>,
1126                 ) -> #proj_ident #proj_ty_generics {
1127                     unsafe {
1128                         #proj_body
1129                     }
1130                 }
1131                 #vis fn project_ref<#lifetime>(
1132                     self: ::pin_project::__private::Pin<&#lifetime Self>,
1133                 ) -> #proj_ref_ident #proj_ty_generics {
1134                     unsafe {
1135                         #proj_ref_body
1136                     }
1137                 }
1138                 #replace_impl
1139             }
1140         }
1141     }
1142 
ensure_not_packed(&self, fields: &Fields) -> Result<TokenStream>1143     fn ensure_not_packed(&self, fields: &Fields) -> Result<TokenStream> {
1144         for meta in self.orig.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
1145             if let Meta::List(list) = meta {
1146                 if list.path.is_ident("repr") {
1147                     for repr in list.nested.iter() {
1148                         match repr {
1149                             NestedMeta::Meta(Meta::Path(path))
1150                             | NestedMeta::Meta(Meta::List(MetaList { path, .. }))
1151                                 if path.is_ident("packed") =>
1152                             {
1153                                 return Err(error!(
1154                                     repr,
1155                                     "#[pin_project] attribute may not be used on #[repr(packed)] types"
1156                                 ));
1157                             }
1158                             _ => {}
1159                         }
1160                     }
1161                 }
1162             }
1163         }
1164 
1165         // As proc-macro-derive can't rewrite the structure definition,
1166         // it's probably no longer necessary, but it keeps it for now.
1167 
1168         // Workaround for https://github.com/taiki-e/pin-project/issues/32
1169         // Through the tricky use of proc macros, it's possible to bypass
1170         // the above check for the `repr` attribute.
1171         // To ensure that it's impossible to use pin projections on a `#[repr(packed)]`
1172         // struct, we generate code like this:
1173         //
1174         // ```rust
1175         // #[forbid(safe_packed_borrows)]
1176         // fn assert_not_repr_packed(val: &MyStruct) {
1177         //     let _field1 = &val.field1;
1178         //     let _field2 = &val.field2;
1179         //     ...
1180         //     let _fieldn = &val.fieldn;
1181         // }
1182         // ```
1183         //
1184         // Taking a reference to a packed field is unsafe, and applying
1185         // `#[forbid(safe_packed_borrows)]` makes sure that doing this without
1186         // an `unsafe` block (which we deliberately do not generate)
1187         // is a hard error.
1188         //
1189         // If the struct ends up having `#[repr(packed)]` applied somehow,
1190         // this will generate an (unfriendly) error message. Under all reasonable
1191         // circumstances, we'll detect the `#[repr(packed)]` attribute, and generate
1192         // a much nicer error above.
1193         //
1194         // There is one exception: If the type of a struct field has an alignment of 1
1195         // (e.g. u8), it is always safe to take a reference to it, even if the struct
1196         // is `#[repr(packed)]`. If the struct is composed entirely of types of
1197         // alignment 1, our generated method will not trigger an error if the
1198         // struct is `#[repr(packed)]`.
1199         //
1200         // Fortunately, this should have no observable consequence - `#[repr(packed)]`
1201         // is essentially a no-op on such a type. Nevertheless, we include a test
1202         // to ensure that the compiler doesn't ever try to copy the fields on
1203         // such a struct when trying to drop it - which is reason we prevent
1204         // `#[repr(packed)]` in the first place.
1205         //
1206         // See also https://github.com/taiki-e/pin-project/pull/34.
1207         let mut field_refs = vec![];
1208         match fields {
1209             Fields::Named(FieldsNamed { named, .. }) => {
1210                 for Field { ident, .. } in named {
1211                     field_refs.push(quote!(&val.#ident;));
1212                 }
1213             }
1214             Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
1215                 for (index, _) in unnamed.iter().enumerate() {
1216                     let index = Index::from(index);
1217                     field_refs.push(quote!(&val.#index;));
1218                 }
1219             }
1220             Fields::Unit => {}
1221         }
1222 
1223         let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
1224         let ident = self.orig.ident;
1225         Ok(quote! {
1226             #[forbid(safe_packed_borrows)]
1227             fn __assert_not_repr_packed #impl_generics (val: &#ident #ty_generics) #where_clause {
1228                 #(#field_refs)*
1229             }
1230         })
1231     }
1232 }
1233