1 use proc_macro2::{Span, TokenStream};
2 use quote::{format_ident, quote, quote_spanned};
3 use syn::{
4     parse::{Parse, ParseBuffer, ParseStream},
5     visit_mut::VisitMut,
6     *,
7 };
8 
9 use crate::utils::*;
10 
11 use super::PIN;
12 
parse_derive(input: TokenStream) -> Result<TokenStream>13 pub(super) fn parse_derive(input: TokenStream) -> Result<TokenStream> {
14     match syn::parse2(input)? {
15         Item::Struct(ItemStruct { attrs, vis, ident, generics, fields, .. }) => {
16             validate_struct(&ident, &fields)?;
17             let mut cx = Context::new(attrs, vis, ident, generics)?;
18 
19             let packed_check = cx.ensure_not_packed(&fields)?;
20             let mut proj_items = cx.parse_struct(&fields)?;
21             proj_items.extend(packed_check);
22             proj_items.extend(cx.make_unpin_impl());
23             proj_items.extend(cx.make_drop_impl());
24             Ok(proj_items)
25         }
26         Item::Enum(ItemEnum { attrs, vis, ident, generics, brace_token, variants, .. }) => {
27             validate_enum(brace_token, &variants)?;
28             let mut cx = Context::new(attrs, vis, ident, generics)?;
29 
30             // We don't need to check for '#[repr(packed)]',
31             // since it does not apply to enums.
32             let mut proj_items = cx.parse_enum(&variants)?;
33             proj_items.extend(cx.make_unpin_impl());
34             proj_items.extend(cx.make_drop_impl());
35             Ok(proj_items)
36         }
37         item => Err(error!(item, "#[pin_project] attribute may only be used on structs or enums")),
38     }
39 }
40 
validate_struct(ident: &Ident, fields: &Fields) -> Result<()>41 fn validate_struct(ident: &Ident, fields: &Fields) -> Result<()> {
42     match fields {
43         Fields::Named(FieldsNamed { named: f, .. })
44         | Fields::Unnamed(FieldsUnnamed { unnamed: f, .. })
45             if f.is_empty() =>
46         {
47             Err(error!(
48                 fields,
49                 "#[pin_project] attribute may not be used on structs with zero fields"
50             ))
51         }
52         Fields::Unit => {
53             Err(error!(ident, "#[pin_project] attribute may not be used on structs with units"))
54         }
55         _ => Ok(()),
56     }
57 }
58 
validate_enum(brace_token: token::Brace, variants: &Variants) -> Result<()>59 fn validate_enum(brace_token: token::Brace, variants: &Variants) -> Result<()> {
60     if variants.is_empty() {
61         return Err(syn::Error::new(
62             brace_token.span,
63             "#[pin_project] attribute may not be used on enums without variants",
64         ));
65     }
66     let has_field = variants.iter().try_fold(false, |has_field, v| {
67         if let Some((_, e)) = &v.discriminant {
68             Err(error!(e, "#[pin_project] attribute may not be used on enums with discriminants"))
69         } else if let Some(attr) = v.attrs.find(PIN) {
70             Err(error!(attr, "#[pin] attribute may only be used on fields of structs or variants"))
71         } else if let Fields::Unit = v.fields {
72             Ok(has_field)
73         } else {
74             Ok(true)
75         }
76     })?;
77     if has_field {
78         Ok(())
79     } else {
80         Err(error!(
81             variants,
82             "#[pin_project] attribute may not be used on enums that have no field"
83         ))
84     }
85 }
86 
87 #[derive(Default)]
88 struct Args {
89     pinned_drop: Option<Span>,
90     unsafe_unpin: Option<Span>,
91 }
92 
93 const DUPLICATE_PIN: &str = "duplicate #[pin] attribute";
94 
95 impl Args {
get(attrs: &[Attribute]) -> Result<Self>96     fn get(attrs: &[Attribute]) -> Result<Self> {
97         let mut prev: Option<(&Attribute, Result<Args>)> = None;
98 
99         for attr in attrs {
100             if attr.path.is_ident(PIN) {
101                 if let Some((prev_attr, prev_res)) = &prev {
102                     // As the `#[pin]` attribute generated by `#[pin_project]`
103                     // has the same span as `#[pin_project]`, it is possible
104                     // that a useless error message will be generated.
105                     let res = syn::parse2::<Self>(attr.tokens.clone());
106                     let span = match (&prev_res, res) {
107                         (Ok(_), Ok(_)) => unreachable!(),
108                         (_, Ok(_)) => prev_attr,
109                         (Ok(_), _) => attr,
110                         (Err(prev_err), Err(_)) => {
111                             if prev_err.to_string() == DUPLICATE_PIN {
112                                 attr
113                             } else {
114                                 prev_attr
115                             }
116                         }
117                     };
118                     return Err(error!(span, DUPLICATE_PIN));
119                 }
120                 prev = Some((attr, syn::parse2::<Self>(attr.tokens.clone())));
121             }
122         }
123 
124         // This `unwrap` only fails if another macro removes `#[pin]`.
125         prev.unwrap().1
126     }
127 }
128 
129 impl Parse for Args {
parse(input: ParseStream<'_>) -> Result<Self>130     fn parse(input: ParseStream<'_>) -> Result<Self> {
131         fn parse_input(input: ParseStream<'_>) -> Result<ParseBuffer<'_>> {
132             // Extracts `#args` from `(#private(#args))`.
133             if let Ok(content) = input.parenthesized() {
134                 if let Ok(private) = content.parse::<Ident>() {
135                     if private == CURRENT_PRIVATE_MODULE {
136                         if let Ok(args) = content.parenthesized() {
137                             return Ok(args);
138                         }
139                     }
140                 }
141             }
142 
143             // If this fails, it means that there is a `#[pin]` attribute
144             // inserted by something other than #[pin_project] attribute.
145             Err(error!(TokenStream::new(), DUPLICATE_PIN))
146         }
147 
148         let input = parse_input(input)?;
149         let mut args = Self::default();
150         while !input.is_empty() {
151             let ident = input.parse::<Ident>()?;
152             match &*ident.to_string() {
153                 "PinnedDrop" => {
154                     if args.pinned_drop.is_some() {
155                         return Err(error!(ident, "duplicate `PinnedDrop` argument"));
156                     }
157                     args.pinned_drop = Some(ident.span());
158                 }
159                 "UnsafeUnpin" => {
160                     if args.unsafe_unpin.is_some() {
161                         return Err(error!(ident, "duplicate `UnsafeUnpin` argument"));
162                     }
163                     args.unsafe_unpin = Some(ident.span());
164                 }
165                 _ => return Err(error!(ident, "unexpected argument: {}", ident)),
166             }
167 
168             if !input.is_empty() {
169                 let _: token::Comma = input.parse()?;
170             }
171         }
172 
173         Ok(args)
174     }
175 }
176 
177 struct OriginalType {
178     /// Attributes of the original type.
179     attrs: Vec<Attribute>,
180     /// Visibility of the original type.
181     vis: Visibility,
182     /// Name of the original type.
183     ident: Ident,
184     /// Generics of the original type.
185     generics: Generics,
186 }
187 
188 struct ProjectedType {
189     /// Visibility of the projected type.
190     vis: Visibility,
191     /// Name of the projected type returned by `project` method.
192     mut_ident: Ident,
193     /// Name of the projected type returned by `project_ref` method.
194     ref_ident: Ident,
195     /// Lifetime on the generated projected type.
196     lifetime: Lifetime,
197     /// Generics of the projected type.
198     generics: Generics,
199 }
200 
201 struct Context {
202     orig: OriginalType,
203     proj: ProjectedType,
204     /// Types of the pinned fields.
205     pinned_fields: Vec<Type>,
206     /// `PinnedDrop` attribute.
207     pinned_drop: Option<Span>,
208     /// `UnsafeUnpin` attribute.
209     unsafe_unpin: Option<Span>,
210 }
211 
212 impl Context {
new( attrs: Vec<Attribute>, vis: Visibility, ident: Ident, mut generics: Generics, ) -> Result<Self>213     fn new(
214         attrs: Vec<Attribute>,
215         vis: Visibility,
216         ident: Ident,
217         mut generics: Generics,
218     ) -> Result<Self> {
219         let Args { pinned_drop, unsafe_unpin } = Args::get(&attrs)?;
220 
221         {
222             let ty_generics = generics.split_for_impl().1;
223             let self_ty = syn::parse_quote!(#ident #ty_generics);
224             let mut visitor = ReplaceReceiver::new(&self_ty);
225             visitor.visit_where_clause_mut(generics.make_where_clause());
226         }
227 
228         let mut lifetime_name = String::from(DEFAULT_LIFETIME_NAME);
229         determine_lifetime_name(&mut lifetime_name, &generics.params);
230         let lifetime = Lifetime::new(&lifetime_name, Span::call_site());
231 
232         let mut proj_generics = generics.clone();
233         insert_lifetime(&mut proj_generics, lifetime.clone());
234 
235         Ok(Self {
236             proj: ProjectedType {
237                 vis: determine_visibility(&vis),
238                 mut_ident: proj_ident(&ident, Mutable),
239                 ref_ident: proj_ident(&ident, Immutable),
240                 lifetime,
241                 generics: proj_generics,
242             },
243             orig: OriginalType { attrs, vis, ident, generics },
244             pinned_drop,
245             unsafe_unpin,
246             pinned_fields: Vec::new(),
247         })
248     }
249 
parse_struct(&mut self, fields: &Fields) -> Result<TokenStream>250     fn parse_struct(&mut self, fields: &Fields) -> Result<TokenStream> {
251         let (proj_pat, proj_init, proj_fields, proj_ref_fields) = match fields {
252             Fields::Named(fields) => self.visit_named(fields)?,
253             Fields::Unnamed(fields) => self.visit_unnamed(fields, true)?,
254             Fields::Unit => unreachable!(),
255         };
256 
257         let orig_ident = &self.orig.ident;
258         let proj_ident = &self.proj.mut_ident;
259         let proj_ref_ident = &self.proj.ref_ident;
260         let vis = &self.proj.vis;
261         let proj_generics = &self.proj.generics;
262         let where_clause = self.orig.generics.split_for_impl().2;
263 
264         let mut proj_items = quote! {
265             #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
266             #[allow(dead_code)] // This lint warns unused fields/variants.
267             #vis struct #proj_ident #proj_generics #where_clause #proj_fields
268             #[allow(dead_code)] // This lint warns unused fields/variants.
269             #vis struct #proj_ref_ident #proj_generics #where_clause #proj_ref_fields
270         };
271 
272         let proj_body = quote! {
273             let #orig_ident #proj_pat = self.get_unchecked_mut();
274             #proj_ident #proj_init
275         };
276         let proj_ref_body = quote! {
277             let #orig_ident #proj_pat = self.get_ref();
278             #proj_ref_ident #proj_init
279         };
280 
281         proj_items.extend(self.make_proj_impl(&proj_body, &proj_ref_body));
282 
283         Ok(proj_items)
284     }
285 
parse_enum(&mut self, variants: &Variants) -> Result<TokenStream>286     fn parse_enum(&mut self, variants: &Variants) -> Result<TokenStream> {
287         let (proj_variants, proj_ref_variants, proj_arms, proj_ref_arms) =
288             self.visit_variants(variants)?;
289 
290         let proj_ident = &self.proj.mut_ident;
291         let proj_ref_ident = &self.proj.ref_ident;
292         let vis = &self.proj.vis;
293         let proj_generics = &self.proj.generics;
294         let where_clause = self.orig.generics.split_for_impl().2;
295 
296         let mut proj_items = quote! {
297             #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
298             #[allow(dead_code)] // This lint warns unused fields/variants.
299             #vis enum #proj_ident #proj_generics #where_clause {
300                 #proj_variants
301             }
302             #[allow(dead_code)] // This lint warns unused fields/variants.
303             #vis enum #proj_ref_ident #proj_generics #where_clause {
304                 #proj_ref_variants
305             }
306         };
307 
308         let proj_body = quote! {
309             match self.get_unchecked_mut() {
310                 #proj_arms
311             }
312         };
313         let proj_ref_body = quote! {
314             match self.get_ref() {
315                 #proj_ref_arms
316             }
317         };
318 
319         proj_items.extend(self.make_proj_impl(&proj_body, &proj_ref_body));
320 
321         Ok(proj_items)
322     }
323 
visit_variants( &mut self, variants: &Variants, ) -> Result<(TokenStream, TokenStream, TokenStream, TokenStream)>324     fn visit_variants(
325         &mut self,
326         variants: &Variants,
327     ) -> Result<(TokenStream, TokenStream, TokenStream, TokenStream)> {
328         let mut proj_variants = TokenStream::new();
329         let mut proj_ref_variants = TokenStream::new();
330         let mut proj_arms = TokenStream::new();
331         let mut proj_ref_arms = TokenStream::new();
332         for Variant { ident, fields, .. } in variants {
333             let (proj_pat, proj_body, proj_fields, proj_ref_fields) = match fields {
334                 Fields::Named(fields) => self.visit_named(fields)?,
335                 Fields::Unnamed(fields) => self.visit_unnamed(fields, false)?,
336                 Fields::Unit => {
337                     (TokenStream::new(), TokenStream::new(), TokenStream::new(), TokenStream::new())
338                 }
339             };
340 
341             let orig_ident = &self.orig.ident;
342             let proj_ident = &self.proj.mut_ident;
343             let proj_ref_ident = &self.proj.ref_ident;
344             proj_variants.extend(quote! {
345                 #ident #proj_fields,
346             });
347             proj_ref_variants.extend(quote! {
348                 #ident #proj_ref_fields,
349             });
350             proj_arms.extend(quote! {
351                 #orig_ident::#ident #proj_pat => {
352                     #proj_ident::#ident #proj_body
353                 }
354             });
355             proj_ref_arms.extend(quote! {
356                 #orig_ident::#ident #proj_pat => {
357                     #proj_ref_ident::#ident #proj_body
358                 }
359             });
360         }
361 
362         Ok((proj_variants, proj_ref_variants, proj_arms, proj_ref_arms))
363     }
364 
365     fn visit_named(
366         &mut self,
367         FieldsNamed { named: fields, .. }: &FieldsNamed,
368     ) -> Result<(TokenStream, TokenStream, TokenStream, TokenStream)> {
369         let mut proj_pat = Vec::with_capacity(fields.len());
370         let mut proj_body = Vec::with_capacity(fields.len());
371         let mut proj_fields = Vec::with_capacity(fields.len());
372         let mut proj_ref_fields = Vec::with_capacity(fields.len());
373         for Field { attrs, vis, ident, ty, .. } in fields {
374             if attrs.find_exact(PIN)?.is_some() {
375                 self.pinned_fields.push(ty.clone());
376 
377                 let lifetime = &self.proj.lifetime;
378                 proj_fields.push(quote! {
379                     #vis #ident: ::core::pin::Pin<&#lifetime mut (#ty)>
380                 });
381                 proj_ref_fields.push(quote! {
382                     #vis #ident: ::core::pin::Pin<&#lifetime (#ty)>
383                 });
384                 proj_body.push(quote! {
385                     #ident: ::core::pin::Pin::new_unchecked(#ident)
386                 });
387             } else {
388                 let lifetime = &self.proj.lifetime;
389                 proj_fields.push(quote! {
390                     #vis #ident: &#lifetime mut (#ty)
391                 });
392                 proj_ref_fields.push(quote! {
393                     #vis #ident: &#lifetime (#ty)
394                 });
395                 proj_body.push(quote! {
396                     #ident
397                 });
398             }
399             proj_pat.push(ident);
400         }
401 
402         let proj_pat = quote!({ #(#proj_pat),* });
403         let proj_body = quote!({ #(#proj_body),* });
404         let proj_fields = quote!({ #(#proj_fields),* });
405         let proj_ref_fields = quote!({ #(#proj_ref_fields),* });
406 
407         Ok((proj_pat, proj_body, proj_fields, proj_ref_fields))
408     }
409 
410     fn visit_unnamed(
411         &mut self,
412         FieldsUnnamed { unnamed: fields, .. }: &FieldsUnnamed,
413         is_struct: bool,
414     ) -> Result<(TokenStream, TokenStream, TokenStream, TokenStream)> {
415         let mut proj_pat = Vec::with_capacity(fields.len());
416         let mut proj_body = Vec::with_capacity(fields.len());
417         let mut proj_fields = Vec::with_capacity(fields.len());
418         let mut proj_ref_fields = Vec::with_capacity(fields.len());
419         for (i, Field { attrs, vis, ty, .. }) in fields.iter().enumerate() {
420             let id = format_ident!("_{}", i);
421             if attrs.find_exact(PIN)?.is_some() {
422                 self.pinned_fields.push(ty.clone());
423 
424                 let lifetime = &self.proj.lifetime;
425                 proj_fields.push(quote! {
426                     #vis ::core::pin::Pin<&#lifetime mut (#ty)>
427                 });
428                 proj_ref_fields.push(quote! {
429                     #vis ::core::pin::Pin<&#lifetime (#ty)>
430                 });
431                 proj_body.push(quote! {
432                     ::core::pin::Pin::new_unchecked(#id)
433                 });
434             } else {
435                 let lifetime = &self.proj.lifetime;
436                 proj_fields.push(quote! {
437                     #vis &#lifetime mut (#ty)
438                 });
439                 proj_ref_fields.push(quote! {
440                     #vis &#lifetime (#ty)
441                 });
442                 proj_body.push(quote! {
443                     #id
444                 });
445             }
446             proj_pat.push(id);
447         }
448 
449         let proj_pat = quote!((#(#proj_pat),*));
450         let proj_body = quote!((#(#proj_body),*));
451         let (proj_fields, proj_ref_fields) = if is_struct {
452             (quote!((#(#proj_fields),*);), quote!((#(#proj_ref_fields),*);))
453         } else {
454             (quote!((#(#proj_fields),*)), quote!((#(#proj_ref_fields),*)))
455         };
456 
457         Ok((proj_pat, proj_body, proj_fields, proj_ref_fields))
458     }
459 
460     /// Creates conditional `Unpin` implementation for original type.
make_unpin_impl(&mut self) -> TokenStream461     fn make_unpin_impl(&mut self) -> TokenStream {
462         if let Some(unsafe_unpin) = self.unsafe_unpin {
463             let mut proj_generics = self.proj.generics.clone();
464             let orig_ident = &self.orig.ident;
465             let lifetime = &self.proj.lifetime;
466 
467             let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
468             proj_generics.make_where_clause().predicates.push(
469                 // Make the error message highlight `UnsafeUnpin` argument.
470                 syn::parse2(quote_spanned! { unsafe_unpin =>
471                     ::pin_project::#private::Wrapper<#lifetime, Self>: ::pin_project::UnsafeUnpin
472                 })
473                 .unwrap(),
474             );
475 
476             let (impl_generics, _, where_clause) = proj_generics.split_for_impl();
477             let ty_generics = self.orig.generics.split_for_impl().1;
478 
479             quote! {
480                 #[allow(single_use_lifetimes)]
481                 impl #impl_generics ::core::marker::Unpin for #orig_ident #ty_generics #where_clause {}
482             }
483         } else {
484             let mut full_where_clause = self.orig.generics.where_clause.as_ref().cloned().unwrap();
485             let orig_ident = &self.orig.ident;
486 
487             let make_span = || {
488                 #[cfg(pin_project_show_unpin_struct)]
489                 {
490                     proc_macro::Span::def_site().into()
491                 }
492                 #[cfg(not(pin_project_show_unpin_struct))]
493                 {
494                     Span::call_site()
495                 }
496             };
497 
498             let struct_ident = format_ident!("__{}", orig_ident, span = make_span());
499 
500             // Generate a field in our new struct for every
501             // pinned field in the original type.
502             let fields: Vec<_> = self
503                 .pinned_fields
504                 .iter()
505                 .enumerate()
506                 .map(|(i, ty)| {
507                     let field_ident = format_ident!("__field{}", i);
508                     quote! {
509                         #field_ident: #ty
510                     }
511                 })
512                 .collect();
513 
514             // We could try to determine the subset of type parameters
515             // and lifetimes that are actually used by the pinned fields
516             // (as opposed to those only used by unpinned fields).
517             // However, this would be tricky and error-prone, since
518             // it's possible for users to create types that would alias
519             // with generic parameters (e.g. 'struct T').
520             //
521             // Instead, we generate a use of every single type parameter
522             // and lifetime used in the original struct. For type parameters,
523             // we generate code like this:
524             //
525             // ```rust
526             // struct AlwaysUnpin<T: ?Sized>(PhantomData<T>) {}
527             // impl<T: ?Sized> Unpin for AlwaysUnpin<T> {}
528             //
529             // ...
530             // _field: AlwaysUnpin<(A, B, C)>
531             // ```
532             //
533             // This ensures that any unused type parameters
534             // don't end up with Unpin bounds.
535             let lifetime_fields: Vec<_> = self
536                 .orig
537                 .generics
538                 .lifetimes()
539                 .enumerate()
540                 .map(|(i, LifetimeDef { lifetime, .. })| {
541                     let field_ident = format_ident!("__lifetime{}", i);
542                     quote! {
543                         #field_ident: &#lifetime ()
544                     }
545                 })
546                 .collect();
547 
548             let scope_ident = format_ident!("__unpin_scope_{}", orig_ident);
549 
550             let vis = &self.orig.vis;
551             let lifetime = &self.proj.lifetime;
552             let type_params: Vec<_> = self.orig.generics.type_params().map(|t| &t.ident).collect();
553             let proj_generics = &self.proj.generics;
554             let (impl_generics, proj_ty_generics, _) = proj_generics.split_for_impl();
555             let (_, ty_generics, where_clause) = self.orig.generics.split_for_impl();
556 
557             full_where_clause.predicates.push(syn::parse_quote! {
558                 #struct_ident #proj_ty_generics: ::core::marker::Unpin
559             });
560 
561             let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
562             let inner_data = quote! {
563                 // This needs to have the same visibility as the original type,
564                 // due to the limitations of the 'public in private' error.
565                 //
566                 // Out goal is to implement the public trait Unpin for
567                 // a potentially public user type. Because of this, rust
568                 // requires that any types mentioned in the where clause of
569                 // our Unpin impl also be public. This means that our generated
570                 // 'UnpinStruct' type must also be public. However, we take
571                 // steps to ensure that the user can never actually reference
572                 // this 'public' type. These steps are described below.
573                 //
574                 // See also https://github.com/taiki-e/pin-project/pull/53.
575                 #vis struct #struct_ident #proj_generics #where_clause {
576                     __pin_project_use_generics: ::pin_project::#private::AlwaysUnpin<#lifetime, (#(#type_params),*)>,
577 
578                     #(#fields,)*
579                     #(#lifetime_fields,)*
580                 }
581 
582                 impl #impl_generics ::core::marker::Unpin for #orig_ident #ty_generics #full_where_clause {}
583             };
584 
585             if cfg!(pin_project_show_unpin_struct) {
586                 // On nightly, we use def-site hygiene to make it impossible
587                 // for user code to refer to any of the types we define.
588                 // This allows us to omit wrapping the generated types
589                 // in an fn() scope, allowing rustdoc to properly document
590                 // them.
591                 inner_data
592             } else {
593                 // When we're not on nightly, we need to create an enclosing fn() scope
594                 // for all of our generated items. This makes it impossible for
595                 // user code to refer to any of our generated types, but has
596                 // the advantage of preventing Rustdoc from displaying
597                 // docs for any of our types. In particular, users cannot see
598                 // the automatically generated Unpin impl for the 'UnpinStruct$Name' types.
599                 quote! {
600                     #[allow(non_snake_case)]
601                     fn #scope_ident() {
602                         #inner_data
603                     }
604                 }
605             }
606         }
607     }
608 
609     /// Creates `Drop` implementation for original type.
make_drop_impl(&self) -> TokenStream610     fn make_drop_impl(&self) -> TokenStream {
611         let ident = &self.orig.ident;
612         let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
613 
614         let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
615         if let Some(pinned_drop) = self.pinned_drop {
616             // Make the error message highlight `PinnedDrop` argument.
617             // See https://github.com/taiki-e/pin-project/issues/16#issuecomment-513586812
618             // for why this is only for the span of function calls, not the entire `impl` block.
619             let call_drop = quote_spanned! { pinned_drop =>
620                 ::pin_project::#private::PinnedDrop::drop(pinned_self)
621             };
622 
623             quote! {
624                 #[allow(single_use_lifetimes)]
625                 impl #impl_generics ::core::ops::Drop for #ident #ty_generics #where_clause {
626                     fn drop(&mut self) {
627                         // Safety - we're in 'drop', so we know that 'self' will
628                         // never move again.
629                         let pinned_self = unsafe { ::core::pin::Pin::new_unchecked(self) };
630                         // We call `pinned_drop` only once. Since `PinnedDrop::drop`
631                         // is an unsafe function and a private API, it is never called again in safe
632                         // code *unless the user uses a maliciously crafted macro*.
633                         unsafe {
634                             #call_drop;
635                         }
636                     }
637                 }
638             }
639         } else {
640             // If the user does not provide a pinned_drop impl,
641             // we need to ensure that they don't provide a `Drop` impl of their
642             // own.
643             // Based on https://github.com/upsuper/assert-impl/blob/f503255b292ab0ba8d085b657f4065403cfa46eb/src/lib.rs#L80-L87
644             //
645             // We create a new identifier for each struct, so that the traits
646             // for different types do not conflict with each other.
647             //
648             // Another approach would be to provide an empty Drop impl,
649             // which would conflict with a user-provided Drop impl.
650             // However, this would trigger the compiler's special handling
651             // of Drop types (e.g. fields cannot be moved out of a Drop type).
652             // This approach prevents the creation of needless Drop impls,
653             // giving users more flexibility.
654             let trait_ident = format_ident!("{}MustNotImplDrop", ident);
655 
656             quote! {
657                 // There are two possible cases:
658                 // 1. The user type does not implement Drop. In this case,
659                 // the first blanked impl will not apply to it. This code
660                 // will compile, as there is only one impl of MustNotImplDrop for the user type
661                 // 2. The user type does impl Drop. This will make the blanket impl applicable,
662                 // which will then conflict with the explicit MustNotImplDrop impl below.
663                 // This will result in a compilation error, which is exactly what we want.
664                 trait #trait_ident {}
665                 #[allow(clippy::drop_bounds)]
666                 impl<T: ::core::ops::Drop> #trait_ident for T {}
667                 #[allow(single_use_lifetimes)]
668                 impl #impl_generics #trait_ident for #ident #ty_generics #where_clause {}
669 
670                 // A dummy impl of `PinnedDrop`, to ensure that the user cannot implement it.
671                 // Since the user did not pass `PinnedDrop` to `#[pin_project]`, any `PinnedDrop`
672                 // impl will not actually be called. Unfortunately, we can't detect this situation
673                 // directly from either the `#[pin_project]` or `#[pinned_drop]` attributes, since
674                 // we don't know what other attirbutes/impl may exist.
675                 //
676                 // To ensure that users don't accidentally write a non-functional `PinnedDrop`
677                 // impls, we emit one ourselves. If the user ends up writing a `PinnedDrop` impl,
678                 // they'll get a "conflicting implementations of trait" error when coherence
679                 // checks are run
680                 #[allow(single_use_lifetimes)]
681                 impl #impl_generics ::pin_project::#private::PinnedDrop for #ident #ty_generics #where_clause {
682                     unsafe fn drop(self: ::core::pin::Pin<&mut Self>) {}
683                 }
684             }
685         }
686     }
687 
688     /// Creates an implementation of the projection method.
make_proj_impl(&self, proj_body: &TokenStream, proj_ref_body: &TokenStream) -> TokenStream689     fn make_proj_impl(&self, proj_body: &TokenStream, proj_ref_body: &TokenStream) -> TokenStream {
690         let vis = &self.proj.vis;
691         let lifetime = &self.proj.lifetime;
692         let orig_ident = &self.orig.ident;
693         let proj_ident = &self.proj.mut_ident;
694         let proj_ref_ident = &self.proj.ref_ident;
695 
696         let proj_ty_generics = self.proj.generics.split_for_impl().1;
697         let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
698 
699         quote! {
700             impl #impl_generics #orig_ident #ty_generics #where_clause {
701                 #vis fn project<#lifetime>(
702                     self: ::core::pin::Pin<&#lifetime mut Self>,
703                 ) -> #proj_ident #proj_ty_generics {
704                     unsafe {
705                         #proj_body
706                     }
707                 }
708                 #vis fn project_ref<#lifetime>(
709                     self: ::core::pin::Pin<&#lifetime Self>,
710                 ) -> #proj_ref_ident #proj_ty_generics {
711                     unsafe {
712                         #proj_ref_body
713                     }
714                 }
715             }
716         }
717     }
718 
ensure_not_packed(&self, fields: &Fields) -> Result<TokenStream>719     fn ensure_not_packed(&self, fields: &Fields) -> Result<TokenStream> {
720         for meta in self.orig.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
721             if let Meta::List(l) = meta {
722                 if l.path.is_ident("repr") {
723                     for repr in l.nested.iter() {
724                         match repr {
725                             NestedMeta::Meta(Meta::Path(path))
726                             | NestedMeta::Meta(Meta::List(MetaList { path, .. }))
727                                 if path.is_ident("packed") =>
728                             {
729                                 return Err(error!(
730                                     repr,
731                                     "#[pin_project] attribute may not be used on #[repr(packed)] types"
732                                 ));
733                             }
734                             _ => {}
735                         }
736                     }
737                 }
738             }
739         }
740 
741         // As proc-macro-derive can't rewrite the structure definition,
742         // it's probably no longer necessary, but it keeps it for now.
743 
744         // Workaround for https://github.com/taiki-e/pin-project/issues/32
745         // Through the tricky use of proc macros, it's possible to bypass
746         // the above check for the 'repr' attribute.
747         // To ensure that it's impossible to use pin projections on a #[repr(packed)]
748         // struct, we generate code like this:
749         //
750         // #[deny(safe_packed_borrows)]
751         // fn enforce_not_packed_for_MyStruct(val: &MyStruct) {
752         //  let _field1 = &val.field1;
753         //  let _field2 = &val.field2;
754         //  ...
755         //  let _fieldn = &val.fieldn;
756         // }
757         //
758         // Taking a reference to a packed field is unsafe, and applying
759         // #[deny(safe_packed_borrows)] makes sure that doing this without
760         // an 'unsafe' block (which we deliberately do not generate)
761         // is a hard error.
762         //
763         // If the struct ends up having #[repr(packed)] applied somehow,
764         // this will generate an (unfriendly) error message. Under all reasonable
765         // circumstances, we'll detect the #[repr(packed)] attribute, and generate
766         // a much nicer error above.
767         //
768         // There is one exception: If the type of a struct field has an alignment of 1
769         // (e.g. u8), it is always safe to take a reference to it, even if the struct
770         // is #[repr(packed)]. If the struct is composed entirely of types of alignment 1,
771         // our generated method will not trigger an error if the struct is #[repr(packed)]
772         //
773         // Fortunately, this should have no observable consequence - #[repr(packed)]
774         // is essentially a no-op on such a type. Nevertheless, we include a test
775         // to ensure that the compiler doesn't ever try to copy the fields on
776         // such a struct when trying to drop it - which is reason we prevent
777         // #[repr(packed)] in the first place.
778         //
779         // See also https://github.com/taiki-e/pin-project/pull/34.
780         let mut field_refs = vec![];
781         match fields {
782             Fields::Named(FieldsNamed { named, .. }) => {
783                 for Field { ident, .. } in named {
784                     field_refs.push(quote! {
785                         &val.#ident;
786                     });
787                 }
788             }
789             Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
790                 for (index, _) in unnamed.iter().enumerate() {
791                     let index = Index::from(index);
792                     field_refs.push(quote! {
793                         &val.#index;
794                     });
795                 }
796             }
797             Fields::Unit => {}
798         }
799 
800         let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
801 
802         let struct_name = &self.orig.ident;
803         let method_name = format_ident!("__pin_project_assert_not_repr_packed_{}", self.orig.ident);
804         Ok(quote! {
805             #[allow(single_use_lifetimes)]
806             #[allow(non_snake_case)]
807             #[deny(safe_packed_borrows)]
808             fn #method_name #impl_generics (val: &#struct_name #ty_generics) #where_clause {
809                 #(#field_refs)*
810             }
811         })
812     }
813 }
814