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