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