synstructure/
lib.rs

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