1 //! This crate provides helper types for matching against enum variants, and
2 //! extracting bindings to each of the fields in the deriving Struct or Enum in
3 //! a generic way.
4 //!
5 //! If you are writing a `#[derive]` which needs to perform some operation on
6 //! every field, then you have come to the right place!
7 //!
8 //! # Example: `WalkFields`
9 //! ### Trait Implementation
10 //! ```
11 //! pub trait WalkFields: std::any::Any {
12 //!     fn walk_fields(&self, walk: &mut FnMut(&WalkFields));
13 //! }
14 //! impl WalkFields for i32 {
15 //!     fn walk_fields(&self, _walk: &mut FnMut(&WalkFields)) {}
16 //! }
17 //! ```
18 //!
19 //! ### Custom Derive
20 //! ```
21 //! # use quote::quote;
22 //! fn walkfields_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
23 //!     let body = s.each(|bi| quote!{
24 //!         walk(#bi)
25 //!     });
26 //!
27 //!     s.gen_impl(quote! {
28 //!         extern crate synstructure_test_traits;
29 //!
30 //!         gen impl synstructure_test_traits::WalkFields for @Self {
31 //!             fn walk_fields(&self, walk: &mut FnMut(&synstructure_test_traits::WalkFields)) {
32 //!                 match *self { #body }
33 //!             }
34 //!         }
35 //!     })
36 //! }
37 //! # const _IGNORE: &'static str = stringify!(
38 //! synstructure::decl_derive!([WalkFields] => walkfields_derive);
39 //! # );
40 //!
41 //! /*
42 //!  * Test Case
43 //!  */
44 //! fn main() {
45 //!     synstructure::test_derive! {
46 //!         walkfields_derive {
47 //!             enum A<T> {
48 //!                 B(i32, T),
49 //!                 C(i32),
50 //!             }
51 //!         }
52 //!         expands to {
53 //!             #[allow(non_upper_case_globals)]
54 //!             const _DERIVE_synstructure_test_traits_WalkFields_FOR_A: () = {
55 //!                 extern crate synstructure_test_traits;
56 //!                 impl<T> synstructure_test_traits::WalkFields for A<T>
57 //!                     where T: synstructure_test_traits::WalkFields
58 //!                 {
59 //!                     fn walk_fields(&self, walk: &mut FnMut(&synstructure_test_traits::WalkFields)) {
60 //!                         match *self {
61 //!                             A::B(ref __binding_0, ref __binding_1,) => {
62 //!                                 { walk(__binding_0) }
63 //!                                 { walk(__binding_1) }
64 //!                             }
65 //!                             A::C(ref __binding_0,) => {
66 //!                                 { walk(__binding_0) }
67 //!                             }
68 //!                         }
69 //!                     }
70 //!                 }
71 //!             };
72 //!         }
73 //!     }
74 //! }
75 //! ```
76 //!
77 //! # Example: `Interest`
78 //! ### Trait Implementation
79 //! ```
80 //! pub trait Interest {
81 //!     fn interesting(&self) -> bool;
82 //! }
83 //! impl Interest for i32 {
84 //!     fn interesting(&self) -> bool { *self > 0 }
85 //! }
86 //! ```
87 //!
88 //! ### Custom Derive
89 //! ```
90 //! # use quote::quote;
91 //! fn interest_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream {
92 //!     let body = s.fold(false, |acc, bi| quote!{
93 //!         #acc || synstructure_test_traits::Interest::interesting(#bi)
94 //!     });
95 //!
96 //!     s.gen_impl(quote! {
97 //!         extern crate synstructure_test_traits;
98 //!         gen impl synstructure_test_traits::Interest for @Self {
99 //!             fn interesting(&self) -> bool {
100 //!                 match *self {
101 //!                     #body
102 //!                 }
103 //!             }
104 //!         }
105 //!     })
106 //! }
107 //! # const _IGNORE: &'static str = stringify!(
108 //! synstructure::decl_derive!([Interest] => interest_derive);
109 //! # );
110 //!
111 //! /*
112 //!  * Test Case
113 //!  */
114 //! fn main() {
115 //!     synstructure::test_derive!{
116 //!         interest_derive {
117 //!             enum A<T> {
118 //!                 B(i32, T),
119 //!                 C(i32),
120 //!             }
121 //!         }
122 //!         expands to {
123 //!             #[allow(non_upper_case_globals)]
124 //!             const _DERIVE_synstructure_test_traits_Interest_FOR_A: () = {
125 //!                 extern crate synstructure_test_traits;
126 //!                 impl<T> synstructure_test_traits::Interest for A<T>
127 //!                     where T: synstructure_test_traits::Interest
128 //!                 {
129 //!                     fn interesting(&self) -> bool {
130 //!                         match *self {
131 //!                             A::B(ref __binding_0, ref __binding_1,) => {
132 //!                                 false ||
133 //!                                     synstructure_test_traits::Interest::interesting(__binding_0) ||
134 //!                                     synstructure_test_traits::Interest::interesting(__binding_1)
135 //!                             }
136 //!                             A::C(ref __binding_0,) => {
137 //!                                 false ||
138 //!                                     synstructure_test_traits::Interest::interesting(__binding_0)
139 //!                             }
140 //!                         }
141 //!                     }
142 //!                 }
143 //!             };
144 //!         }
145 //!     }
146 //! }
147 //! ```
148 //!
149 //! For more example usage, consider investigating the `abomonation_derive` crate,
150 //! which makes use of this crate, and is fairly simple.
151 
152 #[cfg(all(
153     not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
154     feature = "proc-macro"
155 ))]
156 extern crate proc_macro;
157 
158 use std::collections::HashSet;
159 
160 use syn::parse::{ParseStream, Parser};
161 use syn::visit::{self, Visit};
162 use syn::{
163     braced, punctuated, token, Attribute, Data, DeriveInput, Error, Expr, Field, Fields,
164     FieldsNamed, FieldsUnnamed, GenericParam, Generics, Ident, PredicateType, Result, Token,
165     TraitBound, Type, TypeMacro, TypeParamBound, TypePath, WhereClause, WherePredicate,
166 };
167 
168 use quote::{format_ident, quote_spanned, ToTokens};
169 // re-export the quote! macro so we can depend on it being around in our macro's
170 // implementations.
171 #[doc(hidden)]
172 pub use quote::quote;
173 
174 use unicode_xid::UnicodeXID;
175 
176 use proc_macro2::{Span, TokenStream, TokenTree};
177 
178 // NOTE: This module has documentation hidden, as it only exports macros (which
179 // always appear in the root of the crate) and helper methods / re-exports used
180 // in the implementation of those macros.
181 #[doc(hidden)]
182 pub mod macros;
183 
184 /// Changes how bounds are added
185 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
186 pub enum AddBounds {
187     /// Add for fields and generics
188     Both,
189     /// Fields only
190     Fields,
191     /// Generics only
192     Generics,
193     /// None
194     None,
195     #[doc(hidden)]
196     __Nonexhaustive,
197 }
198 
199 /// The type of binding to use when generating a pattern.
200 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
201 pub enum BindStyle {
202     /// `x`
203     Move,
204     /// `mut x`
205     MoveMut,
206     /// `ref x`
207     Ref,
208     /// `ref mut x`
209     RefMut,
210 }
211 
212 impl ToTokens for BindStyle {
to_tokens(&self, tokens: &mut TokenStream)213     fn to_tokens(&self, tokens: &mut TokenStream) {
214         match self {
215             BindStyle::Move => {}
216             BindStyle::MoveMut => quote_spanned!(Span::call_site() => mut).to_tokens(tokens),
217             BindStyle::Ref => quote_spanned!(Span::call_site() => ref).to_tokens(tokens),
218             BindStyle::RefMut => quote_spanned!(Span::call_site() => ref mut).to_tokens(tokens),
219         }
220     }
221 }
222 
223 // Internal method for merging seen_generics arrays together.
generics_fuse(res: &mut Vec<bool>, new: &[bool])224 fn generics_fuse(res: &mut Vec<bool>, new: &[bool]) {
225     for (i, &flag) in new.iter().enumerate() {
226         if i == res.len() {
227             res.push(false);
228         }
229         if flag {
230             res[i] = true;
231         }
232     }
233 }
234 
235 // Internal method for extracting the set of generics which have been matched.
fetch_generics<'a>(set: &[bool], generics: &'a Generics) -> Vec<&'a Ident>236 fn fetch_generics<'a>(set: &[bool], generics: &'a Generics) -> Vec<&'a Ident> {
237     let mut tys = vec![];
238     for (&seen, param) in set.iter().zip(generics.params.iter()) {
239         if seen {
240             if let GenericParam::Type(tparam) = param {
241                 tys.push(&tparam.ident)
242             }
243         }
244     }
245     tys
246 }
247 
248 // Internal method for sanitizing an identifier for hygiene purposes.
sanitize_ident(s: &str) -> Ident249 fn sanitize_ident(s: &str) -> Ident {
250     let mut res = String::with_capacity(s.len());
251     for mut c in s.chars() {
252         if !UnicodeXID::is_xid_continue(c) {
253             c = '_'
254         }
255         // Deduplicate consecutive _ characters.
256         if res.ends_with('_') && c == '_' {
257             continue;
258         }
259         res.push(c);
260     }
261     Ident::new(&res, Span::call_site())
262 }
263 
264 // Internal method to merge two Generics objects together intelligently.
merge_generics(into: &mut Generics, from: &Generics) -> Result<()>265 fn merge_generics(into: &mut Generics, from: &Generics) -> Result<()> {
266     // Try to add the param into `into`, and merge parmas with identical names.
267     for p in &from.params {
268         for op in &into.params {
269             match (op, p) {
270                 (GenericParam::Type(otp), GenericParam::Type(tp)) => {
271                     // NOTE: This is only OK because syn ignores the span for equality purposes.
272                     if otp.ident == tp.ident {
273                         return Err(Error::new_spanned(
274                             p,
275                             format!(
276                                 "Attempted to merge conflicting generic parameters: {} and {}",
277                                 quote!(#op),
278                                 quote!(#p)
279                             ),
280                         ));
281                     }
282                 }
283                 (GenericParam::Lifetime(olp), GenericParam::Lifetime(lp)) => {
284                     // NOTE: This is only OK because syn ignores the span for equality purposes.
285                     if olp.lifetime == lp.lifetime {
286                         return Err(Error::new_spanned(
287                             p,
288                             format!(
289                                 "Attempted to merge conflicting generic parameters: {} and {}",
290                                 quote!(#op),
291                                 quote!(#p)
292                             ),
293                         ));
294                     }
295                 }
296                 // We don't support merging Const parameters, because that wouldn't make much sense.
297                 _ => (),
298             }
299         }
300         into.params.push(p.clone());
301     }
302 
303     // Add any where clauses from the input generics object.
304     if let Some(from_clause) = &from.where_clause {
305         into.make_where_clause()
306             .predicates
307             .extend(from_clause.predicates.iter().cloned());
308     }
309 
310     Ok(())
311 }
312 
313 /// Helper method which does the same thing as rustc 1.20's
314 /// `Option::get_or_insert_with`. This method is used to keep backwards
315 /// compatibility with rustc 1.15.
get_or_insert_with<T, F>(opt: &mut Option<T>, f: F) -> &mut T where F: FnOnce() -> T,316 fn get_or_insert_with<T, F>(opt: &mut Option<T>, f: F) -> &mut T
317 where
318     F: FnOnce() -> T,
319 {
320     if opt.is_none() {
321         *opt = Some(f());
322     }
323 
324     match opt {
325         Some(v) => v,
326         None => unreachable!(),
327     }
328 }
329 
330 /// Information about a specific binding. This contains both an `Ident`
331 /// reference to the given field, and the syn `&'a Field` descriptor for that
332 /// field.
333 ///
334 /// This type supports `quote::ToTokens`, so can be directly used within the
335 /// `quote!` macro. It expands to a reference to the matched field.
336 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
337 pub struct BindingInfo<'a> {
338     /// The name which this BindingInfo will bind to.
339     pub binding: Ident,
340 
341     /// The type of binding which this BindingInfo will create.
342     pub style: BindStyle,
343 
344     field: &'a Field,
345 
346     // These are used to determine which type parameters are avaliable.
347     generics: &'a Generics,
348     seen_generics: Vec<bool>,
349     // The original index of the binding
350     // this will not change when .filter() is called
351     index: usize,
352 }
353 
354 impl<'a> ToTokens for BindingInfo<'a> {
to_tokens(&self, tokens: &mut TokenStream)355     fn to_tokens(&self, tokens: &mut TokenStream) {
356         self.binding.to_tokens(tokens);
357     }
358 }
359 
360 impl<'a> BindingInfo<'a> {
361     /// Returns a reference to the underlying `syn` AST node which this
362     /// `BindingInfo` references
ast(&self) -> &'a Field363     pub fn ast(&self) -> &'a Field {
364         self.field
365     }
366 
367     /// Generates the pattern fragment for this field binding.
368     ///
369     /// # Example
370     /// ```
371     /// # use synstructure::*;
372     /// let di: syn::DeriveInput = syn::parse_quote! {
373     ///     enum A {
374     ///         B{ a: i32, b: i32 },
375     ///         C(u32),
376     ///     }
377     /// };
378     /// let s = Structure::new(&di);
379     ///
380     /// assert_eq!(
381     ///     s.variants()[0].bindings()[0].pat().to_string(),
382     ///     quote! {
383     ///         ref __binding_0
384     ///     }.to_string()
385     /// );
386     /// ```
pat(&self) -> TokenStream387     pub fn pat(&self) -> TokenStream {
388         let BindingInfo { binding, style, .. } = self;
389         quote!(#style #binding)
390     }
391 
392     /// Returns a list of the type parameters which are referenced in this
393     /// field's type.
394     ///
395     /// # Caveat
396     ///
397     /// If the field contains any macros in type position, all parameters will
398     /// be considered bound. This is because we cannot determine which type
399     /// parameters are bound by type macros.
400     ///
401     /// # Example
402     /// ```
403     /// # use synstructure::*;
404     /// let di: syn::DeriveInput = syn::parse_quote! {
405     ///     struct A<T, U> {
406     ///         a: Option<T>,
407     ///         b: U,
408     ///     }
409     /// };
410     /// let mut s = Structure::new(&di);
411     ///
412     /// assert_eq!(
413     ///     s.variants()[0].bindings()[0].referenced_ty_params(),
414     ///     &[&quote::format_ident!("T")]
415     /// );
416     /// ```
referenced_ty_params(&self) -> Vec<&'a Ident>417     pub fn referenced_ty_params(&self) -> Vec<&'a Ident> {
418         fetch_generics(&self.seen_generics, self.generics)
419     }
420 }
421 
422 /// This type is similar to `syn`'s `Variant` type, however each of the fields
423 /// are references rather than owned. When this is used as the AST for a real
424 /// variant, this struct simply borrows the fields of the `syn::Variant`,
425 /// however this type may also be used as the sole variant for a struct.
426 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
427 pub struct VariantAst<'a> {
428     pub attrs: &'a [Attribute],
429     pub ident: &'a Ident,
430     pub fields: &'a Fields,
431     pub discriminant: &'a Option<(token::Eq, Expr)>,
432 }
433 
434 /// A wrapper around a `syn::DeriveInput`'s variant which provides utilities
435 /// for destructuring `Variant`s with `match` expressions.
436 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
437 pub struct VariantInfo<'a> {
438     pub prefix: Option<&'a Ident>,
439     bindings: Vec<BindingInfo<'a>>,
440     ast: VariantAst<'a>,
441     generics: &'a Generics,
442     // The original length of `bindings` before any `.filter()` calls
443     original_length: usize,
444 }
445 
446 /// Helper function used by the VariantInfo constructor. Walks all of the types
447 /// in `field` and returns a list of the type parameters from `ty_params` which
448 /// are referenced in the field.
get_ty_params(field: &Field, generics: &Generics) -> Vec<bool>449 fn get_ty_params(field: &Field, generics: &Generics) -> Vec<bool> {
450     // Helper type. Discovers all identifiers inside of the visited type,
451     // and calls a callback with them.
452     struct BoundTypeLocator<'a> {
453         result: Vec<bool>,
454         generics: &'a Generics,
455     }
456 
457     impl<'a> Visit<'a> for BoundTypeLocator<'a> {
458         // XXX: This also (intentionally) captures paths like T::SomeType. Is
459         // this desirable?
460         fn visit_ident(&mut self, id: &Ident) {
461             for (idx, i) in self.generics.params.iter().enumerate() {
462                 if let GenericParam::Type(tparam) = i {
463                     if tparam.ident == *id {
464                         self.result[idx] = true;
465                     }
466                 }
467             }
468         }
469 
470         fn visit_type_macro(&mut self, x: &'a TypeMacro) {
471             // If we see a type_mac declaration, then we can't know what type parameters
472             // it might be binding, so we presume it binds all of them.
473             for r in &mut self.result {
474                 *r = true;
475             }
476             visit::visit_type_macro(self, x)
477         }
478     }
479 
480     let mut btl = BoundTypeLocator {
481         result: vec![false; generics.params.len()],
482         generics,
483     };
484 
485     btl.visit_type(&field.ty);
486 
487     btl.result
488 }
489 
490 impl<'a> VariantInfo<'a> {
new(ast: VariantAst<'a>, prefix: Option<&'a Ident>, generics: &'a Generics) -> Self491     fn new(ast: VariantAst<'a>, prefix: Option<&'a Ident>, generics: &'a Generics) -> Self {
492         let bindings = match ast.fields {
493             Fields::Unit => vec![],
494             Fields::Unnamed(FieldsUnnamed {
495                 unnamed: fields, ..
496             })
497             | Fields::Named(FieldsNamed { named: fields, .. }) => {
498                 fields
499                     .into_iter()
500                     .enumerate()
501                     .map(|(i, field)| {
502                         BindingInfo {
503                             // XXX: This has to be call_site to avoid privacy
504                             // when deriving on private fields.
505                             binding: format_ident!("__binding_{}", i),
506                             style: BindStyle::Ref,
507                             field,
508                             generics,
509                             seen_generics: get_ty_params(field, generics),
510                             index: i,
511                         }
512                     })
513                     .collect::<Vec<_>>()
514             }
515         };
516 
517         let original_length = bindings.len();
518         VariantInfo {
519             prefix,
520             bindings,
521             ast,
522             generics,
523             original_length,
524         }
525     }
526 
527     /// Returns a slice of the bindings in this Variant.
bindings(&self) -> &[BindingInfo<'a>]528     pub fn bindings(&self) -> &[BindingInfo<'a>] {
529         &self.bindings
530     }
531 
532     /// Returns a mut slice of the bindings in this Variant.
bindings_mut(&mut self) -> &mut [BindingInfo<'a>]533     pub fn bindings_mut(&mut self) -> &mut [BindingInfo<'a>] {
534         &mut self.bindings
535     }
536 
537     /// Returns a `VariantAst` object which contains references to the
538     /// underlying `syn` AST node which this `Variant` was created from.
ast(&self) -> VariantAst<'a>539     pub fn ast(&self) -> VariantAst<'a> {
540         self.ast
541     }
542 
543     /// True if any bindings were omitted due to a `filter` call.
omitted_bindings(&self) -> bool544     pub fn omitted_bindings(&self) -> bool {
545         self.original_length != self.bindings.len()
546     }
547 
548     /// Generates the match-arm pattern which could be used to match against this Variant.
549     ///
550     /// # Example
551     /// ```
552     /// # use synstructure::*;
553     /// let di: syn::DeriveInput = syn::parse_quote! {
554     ///     enum A {
555     ///         B(i32, i32),
556     ///         C(u32),
557     ///     }
558     /// };
559     /// let s = Structure::new(&di);
560     ///
561     /// assert_eq!(
562     ///     s.variants()[0].pat().to_string(),
563     ///     quote!{
564     ///         A::B(ref __binding_0, ref __binding_1,)
565     ///     }.to_string()
566     /// );
567     /// ```
pat(&self) -> TokenStream568     pub fn pat(&self) -> TokenStream {
569         let mut t = TokenStream::new();
570         if let Some(prefix) = self.prefix {
571             prefix.to_tokens(&mut t);
572             quote!(::).to_tokens(&mut t);
573         }
574         self.ast.ident.to_tokens(&mut t);
575         match self.ast.fields {
576             Fields::Unit => {
577                 assert!(self.bindings.is_empty());
578             }
579             Fields::Unnamed(..) => token::Paren(Span::call_site()).surround(&mut t, |t| {
580                 let mut expected_index = 0;
581                 for binding in &self.bindings {
582                     while expected_index < binding.index {
583                         quote!(_,).to_tokens(t);
584                         expected_index += 1;
585                     }
586                     binding.pat().to_tokens(t);
587                     quote!(,).to_tokens(t);
588                     expected_index += 1;
589                 }
590                 if expected_index != self.original_length {
591                     quote!(..).to_tokens(t);
592                 }
593             }),
594             Fields::Named(..) => token::Brace(Span::call_site()).surround(&mut t, |t| {
595                 for binding in &self.bindings {
596                     binding.field.ident.to_tokens(t);
597                     quote!(:).to_tokens(t);
598                     binding.pat().to_tokens(t);
599                     quote!(,).to_tokens(t);
600                 }
601                 if self.omitted_bindings() {
602                     quote!(..).to_tokens(t);
603                 }
604             }),
605         }
606         t
607     }
608 
609     /// Generates the token stream required to construct the current variant.
610     ///
611     /// The init array initializes each of the fields in the order they are
612     /// written in `variant.ast().fields`.
613     ///
614     /// # Example
615     /// ```
616     /// # use synstructure::*;
617     /// let di: syn::DeriveInput = syn::parse_quote! {
618     ///     enum A {
619     ///         B(usize, usize),
620     ///         C{ v: usize },
621     ///     }
622     /// };
623     /// let s = Structure::new(&di);
624     ///
625     /// assert_eq!(
626     ///     s.variants()[0].construct(|_, i| quote!(#i)).to_string(),
627     ///
628     ///     quote!{
629     ///         A::B(0usize, 1usize,)
630     ///     }.to_string()
631     /// );
632     ///
633     /// assert_eq!(
634     ///     s.variants()[1].construct(|_, i| quote!(#i)).to_string(),
635     ///
636     ///     quote!{
637     ///         A::C{ v: 0usize, }
638     ///     }.to_string()
639     /// );
640     /// ```
construct<F, T>(&self, mut func: F) -> TokenStream where F: FnMut(&Field, usize) -> T, T: ToTokens,641     pub fn construct<F, T>(&self, mut func: F) -> TokenStream
642     where
643         F: FnMut(&Field, usize) -> T,
644         T: ToTokens,
645     {
646         let mut t = TokenStream::new();
647         if let Some(prefix) = self.prefix {
648             quote!(#prefix ::).to_tokens(&mut t);
649         }
650         self.ast.ident.to_tokens(&mut t);
651 
652         match &self.ast.fields {
653             Fields::Unit => (),
654             Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
655                 token::Paren::default().surround(&mut t, |t| {
656                     for (i, field) in unnamed.into_iter().enumerate() {
657                         func(field, i).to_tokens(t);
658                         quote!(,).to_tokens(t);
659                     }
660                 })
661             }
662             Fields::Named(FieldsNamed { named, .. }) => {
663                 token::Brace::default().surround(&mut t, |t| {
664                     for (i, field) in named.into_iter().enumerate() {
665                         field.ident.to_tokens(t);
666                         quote!(:).to_tokens(t);
667                         func(field, i).to_tokens(t);
668                         quote!(,).to_tokens(t);
669                     }
670                 })
671             }
672         }
673         t
674     }
675 
676     /// Runs the passed-in function once for each bound field, passing in a `BindingInfo`.
677     /// and generating a `match` arm which evaluates the returned tokens.
678     ///
679     /// This method will ignore fields which are ignored through the `filter`
680     /// method.
681     ///
682     /// # Example
683     /// ```
684     /// # use synstructure::*;
685     /// let di: syn::DeriveInput = syn::parse_quote! {
686     ///     enum A {
687     ///         B(i32, i32),
688     ///         C(u32),
689     ///     }
690     /// };
691     /// let s = Structure::new(&di);
692     ///
693     /// assert_eq!(
694     ///     s.variants()[0].each(|bi| quote!(println!("{:?}", #bi))).to_string(),
695     ///
696     ///     quote!{
697     ///         A::B(ref __binding_0, ref __binding_1,) => {
698     ///             { println!("{:?}", __binding_0) }
699     ///             { println!("{:?}", __binding_1) }
700     ///         }
701     ///     }.to_string()
702     /// );
703     /// ```
each<F, R>(&self, mut f: F) -> TokenStream where F: FnMut(&BindingInfo<'_>) -> R, R: ToTokens,704     pub fn each<F, R>(&self, mut f: F) -> TokenStream
705     where
706         F: FnMut(&BindingInfo<'_>) -> R,
707         R: ToTokens,
708     {
709         let pat = self.pat();
710         let mut body = TokenStream::new();
711         for binding in &self.bindings {
712             token::Brace::default().surround(&mut body, |body| {
713                 f(binding).to_tokens(body);
714             });
715         }
716         quote!(#pat => { #body })
717     }
718 
719     /// Runs the passed-in function once for each bound field, passing in the
720     /// result of the previous call, and a `BindingInfo`. generating a `match`
721     /// arm which evaluates to the resulting tokens.
722     ///
723     /// This method will ignore fields which are ignored through the `filter`
724     /// method.
725     ///
726     /// # Example
727     /// ```
728     /// # use synstructure::*;
729     /// let di: syn::DeriveInput = syn::parse_quote! {
730     ///     enum A {
731     ///         B(i32, i32),
732     ///         C(u32),
733     ///     }
734     /// };
735     /// let s = Structure::new(&di);
736     ///
737     /// assert_eq!(
738     ///     s.variants()[0].fold(quote!(0), |acc, bi| quote!(#acc + #bi)).to_string(),
739     ///
740     ///     quote!{
741     ///         A::B(ref __binding_0, ref __binding_1,) => {
742     ///             0 + __binding_0 + __binding_1
743     ///         }
744     ///     }.to_string()
745     /// );
746     /// ```
fold<F, I, R>(&self, init: I, mut f: F) -> TokenStream where F: FnMut(TokenStream, &BindingInfo<'_>) -> R, I: ToTokens, R: ToTokens,747     pub fn fold<F, I, R>(&self, init: I, mut f: F) -> TokenStream
748     where
749         F: FnMut(TokenStream, &BindingInfo<'_>) -> R,
750         I: ToTokens,
751         R: ToTokens,
752     {
753         let pat = self.pat();
754         let body = self.bindings.iter().fold(quote!(#init), |i, bi| {
755             let r = f(i, bi);
756             quote!(#r)
757         });
758         quote!(#pat => { #body })
759     }
760 
761     /// Filter the bindings created by this `Variant` object. This has 2 effects:
762     ///
763     /// * The bindings will no longer appear in match arms generated by methods
764     ///   on this `Variant` or its subobjects.
765     ///
766     /// * Impl blocks created with the `bound_impl` or `unsafe_bound_impl`
767     ///   method only consider type parameters referenced in the types of
768     ///   non-filtered fields.
769     ///
770     /// # Example
771     /// ```
772     /// # use synstructure::*;
773     /// let di: syn::DeriveInput = syn::parse_quote! {
774     ///     enum A {
775     ///         B{ a: i32, b: i32 },
776     ///         C{ a: u32 },
777     ///     }
778     /// };
779     /// let mut s = Structure::new(&di);
780     ///
781     /// s.variants_mut()[0].filter(|bi| {
782     ///     bi.ast().ident == Some(quote::format_ident!("b"))
783     /// });
784     ///
785     /// assert_eq!(
786     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
787     ///
788     ///     quote!{
789     ///         A::B{ b: ref __binding_1, .. } => {
790     ///             { println!("{:?}", __binding_1) }
791     ///         }
792     ///         A::C{ a: ref __binding_0, } => {
793     ///             { println!("{:?}", __binding_0) }
794     ///         }
795     ///     }.to_string()
796     /// );
797     /// ```
filter<F>(&mut self, f: F) -> &mut Self where F: FnMut(&BindingInfo<'_>) -> bool,798     pub fn filter<F>(&mut self, f: F) -> &mut Self
799     where
800         F: FnMut(&BindingInfo<'_>) -> bool,
801     {
802         self.bindings.retain(f);
803         self
804     }
805 
806     /// Remove the binding at the given index.
807     ///
808     /// # Panics
809     ///
810     /// Panics if the index is out of range.
remove_binding(&mut self, idx: usize) -> &mut Self811     pub fn remove_binding(&mut self, idx: usize) -> &mut Self {
812         self.bindings.remove(idx);
813         self
814     }
815 
816     /// Updates the `BindStyle` for each of the passed-in fields by calling the
817     /// passed-in function for each `BindingInfo`.
818     ///
819     /// # Example
820     /// ```
821     /// # use synstructure::*;
822     /// let di: syn::DeriveInput = syn::parse_quote! {
823     ///     enum A {
824     ///         B(i32, i32),
825     ///         C(u32),
826     ///     }
827     /// };
828     /// let mut s = Structure::new(&di);
829     ///
830     /// s.variants_mut()[0].bind_with(|bi| BindStyle::RefMut);
831     ///
832     /// assert_eq!(
833     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
834     ///
835     ///     quote!{
836     ///         A::B(ref mut __binding_0, ref mut __binding_1,) => {
837     ///             { println!("{:?}", __binding_0) }
838     ///             { println!("{:?}", __binding_1) }
839     ///         }
840     ///         A::C(ref __binding_0,) => {
841     ///             { println!("{:?}", __binding_0) }
842     ///         }
843     ///     }.to_string()
844     /// );
845     /// ```
bind_with<F>(&mut self, mut f: F) -> &mut Self where F: FnMut(&BindingInfo<'_>) -> BindStyle,846     pub fn bind_with<F>(&mut self, mut f: F) -> &mut Self
847     where
848         F: FnMut(&BindingInfo<'_>) -> BindStyle,
849     {
850         for binding in &mut self.bindings {
851             binding.style = f(&binding);
852         }
853         self
854     }
855 
856     /// Updates the binding name for each fo the passed-in fields by calling the
857     /// passed-in function for each `BindingInfo`.
858     ///
859     /// The function will be called with the `BindingInfo` and its index in the
860     /// enclosing variant.
861     ///
862     /// The default name is `__binding_{}` where `{}` is replaced with an
863     /// increasing number.
864     ///
865     /// # Example
866     /// ```
867     /// # use synstructure::*;
868     /// let di: syn::DeriveInput = syn::parse_quote! {
869     ///     enum A {
870     ///         B{ a: i32, b: i32 },
871     ///         C{ a: u32 },
872     ///     }
873     /// };
874     /// let mut s = Structure::new(&di);
875     ///
876     /// s.variants_mut()[0].binding_name(|bi, i| bi.ident.clone().unwrap());
877     ///
878     /// assert_eq!(
879     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
880     ///
881     ///     quote!{
882     ///         A::B{ a: ref a, b: ref b, } => {
883     ///             { println!("{:?}", a) }
884     ///             { println!("{:?}", b) }
885     ///         }
886     ///         A::C{ a: ref __binding_0, } => {
887     ///             { println!("{:?}", __binding_0) }
888     ///         }
889     ///     }.to_string()
890     /// );
891     /// ```
binding_name<F>(&mut self, mut f: F) -> &mut Self where F: FnMut(&Field, usize) -> Ident,892     pub fn binding_name<F>(&mut self, mut f: F) -> &mut Self
893     where
894         F: FnMut(&Field, usize) -> Ident,
895     {
896         for (it, binding) in self.bindings.iter_mut().enumerate() {
897             binding.binding = f(binding.field, it);
898         }
899         self
900     }
901 
902     /// Returns a list of the type parameters which are referenced in this
903     /// field's type.
904     ///
905     /// # Caveat
906     ///
907     /// If the field contains any macros in type position, all parameters will
908     /// be considered bound. This is because we cannot determine which type
909     /// parameters are bound by type macros.
910     ///
911     /// # Example
912     /// ```
913     /// # use synstructure::*;
914     /// let di: syn::DeriveInput = syn::parse_quote! {
915     ///     struct A<T, U> {
916     ///         a: Option<T>,
917     ///         b: U,
918     ///     }
919     /// };
920     /// let mut s = Structure::new(&di);
921     ///
922     /// assert_eq!(
923     ///     s.variants()[0].bindings()[0].referenced_ty_params(),
924     ///     &[&quote::format_ident!("T")]
925     /// );
926     /// ```
referenced_ty_params(&self) -> Vec<&'a Ident>927     pub fn referenced_ty_params(&self) -> Vec<&'a Ident> {
928         let mut flags = Vec::new();
929         for binding in &self.bindings {
930             generics_fuse(&mut flags, &binding.seen_generics);
931         }
932         fetch_generics(&flags, self.generics)
933     }
934 }
935 
936 /// A wrapper around a `syn::DeriveInput` which provides utilities for creating
937 /// custom derive trait implementations.
938 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
939 pub struct Structure<'a> {
940     variants: Vec<VariantInfo<'a>>,
941     omitted_variants: bool,
942     underscore_const: bool,
943     ast: &'a DeriveInput,
944     extra_impl: Vec<GenericParam>,
945     extra_predicates: Vec<WherePredicate>,
946     add_bounds: AddBounds,
947 }
948 
949 impl<'a> Structure<'a> {
950     /// Create a new `Structure` with the variants and fields from the passed-in
951     /// `DeriveInput`.
952     ///
953     /// # Panics
954     ///
955     /// This method will panic if the provided AST node represents an untagged
956     /// union.
new(ast: &'a DeriveInput) -> Self957     pub fn new(ast: &'a DeriveInput) -> Self {
958         Self::try_new(ast).expect("Unable to create synstructure::Structure")
959     }
960 
961     /// Create a new `Structure` with the variants and fields from the passed-in
962     /// `DeriveInput`.
963     ///
964     /// Unlike `Structure::new`, this method does not panic if the provided AST
965     /// node represents an untagged union.
try_new(ast: &'a DeriveInput) -> Result<Self>966     pub fn try_new(ast: &'a DeriveInput) -> Result<Self> {
967         let variants = match &ast.data {
968             Data::Enum(data) => (&data.variants)
969                 .into_iter()
970                 .map(|v| {
971                     VariantInfo::new(
972                         VariantAst {
973                             attrs: &v.attrs,
974                             ident: &v.ident,
975                             fields: &v.fields,
976                             discriminant: &v.discriminant,
977                         },
978                         Some(&ast.ident),
979                         &ast.generics,
980                     )
981                 })
982                 .collect::<Vec<_>>(),
983             Data::Struct(data) => {
984                 // SAFETY NOTE: Normally putting an `Expr` in static storage
985                 // wouldn't be safe, because it could contain `Term` objects
986                 // which use thread-local interning. However, this static always
987                 // contains the value `None`. Thus, it will never contain any
988                 // unsafe values.
989                 struct UnsafeMakeSync(Option<(token::Eq, Expr)>);
990                 unsafe impl Sync for UnsafeMakeSync {}
991                 static NONE_DISCRIMINANT: UnsafeMakeSync = UnsafeMakeSync(None);
992 
993                 vec![VariantInfo::new(
994                     VariantAst {
995                         attrs: &ast.attrs,
996                         ident: &ast.ident,
997                         fields: &data.fields,
998                         discriminant: &NONE_DISCRIMINANT.0,
999                     },
1000                     None,
1001                     &ast.generics,
1002                 )]
1003             }
1004             Data::Union(_) => {
1005                 return Err(Error::new_spanned(
1006                     ast,
1007                     "unexpected unsupported untagged union",
1008                 ));
1009             }
1010         };
1011 
1012         Ok(Structure {
1013             variants,
1014             omitted_variants: false,
1015             underscore_const: false,
1016             ast,
1017             extra_impl: vec![],
1018             extra_predicates: vec![],
1019             add_bounds: AddBounds::Both,
1020         })
1021     }
1022 
1023     /// Returns a slice of the variants in this Structure.
variants(&self) -> &[VariantInfo<'a>]1024     pub fn variants(&self) -> &[VariantInfo<'a>] {
1025         &self.variants
1026     }
1027 
1028     /// Returns a mut slice of the variants in this Structure.
variants_mut(&mut self) -> &mut [VariantInfo<'a>]1029     pub fn variants_mut(&mut self) -> &mut [VariantInfo<'a>] {
1030         &mut self.variants
1031     }
1032 
1033     /// Returns a reference to the underlying `syn` AST node which this
1034     /// `Structure` was created from.
ast(&self) -> &'a DeriveInput1035     pub fn ast(&self) -> &'a DeriveInput {
1036         self.ast
1037     }
1038 
1039     /// True if any variants were omitted due to a `filter_variants` call.
omitted_variants(&self) -> bool1040     pub fn omitted_variants(&self) -> bool {
1041         self.omitted_variants
1042     }
1043 
1044     /// Runs the passed-in function once for each bound field, passing in a `BindingInfo`.
1045     /// and generating `match` arms which evaluate the returned tokens.
1046     ///
1047     /// This method will ignore variants or fields which are ignored through the
1048     /// `filter` and `filter_variant` methods.
1049     ///
1050     /// # Example
1051     /// ```
1052     /// # use synstructure::*;
1053     /// let di: syn::DeriveInput = syn::parse_quote! {
1054     ///     enum A {
1055     ///         B(i32, i32),
1056     ///         C(u32),
1057     ///     }
1058     /// };
1059     /// let s = Structure::new(&di);
1060     ///
1061     /// assert_eq!(
1062     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
1063     ///
1064     ///     quote!{
1065     ///         A::B(ref __binding_0, ref __binding_1,) => {
1066     ///             { println!("{:?}", __binding_0) }
1067     ///             { println!("{:?}", __binding_1) }
1068     ///         }
1069     ///         A::C(ref __binding_0,) => {
1070     ///             { println!("{:?}", __binding_0) }
1071     ///         }
1072     ///     }.to_string()
1073     /// );
1074     /// ```
each<F, R>(&self, mut f: F) -> TokenStream where F: FnMut(&BindingInfo<'_>) -> R, R: ToTokens,1075     pub fn each<F, R>(&self, mut f: F) -> TokenStream
1076     where
1077         F: FnMut(&BindingInfo<'_>) -> R,
1078         R: ToTokens,
1079     {
1080         let mut t = TokenStream::new();
1081         for variant in &self.variants {
1082             variant.each(&mut f).to_tokens(&mut t);
1083         }
1084         if self.omitted_variants {
1085             quote!(_ => {}).to_tokens(&mut t);
1086         }
1087         t
1088     }
1089 
1090     /// Runs the passed-in function once for each bound field, passing in the
1091     /// result of the previous call, and a `BindingInfo`. generating `match`
1092     /// arms which evaluate to the resulting tokens.
1093     ///
1094     /// This method will ignore variants or fields which are ignored through the
1095     /// `filter` and `filter_variant` methods.
1096     ///
1097     /// If a variant has been ignored, it will return the `init` value.
1098     ///
1099     /// # Example
1100     /// ```
1101     /// # use synstructure::*;
1102     /// let di: syn::DeriveInput = syn::parse_quote! {
1103     ///     enum A {
1104     ///         B(i32, i32),
1105     ///         C(u32),
1106     ///     }
1107     /// };
1108     /// let s = Structure::new(&di);
1109     ///
1110     /// assert_eq!(
1111     ///     s.fold(quote!(0), |acc, bi| quote!(#acc + #bi)).to_string(),
1112     ///
1113     ///     quote!{
1114     ///         A::B(ref __binding_0, ref __binding_1,) => {
1115     ///             0 + __binding_0 + __binding_1
1116     ///         }
1117     ///         A::C(ref __binding_0,) => {
1118     ///             0 + __binding_0
1119     ///         }
1120     ///     }.to_string()
1121     /// );
1122     /// ```
fold<F, I, R>(&self, init: I, mut f: F) -> TokenStream where F: FnMut(TokenStream, &BindingInfo<'_>) -> R, I: ToTokens, R: ToTokens,1123     pub fn fold<F, I, R>(&self, init: I, mut f: F) -> TokenStream
1124     where
1125         F: FnMut(TokenStream, &BindingInfo<'_>) -> R,
1126         I: ToTokens,
1127         R: ToTokens,
1128     {
1129         let mut t = TokenStream::new();
1130         for variant in &self.variants {
1131             variant.fold(&init, &mut f).to_tokens(&mut t);
1132         }
1133         if self.omitted_variants {
1134             quote!(_ => { #init }).to_tokens(&mut t);
1135         }
1136         t
1137     }
1138 
1139     /// Runs the passed-in function once for each variant, passing in a
1140     /// `VariantInfo`. and generating `match` arms which evaluate the returned
1141     /// tokens.
1142     ///
1143     /// This method will ignore variants and not bind fields which are ignored
1144     /// through the `filter` and `filter_variant` methods.
1145     ///
1146     /// # Example
1147     /// ```
1148     /// # use synstructure::*;
1149     /// let di: syn::DeriveInput = syn::parse_quote! {
1150     ///     enum A {
1151     ///         B(i32, i32),
1152     ///         C(u32),
1153     ///     }
1154     /// };
1155     /// let s = Structure::new(&di);
1156     ///
1157     /// assert_eq!(
1158     ///     s.each_variant(|v| {
1159     ///         let name = &v.ast().ident;
1160     ///         quote!(println!(stringify!(#name)))
1161     ///     }).to_string(),
1162     ///
1163     ///     quote!{
1164     ///         A::B(ref __binding_0, ref __binding_1,) => {
1165     ///             println!(stringify!(B))
1166     ///         }
1167     ///         A::C(ref __binding_0,) => {
1168     ///             println!(stringify!(C))
1169     ///         }
1170     ///     }.to_string()
1171     /// );
1172     /// ```
each_variant<F, R>(&self, mut f: F) -> TokenStream where F: FnMut(&VariantInfo<'_>) -> R, R: ToTokens,1173     pub fn each_variant<F, R>(&self, mut f: F) -> TokenStream
1174     where
1175         F: FnMut(&VariantInfo<'_>) -> R,
1176         R: ToTokens,
1177     {
1178         let mut t = TokenStream::new();
1179         for variant in &self.variants {
1180             let pat = variant.pat();
1181             let body = f(variant);
1182             quote!(#pat => { #body }).to_tokens(&mut t);
1183         }
1184         if self.omitted_variants {
1185             quote!(_ => {}).to_tokens(&mut t);
1186         }
1187         t
1188     }
1189 
1190     /// Filter the bindings created by this `Structure` object. This has 2 effects:
1191     ///
1192     /// * The bindings will no longer appear in match arms generated by methods
1193     ///   on this `Structure` or its subobjects.
1194     ///
1195     /// * Impl blocks created with the `bound_impl` or `unsafe_bound_impl`
1196     ///   method only consider type parameters referenced in the types of
1197     ///   non-filtered fields.
1198     ///
1199     /// # Example
1200     /// ```
1201     /// # use synstructure::*;
1202     /// let di: syn::DeriveInput = syn::parse_quote! {
1203     ///     enum A {
1204     ///         B{ a: i32, b: i32 },
1205     ///         C{ a: u32 },
1206     ///     }
1207     /// };
1208     /// let mut s = Structure::new(&di);
1209     ///
1210     /// s.filter(|bi| {
1211     ///     bi.ast().ident == Some(quote::format_ident!("a"))
1212     /// });
1213     ///
1214     /// assert_eq!(
1215     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
1216     ///
1217     ///     quote!{
1218     ///         A::B{ a: ref __binding_0, .. } => {
1219     ///             { println!("{:?}", __binding_0) }
1220     ///         }
1221     ///         A::C{ a: ref __binding_0, } => {
1222     ///             { println!("{:?}", __binding_0) }
1223     ///         }
1224     ///     }.to_string()
1225     /// );
1226     /// ```
filter<F>(&mut self, mut f: F) -> &mut Self where F: FnMut(&BindingInfo<'_>) -> bool,1227     pub fn filter<F>(&mut self, mut f: F) -> &mut Self
1228     where
1229         F: FnMut(&BindingInfo<'_>) -> bool,
1230     {
1231         for variant in &mut self.variants {
1232             variant.filter(&mut f);
1233         }
1234         self
1235     }
1236 
1237     /// Specify additional where predicate bounds which should be generated by
1238     /// impl-generating functions such as `gen_impl`, `bound_impl`, and
1239     /// `unsafe_bound_impl`.
1240     ///
1241     /// # Example
1242     /// ```
1243     /// # use synstructure::*;
1244     /// let di: syn::DeriveInput = syn::parse_quote! {
1245     ///     enum A<T, U> {
1246     ///         B(T),
1247     ///         C(Option<U>),
1248     ///     }
1249     /// };
1250     /// let mut s = Structure::new(&di);
1251     ///
1252     /// // Add an additional where predicate.
1253     /// s.add_where_predicate(syn::parse_quote!(T: std::fmt::Display));
1254     ///
1255     /// assert_eq!(
1256     ///     s.bound_impl(quote!(krate::Trait), quote!{
1257     ///         fn a() {}
1258     ///     }).to_string(),
1259     ///     quote!{
1260     ///         #[allow(non_upper_case_globals)]
1261     ///         #[doc(hidden)]
1262     ///         const _DERIVE_krate_Trait_FOR_A: () = {
1263     ///             extern crate krate;
1264     ///             impl<T, U> krate::Trait for A<T, U>
1265     ///                 where T: std::fmt::Display,
1266     ///                       T: krate::Trait,
1267     ///                       Option<U>: krate::Trait,
1268     ///                       U: krate::Trait
1269     ///             {
1270     ///                 fn a() {}
1271     ///             }
1272     ///         };
1273     ///     }.to_string()
1274     /// );
1275     /// ```
add_where_predicate(&mut self, pred: WherePredicate) -> &mut Self1276     pub fn add_where_predicate(&mut self, pred: WherePredicate) -> &mut Self {
1277         self.extra_predicates.push(pred);
1278         self
1279     }
1280 
1281     /// Specify which bounds should be generated by impl-generating functions
1282     /// such as `gen_impl`, `bound_impl`, and `unsafe_bound_impl`.
1283     ///
1284     /// The default behaviour is to generate both field and generic bounds from
1285     /// type parameters.
1286     ///
1287     /// # Example
1288     /// ```
1289     /// # use synstructure::*;
1290     /// let di: syn::DeriveInput = syn::parse_quote! {
1291     ///     enum A<T, U> {
1292     ///         B(T),
1293     ///         C(Option<U>),
1294     ///     }
1295     /// };
1296     /// let mut s = Structure::new(&di);
1297     ///
1298     /// // Limit bounds to only generics.
1299     /// s.add_bounds(AddBounds::Generics);
1300     ///
1301     /// assert_eq!(
1302     ///     s.bound_impl(quote!(krate::Trait), quote!{
1303     ///         fn a() {}
1304     ///     }).to_string(),
1305     ///     quote!{
1306     ///         #[allow(non_upper_case_globals)]
1307     ///         #[doc(hidden)]
1308     ///         const _DERIVE_krate_Trait_FOR_A: () = {
1309     ///             extern crate krate;
1310     ///             impl<T, U> krate::Trait for A<T, U>
1311     ///                 where T: krate::Trait,
1312     ///                       U: krate::Trait
1313     ///             {
1314     ///                 fn a() {}
1315     ///             }
1316     ///         };
1317     ///     }.to_string()
1318     /// );
1319     /// ```
add_bounds(&mut self, mode: AddBounds) -> &mut Self1320     pub fn add_bounds(&mut self, mode: AddBounds) -> &mut Self {
1321         self.add_bounds = mode;
1322         self
1323     }
1324 
1325     /// Filter the variants matched by this `Structure` object. This has 2 effects:
1326     ///
1327     /// * Match arms destructuring these variants will no longer be generated by
1328     ///   methods on this `Structure`
1329     ///
1330     /// * Impl blocks created with the `bound_impl` or `unsafe_bound_impl`
1331     ///   method only consider type parameters referenced in the types of
1332     ///   fields in non-fitered variants.
1333     ///
1334     /// # Example
1335     /// ```
1336     /// # use synstructure::*;
1337     /// let di: syn::DeriveInput = syn::parse_quote! {
1338     ///     enum A {
1339     ///         B(i32, i32),
1340     ///         C(u32),
1341     ///     }
1342     /// };
1343     ///
1344     /// let mut s = Structure::new(&di);
1345     ///
1346     /// s.filter_variants(|v| v.ast().ident != "B");
1347     ///
1348     /// assert_eq!(
1349     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
1350     ///
1351     ///     quote!{
1352     ///         A::C(ref __binding_0,) => {
1353     ///             { println!("{:?}", __binding_0) }
1354     ///         }
1355     ///         _ => {}
1356     ///     }.to_string()
1357     /// );
1358     /// ```
filter_variants<F>(&mut self, f: F) -> &mut Self where F: FnMut(&VariantInfo<'_>) -> bool,1359     pub fn filter_variants<F>(&mut self, f: F) -> &mut Self
1360     where
1361         F: FnMut(&VariantInfo<'_>) -> bool,
1362     {
1363         let before_len = self.variants.len();
1364         self.variants.retain(f);
1365         if self.variants.len() != before_len {
1366             self.omitted_variants = true;
1367         }
1368         self
1369     }
1370 
1371     /// Remove the variant at the given index.
1372     ///
1373     /// # Panics
1374     ///
1375     /// Panics if the index is out of range.
remove_variant(&mut self, idx: usize) -> &mut Self1376     pub fn remove_variant(&mut self, idx: usize) -> &mut Self {
1377         self.variants.remove(idx);
1378         self.omitted_variants = true;
1379         self
1380     }
1381 
1382     /// Updates the `BindStyle` for each of the passed-in fields by calling the
1383     /// passed-in function for each `BindingInfo`.
1384     ///
1385     /// # Example
1386     /// ```
1387     /// # use synstructure::*;
1388     /// let di: syn::DeriveInput = syn::parse_quote! {
1389     ///     enum A {
1390     ///         B(i32, i32),
1391     ///         C(u32),
1392     ///     }
1393     /// };
1394     /// let mut s = Structure::new(&di);
1395     ///
1396     /// s.bind_with(|bi| BindStyle::RefMut);
1397     ///
1398     /// assert_eq!(
1399     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
1400     ///
1401     ///     quote!{
1402     ///         A::B(ref mut __binding_0, ref mut __binding_1,) => {
1403     ///             { println!("{:?}", __binding_0) }
1404     ///             { println!("{:?}", __binding_1) }
1405     ///         }
1406     ///         A::C(ref mut __binding_0,) => {
1407     ///             { println!("{:?}", __binding_0) }
1408     ///         }
1409     ///     }.to_string()
1410     /// );
1411     /// ```
bind_with<F>(&mut self, mut f: F) -> &mut Self where F: FnMut(&BindingInfo<'_>) -> BindStyle,1412     pub fn bind_with<F>(&mut self, mut f: F) -> &mut Self
1413     where
1414         F: FnMut(&BindingInfo<'_>) -> BindStyle,
1415     {
1416         for variant in &mut self.variants {
1417             variant.bind_with(&mut f);
1418         }
1419         self
1420     }
1421 
1422     /// Updates the binding name for each fo the passed-in fields by calling the
1423     /// passed-in function for each `BindingInfo`.
1424     ///
1425     /// The function will be called with the `BindingInfo` and its index in the
1426     /// enclosing variant.
1427     ///
1428     /// The default name is `__binding_{}` where `{}` is replaced with an
1429     /// increasing number.
1430     ///
1431     /// # Example
1432     /// ```
1433     /// # use synstructure::*;
1434     /// let di: syn::DeriveInput = syn::parse_quote! {
1435     ///     enum A {
1436     ///         B{ a: i32, b: i32 },
1437     ///         C{ a: u32 },
1438     ///     }
1439     /// };
1440     /// let mut s = Structure::new(&di);
1441     ///
1442     /// s.binding_name(|bi, i| bi.ident.clone().unwrap());
1443     ///
1444     /// assert_eq!(
1445     ///     s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
1446     ///
1447     ///     quote!{
1448     ///         A::B{ a: ref a, b: ref b, } => {
1449     ///             { println!("{:?}", a) }
1450     ///             { println!("{:?}", b) }
1451     ///         }
1452     ///         A::C{ a: ref a, } => {
1453     ///             { println!("{:?}", a) }
1454     ///         }
1455     ///     }.to_string()
1456     /// );
1457     /// ```
binding_name<F>(&mut self, mut f: F) -> &mut Self where F: FnMut(&Field, usize) -> Ident,1458     pub fn binding_name<F>(&mut self, mut f: F) -> &mut Self
1459     where
1460         F: FnMut(&Field, usize) -> Ident,
1461     {
1462         for variant in &mut self.variants {
1463             variant.binding_name(&mut f);
1464         }
1465         self
1466     }
1467 
1468     /// Returns a list of the type parameters which are refrenced in the types
1469     /// of non-filtered fields / variants.
1470     ///
1471     /// # Caveat
1472     ///
1473     /// If the struct contains any macros in type position, all parameters will
1474     /// be considered bound. This is because we cannot determine which type
1475     /// parameters are bound by type macros.
1476     ///
1477     /// # Example
1478     /// ```
1479     /// # use synstructure::*;
1480     /// let di: syn::DeriveInput = syn::parse_quote! {
1481     ///     enum A<T, U> {
1482     ///         B(T, i32),
1483     ///         C(Option<U>),
1484     ///     }
1485     /// };
1486     /// let mut s = Structure::new(&di);
1487     ///
1488     /// s.filter_variants(|v| v.ast().ident != "C");
1489     ///
1490     /// assert_eq!(
1491     ///     s.referenced_ty_params(),
1492     ///     &[&quote::format_ident!("T")]
1493     /// );
1494     /// ```
referenced_ty_params(&self) -> Vec<&'a Ident>1495     pub fn referenced_ty_params(&self) -> Vec<&'a Ident> {
1496         let mut flags = Vec::new();
1497         for variant in &self.variants {
1498             for binding in &variant.bindings {
1499                 generics_fuse(&mut flags, &binding.seen_generics);
1500             }
1501         }
1502         fetch_generics(&flags, &self.ast.generics)
1503     }
1504 
1505     /// Adds an `impl<>` generic parameter.
1506     /// This can be used when the trait to be derived needs some extra generic parameters.
1507     ///
1508     /// # Example
1509     /// ```
1510     /// # use synstructure::*;
1511     /// let di: syn::DeriveInput = syn::parse_quote! {
1512     ///     enum A<T, U> {
1513     ///         B(T),
1514     ///         C(Option<U>),
1515     ///     }
1516     /// };
1517     /// let mut s = Structure::new(&di);
1518     /// let generic: syn::GenericParam = syn::parse_quote!(X: krate::AnotherTrait);
1519     ///
1520     /// assert_eq!(
1521     ///     s.add_impl_generic(generic)
1522     ///         .bound_impl(quote!(krate::Trait<X>),
1523     ///         quote!{
1524     ///                 fn a() {}
1525     ///         }
1526     ///     ).to_string(),
1527     ///     quote!{
1528     ///         #[allow(non_upper_case_globals)]
1529     ///         #[doc(hidden)]
1530     ///         const _DERIVE_krate_Trait_X_FOR_A: () = {
1531     ///             extern crate krate;
1532     ///             impl<T, U, X: krate::AnotherTrait> krate::Trait<X> for A<T, U>
1533     ///                 where T : krate :: Trait < X >,
1534     ///                       Option<U>: krate::Trait<X>,
1535     ///                       U: krate::Trait<X>
1536     ///             {
1537     ///                 fn a() {}
1538     ///             }
1539     ///         };
1540     ///     }.to_string()
1541     /// );
1542     /// ```
add_impl_generic(&mut self, param: GenericParam) -> &mut Self1543     pub fn add_impl_generic(&mut self, param: GenericParam) -> &mut Self {
1544         self.extra_impl.push(param);
1545         self
1546     }
1547 
1548     /// Add trait bounds for a trait with the given path for each type parmaeter
1549     /// referenced in the types of non-filtered fields.
1550     ///
1551     /// # Caveat
1552     ///
1553     /// If the method contains any macros in type position, all parameters will
1554     /// be considered bound. This is because we cannot determine which type
1555     /// parameters are bound by type macros.
add_trait_bounds( &self, bound: &TraitBound, where_clause: &mut Option<WhereClause>, mode: AddBounds, )1556     pub fn add_trait_bounds(
1557         &self,
1558         bound: &TraitBound,
1559         where_clause: &mut Option<WhereClause>,
1560         mode: AddBounds,
1561     ) {
1562         // If we have any explicit where predicates, make sure to add them first.
1563         if !self.extra_predicates.is_empty() {
1564             let clause = get_or_insert_with(&mut *where_clause, || WhereClause {
1565                 where_token: Default::default(),
1566                 predicates: punctuated::Punctuated::new(),
1567             });
1568             clause
1569                 .predicates
1570                 .extend(self.extra_predicates.iter().cloned());
1571         }
1572 
1573         let mut seen = HashSet::new();
1574         let mut pred = |ty: Type| {
1575             if !seen.contains(&ty) {
1576                 seen.insert(ty.clone());
1577 
1578                 // Add a predicate.
1579                 let clause = get_or_insert_with(&mut *where_clause, || WhereClause {
1580                     where_token: Default::default(),
1581                     predicates: punctuated::Punctuated::new(),
1582                 });
1583                 clause.predicates.push(WherePredicate::Type(PredicateType {
1584                     lifetimes: None,
1585                     bounded_ty: ty,
1586                     colon_token: Default::default(),
1587                     bounds: Some(punctuated::Pair::End(TypeParamBound::Trait(bound.clone())))
1588                         .into_iter()
1589                         .collect(),
1590                 }));
1591             }
1592         };
1593 
1594         for variant in &self.variants {
1595             for binding in &variant.bindings {
1596                 match mode {
1597                     AddBounds::Both | AddBounds::Fields => {
1598                         for &seen in &binding.seen_generics {
1599                             if seen {
1600                                 pred(binding.ast().ty.clone());
1601                                 break;
1602                             }
1603                         }
1604                     }
1605                     _ => {}
1606                 }
1607 
1608                 match mode {
1609                     AddBounds::Both | AddBounds::Generics => {
1610                         for param in binding.referenced_ty_params() {
1611                             pred(Type::Path(TypePath {
1612                                 qself: None,
1613                                 path: (*param).clone().into(),
1614                             }));
1615                         }
1616                     }
1617                     _ => {}
1618                 }
1619             }
1620         }
1621     }
1622 
1623     /// Configure whether to use `const _` instead of a generated const name in
1624     /// code generated by `gen_impl` and `bound_impl`.
1625     ///
1626     /// This syntax is only supported by rust 1.37, and later versions.
1627     ///
1628     /// Defaults to `false` for backwards compatibility reasons.
1629     ///
1630     /// # Example
1631     ///
1632     /// ```
1633     /// # use synstructure::*;
1634     /// let di: syn::DeriveInput = syn::parse_quote! {
1635     ///     struct MyStruct;
1636     /// };
1637     /// let mut s = Structure::new(&di);
1638     ///
1639     /// assert_eq!(
1640     ///     s.underscore_const(true)
1641     ///         .gen_impl(quote! { gen impl Trait for @Self { } })
1642     ///         .to_string(),
1643     ///     quote! {
1644     ///         const _: () = {
1645     ///             impl Trait for MyStruct { }
1646     ///         };
1647     ///     }
1648     ///     .to_string()
1649     /// );
1650     ///
1651     /// assert_eq!(
1652     ///     s.underscore_const(false)
1653     ///         .gen_impl(quote! { gen impl Trait for @Self { } })
1654     ///         .to_string(),
1655     ///     quote! {
1656     ///         #[allow(non_upper_case_globals)]
1657     ///         const _DERIVE_Trait_FOR_MyStruct: () = {
1658     ///             impl Trait for MyStruct { }
1659     ///         };
1660     ///     }
1661     ///     .to_string()
1662     /// );
1663     /// ```
underscore_const(&mut self, enabled: bool) -> &mut Self1664     pub fn underscore_const(&mut self, enabled: bool) -> &mut Self {
1665         self.underscore_const = enabled;
1666         self
1667     }
1668 
1669     /// > NOTE: This methods' features are superceded by `Structure::gen_impl`.
1670     ///
1671     /// Creates an `impl` block with the required generic type fields filled in
1672     /// to implement the trait `path`.
1673     ///
1674     /// This method also adds where clauses to the impl requiring that all
1675     /// referenced type parmaeters implement the trait `path`.
1676     ///
1677     /// # Hygiene and Paths
1678     ///
1679     /// This method wraps the impl block inside of a `const` (see the example
1680     /// below). In this scope, the first segment of the passed-in path is
1681     /// `extern crate`-ed in. If you don't want to generate that `extern crate`
1682     /// item, use a global path.
1683     ///
1684     /// This means that if you are implementing `my_crate::Trait`, you simply
1685     /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the
1686     /// entirety of the definition, you can refer to your crate as `my_crate`.
1687     ///
1688     /// # Caveat
1689     ///
1690     /// If the method contains any macros in type position, all parameters will
1691     /// be considered bound. This is because we cannot determine which type
1692     /// parameters are bound by type macros.
1693     ///
1694     /// # Panics
1695     ///
1696     /// Panics if the path string parameter is not a valid `TraitBound`.
1697     ///
1698     /// # Example
1699     /// ```
1700     /// # use synstructure::*;
1701     /// let di: syn::DeriveInput = syn::parse_quote! {
1702     ///     enum A<T, U> {
1703     ///         B(T),
1704     ///         C(Option<U>),
1705     ///     }
1706     /// };
1707     /// let mut s = Structure::new(&di);
1708     ///
1709     /// s.filter_variants(|v| v.ast().ident != "B");
1710     ///
1711     /// assert_eq!(
1712     ///     s.bound_impl(quote!(krate::Trait), quote!{
1713     ///         fn a() {}
1714     ///     }).to_string(),
1715     ///     quote!{
1716     ///         #[allow(non_upper_case_globals)]
1717     ///         #[doc(hidden)]
1718     ///         const _DERIVE_krate_Trait_FOR_A: () = {
1719     ///             extern crate krate;
1720     ///             impl<T, U> krate::Trait for A<T, U>
1721     ///                 where Option<U>: krate::Trait,
1722     ///                       U: krate::Trait
1723     ///             {
1724     ///                 fn a() {}
1725     ///             }
1726     ///         };
1727     ///     }.to_string()
1728     /// );
1729     /// ```
bound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream1730     pub fn bound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream {
1731         self.impl_internal(
1732             path.into_token_stream(),
1733             body.into_token_stream(),
1734             quote!(),
1735             None,
1736         )
1737     }
1738 
1739     /// > NOTE: This methods' features are superceded by `Structure::gen_impl`.
1740     ///
1741     /// Creates an `impl` block with the required generic type fields filled in
1742     /// to implement the unsafe trait `path`.
1743     ///
1744     /// This method also adds where clauses to the impl requiring that all
1745     /// referenced type parmaeters implement the trait `path`.
1746     ///
1747     /// # Hygiene and Paths
1748     ///
1749     /// This method wraps the impl block inside of a `const` (see the example
1750     /// below). In this scope, the first segment of the passed-in path is
1751     /// `extern crate`-ed in. If you don't want to generate that `extern crate`
1752     /// item, use a global path.
1753     ///
1754     /// This means that if you are implementing `my_crate::Trait`, you simply
1755     /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the
1756     /// entirety of the definition, you can refer to your crate as `my_crate`.
1757     ///
1758     /// # Caveat
1759     ///
1760     /// If the method contains any macros in type position, all parameters will
1761     /// be considered bound. This is because we cannot determine which type
1762     /// parameters are bound by type macros.
1763     ///
1764     /// # Panics
1765     ///
1766     /// Panics if the path string parameter is not a valid `TraitBound`.
1767     ///
1768     /// # Example
1769     /// ```
1770     /// # use synstructure::*;
1771     /// let di: syn::DeriveInput = syn::parse_quote! {
1772     ///     enum A<T, U> {
1773     ///         B(T),
1774     ///         C(Option<U>),
1775     ///     }
1776     /// };
1777     /// let mut s = Structure::new(&di);
1778     ///
1779     /// s.filter_variants(|v| v.ast().ident != "B");
1780     ///
1781     /// assert_eq!(
1782     ///     s.unsafe_bound_impl(quote!(krate::Trait), quote!{
1783     ///         fn a() {}
1784     ///     }).to_string(),
1785     ///     quote!{
1786     ///         #[allow(non_upper_case_globals)]
1787     ///         #[doc(hidden)]
1788     ///         const _DERIVE_krate_Trait_FOR_A: () = {
1789     ///             extern crate krate;
1790     ///             unsafe impl<T, U> krate::Trait for A<T, U>
1791     ///                 where Option<U>: krate::Trait,
1792     ///                       U: krate::Trait
1793     ///             {
1794     ///                 fn a() {}
1795     ///             }
1796     ///         };
1797     ///     }.to_string()
1798     /// );
1799     /// ```
unsafe_bound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream1800     pub fn unsafe_bound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream {
1801         self.impl_internal(
1802             path.into_token_stream(),
1803             body.into_token_stream(),
1804             quote!(unsafe),
1805             None,
1806         )
1807     }
1808 
1809     /// > NOTE: This methods' features are superceded by `Structure::gen_impl`.
1810     ///
1811     /// Creates an `impl` block with the required generic type fields filled in
1812     /// to implement the trait `path`.
1813     ///
1814     /// This method will not add any where clauses to the impl.
1815     ///
1816     /// # Hygiene and Paths
1817     ///
1818     /// This method wraps the impl block inside of a `const` (see the example
1819     /// below). In this scope, the first segment of the passed-in path is
1820     /// `extern crate`-ed in. If you don't want to generate that `extern crate`
1821     /// item, use a global path.
1822     ///
1823     /// This means that if you are implementing `my_crate::Trait`, you simply
1824     /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the
1825     /// entirety of the definition, you can refer to your crate as `my_crate`.
1826     ///
1827     /// # Panics
1828     ///
1829     /// Panics if the path string parameter is not a valid `TraitBound`.
1830     ///
1831     /// # Example
1832     /// ```
1833     /// # use synstructure::*;
1834     /// let di: syn::DeriveInput = syn::parse_quote! {
1835     ///     enum A<T, U> {
1836     ///         B(T),
1837     ///         C(Option<U>),
1838     ///     }
1839     /// };
1840     /// let mut s = Structure::new(&di);
1841     ///
1842     /// s.filter_variants(|v| v.ast().ident != "B");
1843     ///
1844     /// assert_eq!(
1845     ///     s.unbound_impl(quote!(krate::Trait), quote!{
1846     ///         fn a() {}
1847     ///     }).to_string(),
1848     ///     quote!{
1849     ///         #[allow(non_upper_case_globals)]
1850     ///         #[doc(hidden)]
1851     ///         const _DERIVE_krate_Trait_FOR_A: () = {
1852     ///             extern crate krate;
1853     ///             impl<T, U> krate::Trait for A<T, U> {
1854     ///                 fn a() {}
1855     ///             }
1856     ///         };
1857     ///     }.to_string()
1858     /// );
1859     /// ```
unbound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream1860     pub fn unbound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream {
1861         self.impl_internal(
1862             path.into_token_stream(),
1863             body.into_token_stream(),
1864             quote!(),
1865             Some(AddBounds::None),
1866         )
1867     }
1868 
1869     /// > NOTE: This methods' features are superceded by `Structure::gen_impl`.
1870     ///
1871     /// Creates an `impl` block with the required generic type fields filled in
1872     /// to implement the unsafe trait `path`.
1873     ///
1874     /// This method will not add any where clauses to the impl.
1875     ///
1876     /// # Hygiene and Paths
1877     ///
1878     /// This method wraps the impl block inside of a `const` (see the example
1879     /// below). In this scope, the first segment of the passed-in path is
1880     /// `extern crate`-ed in. If you don't want to generate that `extern crate`
1881     /// item, use a global path.
1882     ///
1883     /// This means that if you are implementing `my_crate::Trait`, you simply
1884     /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the
1885     /// entirety of the definition, you can refer to your crate as `my_crate`.
1886     ///
1887     /// # Panics
1888     ///
1889     /// Panics if the path string parameter is not a valid `TraitBound`.
1890     ///
1891     /// # Example
1892     /// ```
1893     /// # use synstructure::*;
1894     /// let di: syn::DeriveInput = syn::parse_quote! {
1895     ///     enum A<T, U> {
1896     ///         B(T),
1897     ///         C(Option<U>),
1898     ///     }
1899     /// };
1900     /// let mut s = Structure::new(&di);
1901     ///
1902     /// s.filter_variants(|v| v.ast().ident != "B");
1903     ///
1904     /// assert_eq!(
1905     ///     s.unsafe_unbound_impl(quote!(krate::Trait), quote!{
1906     ///         fn a() {}
1907     ///     }).to_string(),
1908     ///     quote!{
1909     ///         #[allow(non_upper_case_globals)]
1910     ///         #[doc(hidden)]
1911     ///         const _DERIVE_krate_Trait_FOR_A: () = {
1912     ///             extern crate krate;
1913     ///             unsafe impl<T, U> krate::Trait for A<T, U> {
1914     ///                 fn a() {}
1915     ///             }
1916     ///         };
1917     ///     }.to_string()
1918     /// );
1919     /// ```
1920     #[deprecated]
unsafe_unbound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream1921     pub fn unsafe_unbound_impl<P: ToTokens, B: ToTokens>(&self, path: P, body: B) -> TokenStream {
1922         self.impl_internal(
1923             path.into_token_stream(),
1924             body.into_token_stream(),
1925             quote!(unsafe),
1926             Some(AddBounds::None),
1927         )
1928     }
1929 
impl_internal( &self, path: TokenStream, body: TokenStream, safety: TokenStream, mode: Option<AddBounds>, ) -> TokenStream1930     fn impl_internal(
1931         &self,
1932         path: TokenStream,
1933         body: TokenStream,
1934         safety: TokenStream,
1935         mode: Option<AddBounds>,
1936     ) -> TokenStream {
1937         let mode = mode.unwrap_or(self.add_bounds);
1938         let name = &self.ast.ident;
1939         let mut gen_clone = self.ast.generics.clone();
1940         gen_clone.params.extend(self.extra_impl.clone().into_iter());
1941         let (impl_generics, _, _) = gen_clone.split_for_impl();
1942         let (_, ty_generics, where_clause) = self.ast.generics.split_for_impl();
1943 
1944         let bound = syn::parse2::<TraitBound>(path)
1945             .expect("`path` argument must be a valid rust trait bound");
1946 
1947         let mut where_clause = where_clause.cloned();
1948         self.add_trait_bounds(&bound, &mut where_clause, mode);
1949 
1950         // This function is smart. If a global path is passed, no extern crate
1951         // statement will be generated, however, a relative path will cause the
1952         // crate which it is relative to to be imported within the current
1953         // scope.
1954         let mut extern_crate = quote!();
1955         if bound.path.leading_colon.is_none() {
1956             if let Some(seg) = bound.path.segments.first() {
1957                 let seg = &seg.ident;
1958                 extern_crate = quote! { extern crate #seg; };
1959             }
1960         }
1961 
1962         let generated = quote! {
1963             #extern_crate
1964             #safety impl #impl_generics #bound for #name #ty_generics #where_clause {
1965                 #body
1966             }
1967         };
1968 
1969         if self.underscore_const {
1970             quote! {
1971                 const _: () = { #generated };
1972             }
1973         } else {
1974             let dummy_const: Ident = sanitize_ident(&format!(
1975                 "_DERIVE_{}_FOR_{}",
1976                 (&bound).into_token_stream(),
1977                 name.into_token_stream(),
1978             ));
1979             quote! {
1980                 #[allow(non_upper_case_globals)]
1981                 #[doc(hidden)]
1982                 const #dummy_const: () = {
1983                     #generated
1984                 };
1985             }
1986         }
1987     }
1988 
1989     /// Generate an impl block for the given struct. This impl block will
1990     /// automatically use hygiene tricks to avoid polluting the caller's
1991     /// namespace, and will automatically add trait bounds for generic type
1992     /// parameters.
1993     ///
1994     /// # Syntax
1995     ///
1996     /// This function accepts its arguments as a `TokenStream`. The recommended way
1997     /// to call this function is passing the result of invoking the `quote!`
1998     /// macro to it.
1999     ///
2000     /// ```ignore
2001     /// s.gen_impl(quote! {
2002     ///     // You can write any items which you want to import into scope here.
2003     ///     // For example, you may want to include an `extern crate` for the
2004     ///     // crate which implements your trait. These items will only be
2005     ///     // visible to the code you generate, and won't be exposed to the
2006     ///     // consuming crate
2007     ///     extern crate krate;
2008     ///
2009     ///     // You can also add `use` statements here to bring types or traits
2010     ///     // into scope.
2011     ///     //
2012     ///     // WARNING: Try not to use common names here, because the stable
2013     ///     // version of syn does not support hygiene and you could accidentally
2014     ///     // shadow types from the caller crate.
2015     ///     use krate::Trait as MyTrait;
2016     ///
2017     ///     // The actual impl block is a `gen impl` or `gen unsafe impl` block.
2018     ///     // You can use `@Self` to refer to the structure's type.
2019     ///     gen impl MyTrait for @Self {
2020     ///         fn f(&self) { ... }
2021     ///     }
2022     /// })
2023     /// ```
2024     ///
2025     /// The most common usage of this trait involves loading the crate the
2026     /// target trait comes from with `extern crate`, and then invoking a `gen
2027     /// impl` block.
2028     ///
2029     /// # Hygiene
2030     ///
2031     /// This method tries to handle hygiene intelligenly for both stable and
2032     /// unstable proc-macro implementations, however there are visible
2033     /// differences.
2034     ///
2035     /// The output of every `gen_impl` function is wrapped in a dummy `const`
2036     /// value, to ensure that it is given its own scope, and any values brought
2037     /// into scope are not leaked to the calling crate.
2038     ///
2039     /// By default, the above invocation may generate an output like the
2040     /// following:
2041     ///
2042     /// ```ignore
2043     /// const _DERIVE_krate_Trait_FOR_Struct: () = {
2044     ///     extern crate krate;
2045     ///     use krate::Trait as MyTrait;
2046     ///     impl<T> MyTrait for Struct<T> where T: MyTrait {
2047     ///         fn f(&self) { ... }
2048     ///     }
2049     /// };
2050     /// ```
2051     ///
2052     /// The `Structure` may also be confired with the [`underscore_const`] method
2053     /// to generate `const _` instead.
2054     ///
2055     /// ```ignore
2056     /// const _: () = {
2057     ///     extern crate krate;
2058     ///     use krate::Trait as MyTrait;
2059     ///     impl<T> MyTrait for Struct<T> where T: MyTrait {
2060     ///         fn f(&self) { ... }
2061     ///     }
2062     /// };
2063     /// ```
2064     ///
2065     /// ### Using the `std` crate
2066     ///
2067     /// If you are using `quote!()` to implement your trait, with the
2068     /// `proc-macro2/nightly` feature, `std` isn't considered to be in scope for
2069     /// your macro. This means that if you use types from `std` in your
2070     /// procedural macro, you'll want to explicitly load it with an `extern
2071     /// crate std;`.
2072     ///
2073     /// ### Absolute paths
2074     ///
2075     /// You should generally avoid using absolute paths in your generated code,
2076     /// as they will resolve very differently when using the stable and nightly
2077     /// versions of `proc-macro2`. Instead, load the crates you need to use
2078     /// explictly with `extern crate` and
2079     ///
2080     /// # Trait Bounds
2081     ///
2082     /// This method will automatically add trait bounds for any type parameters
2083     /// which are referenced within the types of non-ignored fields.
2084     ///
2085     /// Additional type parameters may be added with the generics syntax after
2086     /// the `impl` keyword.
2087     ///
2088     /// ### Type Macro Caveat
2089     ///
2090     /// If the method contains any macros in type position, all parameters will
2091     /// be considered bound. This is because we cannot determine which type
2092     /// parameters are bound by type macros.
2093     ///
2094     /// # Errors
2095     ///
2096     /// This function will generate a `compile_error!` if additional type
2097     /// parameters added by `impl<..>` conflict with generic type parameters on
2098     /// the original struct.
2099     ///
2100     /// # Panics
2101     ///
2102     /// This function will panic if the input `TokenStream` is not well-formed.
2103     ///
2104     /// # Example Usage
2105     ///
2106     /// ```
2107     /// # use synstructure::*;
2108     /// let di: syn::DeriveInput = syn::parse_quote! {
2109     ///     enum A<T, U> {
2110     ///         B(T),
2111     ///         C(Option<U>),
2112     ///     }
2113     /// };
2114     /// let mut s = Structure::new(&di);
2115     ///
2116     /// s.filter_variants(|v| v.ast().ident != "B");
2117     ///
2118     /// assert_eq!(
2119     ///     s.gen_impl(quote! {
2120     ///         extern crate krate;
2121     ///         gen impl krate::Trait for @Self {
2122     ///             fn a() {}
2123     ///         }
2124     ///     }).to_string(),
2125     ///     quote!{
2126     ///         #[allow(non_upper_case_globals)]
2127     ///         const _DERIVE_krate_Trait_FOR_A: () = {
2128     ///             extern crate krate;
2129     ///             impl<T, U> krate::Trait for A<T, U>
2130     ///             where
2131     ///                 Option<U>: krate::Trait,
2132     ///                 U: krate::Trait
2133     ///             {
2134     ///                 fn a() {}
2135     ///             }
2136     ///         };
2137     ///     }.to_string()
2138     /// );
2139     ///
2140     /// // NOTE: You can also add extra generics after the impl
2141     /// assert_eq!(
2142     ///     s.gen_impl(quote! {
2143     ///         extern crate krate;
2144     ///         gen impl<X: krate::OtherTrait> krate::Trait<X> for @Self
2145     ///         where
2146     ///             X: Send + Sync,
2147     ///         {
2148     ///             fn a() {}
2149     ///         }
2150     ///     }).to_string(),
2151     ///     quote!{
2152     ///         #[allow(non_upper_case_globals)]
2153     ///         const _DERIVE_krate_Trait_X_FOR_A: () = {
2154     ///             extern crate krate;
2155     ///             impl<X: krate::OtherTrait, T, U> krate::Trait<X> for A<T, U>
2156     ///             where
2157     ///                 X: Send + Sync,
2158     ///                 Option<U>: krate::Trait<X>,
2159     ///                 U: krate::Trait<X>
2160     ///             {
2161     ///                 fn a() {}
2162     ///             }
2163     ///         };
2164     ///     }.to_string()
2165     /// );
2166     ///
2167     /// // NOTE: you can generate multiple traits with a single call
2168     /// assert_eq!(
2169     ///     s.gen_impl(quote! {
2170     ///         extern crate krate;
2171     ///
2172     ///         gen impl krate::Trait for @Self {
2173     ///             fn a() {}
2174     ///         }
2175     ///
2176     ///         gen impl krate::OtherTrait for @Self {
2177     ///             fn b() {}
2178     ///         }
2179     ///     }).to_string(),
2180     ///     quote!{
2181     ///         #[allow(non_upper_case_globals)]
2182     ///         const _DERIVE_krate_Trait_FOR_A: () = {
2183     ///             extern crate krate;
2184     ///             impl<T, U> krate::Trait for A<T, U>
2185     ///             where
2186     ///                 Option<U>: krate::Trait,
2187     ///                 U: krate::Trait
2188     ///             {
2189     ///                 fn a() {}
2190     ///             }
2191     ///
2192     ///             impl<T, U> krate::OtherTrait for A<T, U>
2193     ///             where
2194     ///                 Option<U>: krate::OtherTrait,
2195     ///                 U: krate::OtherTrait
2196     ///             {
2197     ///                 fn b() {}
2198     ///             }
2199     ///         };
2200     ///     }.to_string()
2201     /// );
2202     /// ```
2203     ///
2204     /// Use `add_bounds` to change which bounds are generated.
gen_impl(&self, cfg: TokenStream) -> TokenStream2205     pub fn gen_impl(&self, cfg: TokenStream) -> TokenStream {
2206         Parser::parse2(
2207             |input: ParseStream<'_>| -> Result<TokenStream> { self.gen_impl_parse(input, true) },
2208             cfg,
2209         )
2210         .expect("Failed to parse gen_impl")
2211     }
2212 
gen_impl_parse(&self, input: ParseStream<'_>, wrap: bool) -> Result<TokenStream>2213     fn gen_impl_parse(&self, input: ParseStream<'_>, wrap: bool) -> Result<TokenStream> {
2214         fn parse_prefix(input: ParseStream<'_>) -> Result<Option<Token![unsafe]>> {
2215             if input.parse::<Ident>()? != "gen" {
2216                 return Err(input.error("Expected keyword `gen`"));
2217             }
2218             let safety = input.parse::<Option<Token![unsafe]>>()?;
2219             let _ = input.parse::<Token![impl]>()?;
2220             Ok(safety)
2221         }
2222 
2223         let mut before = vec![];
2224         loop {
2225             if parse_prefix(&input.fork()).is_ok() {
2226                 break;
2227             }
2228             before.push(input.parse::<TokenTree>()?);
2229         }
2230 
2231         // Parse the prefix "for real"
2232         let safety = parse_prefix(input)?;
2233 
2234         // optional `<>`
2235         let mut generics = input.parse::<Generics>()?;
2236 
2237         // @bound
2238         let bound = input.parse::<TraitBound>()?;
2239 
2240         // `for @Self`
2241         let _ = input.parse::<Token![for]>()?;
2242         let _ = input.parse::<Token![@]>()?;
2243         let _ = input.parse::<Token![Self]>()?;
2244 
2245         // optional `where ...`
2246         generics.where_clause = input.parse()?;
2247 
2248         // Body of the impl
2249         let body;
2250         braced!(body in input);
2251         let body = body.parse::<TokenStream>()?;
2252 
2253         // Try to parse the next entry in sequence. If this fails, we'll fall
2254         // back to just parsing the entire rest of the TokenStream.
2255         let maybe_next_impl = self.gen_impl_parse(&input.fork(), false);
2256 
2257         // Eat tokens to the end. Whether or not our speculative nested parse
2258         // succeeded, we're going to want to consume the rest of our input.
2259         let mut after = input.parse::<TokenStream>()?;
2260         if let Ok(stream) = maybe_next_impl {
2261             after = stream;
2262         }
2263         assert!(input.is_empty(), "Should've consumed the rest of our input");
2264 
2265         /* Codegen Logic */
2266         let name = &self.ast.ident;
2267 
2268         // Add the generics from the original struct in, and then add any
2269         // additional trait bounds which we need on the type.
2270         if let Err(err) = merge_generics(&mut generics, &self.ast.generics) {
2271             // Report the merge error as a `compile_error!`, as it may be
2272             // triggerable by an end-user.
2273             return Ok(err.to_compile_error());
2274         }
2275 
2276         self.add_trait_bounds(&bound, &mut generics.where_clause, self.add_bounds);
2277         let (impl_generics, _, where_clause) = generics.split_for_impl();
2278         let (_, ty_generics, _) = self.ast.generics.split_for_impl();
2279 
2280         let generated = quote! {
2281             #(#before)*
2282             #safety impl #impl_generics #bound for #name #ty_generics #where_clause {
2283                 #body
2284             }
2285             #after
2286         };
2287 
2288         if wrap {
2289             if self.underscore_const {
2290                 Ok(quote! {
2291                     const _: () = { #generated };
2292                 })
2293             } else {
2294                 let dummy_const: Ident = sanitize_ident(&format!(
2295                     "_DERIVE_{}_FOR_{}",
2296                     (&bound).into_token_stream(),
2297                     name.into_token_stream(),
2298                 ));
2299                 Ok(quote! {
2300                     #[allow(non_upper_case_globals)]
2301                     const #dummy_const: () = {
2302                         #generated
2303                     };
2304                 })
2305             }
2306         } else {
2307             Ok(generated)
2308         }
2309     }
2310 }
2311 
2312 /// Dumps an unpretty version of a tokenstream. Takes any type which implements
2313 /// `Display`.
2314 ///
2315 /// This is mostly useful for visualizing the output of a procedural macro, as
2316 /// it makes it marginally more readable. It is used in the implementation of
2317 /// `test_derive!` to unprettily print the output.
2318 ///
2319 /// # Stability
2320 ///
2321 /// The stability of the output of this function is not guaranteed. Do not
2322 /// assert that the output of this function does not change between minor
2323 /// versions.
2324 ///
2325 /// # Example
2326 ///
2327 /// ```
2328 /// # use quote::quote;
2329 /// assert_eq!(
2330 ///     synstructure::unpretty_print(quote! {
2331 ///         #[allow(non_upper_case_globals)]
2332 ///         const _DERIVE_krate_Trait_FOR_A: () = {
2333 ///             extern crate krate;
2334 ///             impl<T, U> krate::Trait for A<T, U>
2335 ///             where
2336 ///                 Option<U>: krate::Trait,
2337 ///                 U: krate::Trait
2338 ///             {
2339 ///                 fn a() {}
2340 ///             }
2341 ///         };
2342 ///     }),
2343 ///     "# [
2344 ///     allow (
2345 ///         non_upper_case_globals )
2346 ///     ]
2347 /// const _DERIVE_krate_Trait_FOR_A : (
2348 ///     )
2349 /// = {
2350 ///     extern crate krate ;
2351 ///     impl < T , U > krate :: Trait for A < T , U > where Option < U > : krate :: Trait , U : krate :: Trait {
2352 ///         fn a (
2353 ///             )
2354 ///         {
2355 ///             }
2356 ///         }
2357 ///     }
2358 /// ;
2359 /// "
2360 /// )
2361 /// ```
unpretty_print<T: std::fmt::Display>(ts: T) -> String2362 pub fn unpretty_print<T: std::fmt::Display>(ts: T) -> String {
2363     let mut res = String::new();
2364 
2365     let raw_s = ts.to_string();
2366     let mut s = &raw_s[..];
2367     let mut indent = 0;
2368     while let Some(i) = s.find(&['(', '{', '[', ')', '}', ']', ';'][..]) {
2369         match &s[i..=i] {
2370             "(" | "{" | "[" => indent += 1,
2371             ")" | "}" | "]" => indent -= 1,
2372             _ => {}
2373         }
2374         res.push_str(&s[..=i]);
2375         res.push('\n');
2376         for _ in 0..indent {
2377             res.push_str("    ");
2378         }
2379         s = trim_start_matches(&s[i + 1..], ' ');
2380     }
2381     res.push_str(s);
2382     res
2383 }
2384 
2385 /// `trim_left_matches` has been deprecated in favor of `trim_start_matches`.
2386 /// This helper silences the warning, as we need to continue using
2387 /// `trim_left_matches` for rust 1.15 support.
2388 #[allow(deprecated)]
trim_start_matches(s: &str, c: char) -> &str2389 fn trim_start_matches(s: &str, c: char) -> &str {
2390     s.trim_left_matches(c)
2391 }
2392 
2393 /// Helper trait describing values which may be returned by macro implementation
2394 /// methods used by this crate's macros.
2395 pub trait MacroResult {
2396     /// Convert this result into a `Result` for further processing / validation.
into_result(self) -> Result<TokenStream>2397     fn into_result(self) -> Result<TokenStream>;
2398 
2399     /// Convert this result into a `proc_macro::TokenStream`, ready to return
2400     /// from a native `proc_macro` implementation.
2401     ///
2402     /// If `into_result()` would return an `Err`, this method should instead
2403     /// generate a `compile_error!` invocation to nicely report the error.
2404     ///
2405     /// *This method is available if `synstructure` is built with the
2406     /// `"proc-macro"` feature.*
2407     #[cfg(all(
2408         not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
2409         feature = "proc-macro"
2410     ))]
into_stream(self) -> proc_macro::TokenStream where Self: Sized,2411     fn into_stream(self) -> proc_macro::TokenStream
2412     where
2413         Self: Sized,
2414     {
2415         match self.into_result() {
2416             Ok(ts) => ts.into(),
2417             Err(err) => err.to_compile_error().into(),
2418         }
2419     }
2420 }
2421 
2422 #[cfg(all(
2423     not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
2424     feature = "proc-macro"
2425 ))]
2426 impl MacroResult for proc_macro::TokenStream {
into_result(self) -> Result<TokenStream>2427     fn into_result(self) -> Result<TokenStream> {
2428         Ok(self.into())
2429     }
2430 
into_stream(self) -> proc_macro::TokenStream2431     fn into_stream(self) -> proc_macro::TokenStream {
2432         self
2433     }
2434 }
2435 
2436 impl MacroResult for TokenStream {
into_result(self) -> Result<TokenStream>2437     fn into_result(self) -> Result<TokenStream> {
2438         Ok(self)
2439     }
2440 }
2441 
2442 impl<T: MacroResult> MacroResult for Result<T> {
into_result(self) -> Result<TokenStream>2443     fn into_result(self) -> Result<TokenStream> {
2444         match self {
2445             Ok(v) => v.into_result(),
2446             Err(err) => Err(err),
2447         }
2448     }
2449 }
2450 
2451 #[cfg(test)]
2452 mod tests {
2453     use super::*;
2454 
2455     // Regression test for #48
2456     #[test]
test_each_enum()2457     fn test_each_enum() {
2458         let di: syn::DeriveInput = syn::parse_quote! {
2459          enum A {
2460              Foo(usize, bool),
2461              Bar(bool, usize),
2462              Baz(usize, bool, usize),
2463              Quux(bool, usize, bool)
2464          }
2465         };
2466         let mut s = Structure::new(&di);
2467 
2468         s.filter(|bi| bi.ast().ty.to_token_stream().to_string() == "bool");
2469 
2470         assert_eq!(
2471             s.each(|bi| quote!(do_something(#bi))).to_string(),
2472             quote! {
2473                 A::Foo(_, ref __binding_1,) => { { do_something(__binding_1) } }
2474                 A::Bar(ref __binding_0, ..) => { { do_something(__binding_0) } }
2475                 A::Baz(_, ref __binding_1, ..) => { { do_something(__binding_1) } }
2476                 A::Quux(ref __binding_0, _, ref __binding_2,) => {
2477                     {
2478                         do_something(__binding_0)
2479                     }
2480                     {
2481                         do_something(__binding_2)
2482                     }
2483                 }
2484             }
2485             .to_string()
2486         );
2487     }
2488 }
2489