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