1 | use proc_macro2; |
2 | |
3 | use ast; |
4 | use attr; |
5 | use bound; |
6 | use syn; |
7 | |
8 | /// Make generic with all the generics in the input, plus a bound `T: <trait_path>` for each |
9 | /// generic field type that will be shown. |
10 | pub fn build_impl_generics<F, G, H>( |
11 | item: &ast::Input, |
12 | trait_path: &syn::Path, |
13 | needs_debug_bound: F, |
14 | field_bound: G, |
15 | input_bound: H, |
16 | ) -> syn::Generics |
17 | where |
18 | F: Fn(&attr::Field) -> bool, |
19 | G: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>, |
20 | H: Fn(&attr::Input) -> Option<&[syn::WherePredicate]>, |
21 | { |
22 | let generics: Generics = bound::without_defaults(item.generics); |
23 | let generics: Generics = bound::with_where_predicates_from_fields(item, &generics, from_field:field_bound); |
24 | |
25 | match input_bound(&item.attrs) { |
26 | Some(predicates: &[WherePredicate]) => bound::with_where_predicates(&generics, predicates), |
27 | None => bound::with_bound(item, &generics, filter:needs_debug_bound, bound:trait_path), |
28 | } |
29 | } |
30 | |
31 | /// Construct a name for the inner type parameter that can't collide with any |
32 | /// type parameters of the item. This is achieved by starting with a base and |
33 | /// then concatenating the names of all other type parameters. |
34 | pub fn hygienic_type_parameter(item: &ast::Input, base: &str) -> syn::Ident { |
35 | let mut typaram: String = String::with_capacity(150); |
36 | typaram.push_str(string:base); |
37 | let typaram: String = item.generics.type_params().fold(init:typaram, |mut acc: String, ty: &TypeParam| { |
38 | acc.push_str(&format!(" {}" , &ty.ident)); |
39 | acc |
40 | }); |
41 | |
42 | syn::Ident::new(&typaram, proc_macro2::Span::call_site()) |
43 | } |
44 | |