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