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