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