• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Traits and types used for tracking the usage of generic parameters through a proc-macro input.
2 //!
3 //! When generating trait impls, libraries often want to automatically figure out which type parameters
4 //! are used in which fields, and then emit bounds that will produce the most permissive compilable
5 //! code.
6 //!
7 //! # Usage
8 //!
9 //! ## Example 1: Filtering
10 //! This example accepts a proc-macro input, then finds all lifetimes and type parameters used
11 //! by private fields.
12 //!
13 //! ```rust
14 //! # extern crate darling_core;
15 //! # extern crate syn;
16 //! #
17 //! # // in real-world usage, import from `darling`
18 //! # use darling_core::usage::{self, CollectLifetimes, CollectTypeParams, GenericsExt, Purpose};
19 //! # use syn::{Data, DeriveInput, GenericParam, Generics, Visibility};
20 //! #
21 //! # #[allow(dead_code)]
22 //! fn process(input: &DeriveInput) -> Generics {
23 //!     let type_params = input.generics.declared_type_params();
24 //!     let lifetimes = input.generics.declared_lifetimes();
25 //!
26 //!     let mut ret_generics = input.generics.clone();
27 //!
28 //!     if let Data::Struct(ref body) = input.data {
29 //!         let internal_fields = body
30 //!             .fields
31 //!             .iter()
32 //!             .filter(|field| field.vis == Visibility::Inherited)
33 //!             .collect::<Vec<_>>();
34 //!
35 //!         let int_type_params = internal_fields
36 //!             .collect_type_params(&Purpose::BoundImpl.into(), &type_params);
37 //!
38 //!         // We could reuse the vec from above, but here we'll instead
39 //!         // directly consume the chained iterator.
40 //!         let int_lifetimes = body
41 //!             .fields
42 //!             .iter()
43 //!             .filter(|field| field.vis == Visibility::Inherited)
44 //!             .collect_lifetimes(&Purpose::BoundImpl.into(), &lifetimes);
45 //!
46 //!
47 //!         ret_generics.params = ret_generics
48 //!             .params
49 //!             .into_iter()
50 //!             .filter(|gp| {
51 //!                 match *gp {
52 //!                     GenericParam::Type(ref ty) => int_type_params.contains(&ty.ident),
53 //!                     GenericParam::Lifetime(ref lt) => int_lifetimes.contains(&lt.lifetime),
54 //!                     _ => true,
55 //!                 }
56 //!             })
57 //!             .collect();
58 //!     }
59 //!
60 //!     ret_generics
61 //! }
62 //!
63 //! # fn main() {}
64 //! ```
65 //!
66 //! ## Example 2: Integrating with `FromDeriveInput`
67 //! It is possible to use `darling`'s magic fields feature in tandem with the `usage` feature set.
68 //! While there is no custom derive for `UsesTypeParams` or `UsesLifetimes`, there are macros to
69 //! generate impls.
70 //!
71 //! ```rust,ignore
72 //! #![allow(dead_code)]
73 //!
74 //! #[derive(FromField)]
75 //! #[darling(attributes(speak))]
76 //! struct SpeakerField {
77 //!     ident: Option<syn::Ident>,
78 //!     ty: syn::Type,
79 //!     #[darling(default)]
80 //!     volume: Option<u32>,
81 //! }
82 //!
83 //! uses_type_params!(SpeakerField, ty);
84 //! uses_lifetimes!(SpeakerField, ty);
85 //!
86 //! #[derive(FromDeriveInput)]
87 //! struct SpeakerOptions {
88 //!     generics: syn::Generics,
89 //!     data: darling::ast::Data<darling::util::Ignored, SpeakerField>,
90 //! }
91 //! ```
92 //!
93 //! At this point, you are able to call `uses_type_params` on `SpeakerOptions.data`, or any filtered
94 //! view of it. `darling` internally uses this in conjunction with the `skip` meta-item to determine
95 //! which type parameters don't require the `FromMeta` bound in generated impls.
96 //!
97 //! **Note:** If you are performing operations referencing generic params in meta-items parsed by `darling`,
98 //! you should determine if those impact the emitted code and wire up `UsesTypeParams` accordingly for
99 //! your field/variant.
100 
101 mod generics_ext;
102 mod ident_set;
103 mod lifetimes;
104 mod options;
105 mod type_params;
106 
107 pub use self::generics_ext::GenericsExt;
108 pub use self::ident_set::{IdentRefSet, IdentSet};
109 pub use self::lifetimes::{CollectLifetimes, LifetimeRefSet, LifetimeSet, UsesLifetimes};
110 pub use self::options::{Options, Purpose};
111 pub use self::type_params::{CollectTypeParams, UsesTypeParams};
112