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(<.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 | |