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