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