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