]>
Commit | Line | Data |
---|---|---|
532ac7d7 XL |
1 | use proc_macro2::{self, Ident}; |
2 | use quote::quote; | |
dfeec247 | 3 | use syn::{self, parse_quote, Meta, NestedMeta}; |
532ac7d7 XL |
4 | |
5 | struct Attributes { | |
6 | ignore: bool, | |
7 | project: Option<Ident>, | |
8 | } | |
9 | ||
10 | fn parse_attributes(field: &syn::Field) -> Attributes { | |
dfeec247 | 11 | let mut attrs = Attributes { ignore: false, project: None }; |
532ac7d7 XL |
12 | for attr in &field.attrs { |
13 | if let Ok(meta) = attr.parse_meta() { | |
e74abb32 | 14 | if !meta.path().is_ident("stable_hasher") { |
532ac7d7 XL |
15 | continue; |
16 | } | |
17 | let mut any_attr = false; | |
18 | if let Meta::List(list) = meta { | |
19 | for nested in list.nested.iter() { | |
20 | if let NestedMeta::Meta(meta) = nested { | |
e74abb32 | 21 | if meta.path().is_ident("ignore") { |
532ac7d7 XL |
22 | attrs.ignore = true; |
23 | any_attr = true; | |
24 | } | |
e74abb32 | 25 | if meta.path().is_ident("project") { |
532ac7d7 XL |
26 | if let Meta::List(list) = meta { |
27 | if let Some(nested) = list.nested.iter().next() { | |
28 | if let NestedMeta::Meta(meta) = nested { | |
e74abb32 | 29 | attrs.project = meta.path().get_ident().cloned(); |
532ac7d7 XL |
30 | any_attr = true; |
31 | } | |
32 | } | |
33 | } | |
34 | } | |
35 | } | |
36 | } | |
37 | } | |
38 | if !any_attr { | |
39 | panic!("error parsing stable_hasher"); | |
40 | } | |
41 | } | |
42 | } | |
43 | attrs | |
44 | } | |
45 | ||
60c5eb7d XL |
46 | pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { |
47 | let generic: syn::GenericParam = parse_quote!(__CTX); | |
48 | s.add_bounds(synstructure::AddBounds::Generics); | |
49 | s.add_impl_generic(generic); | |
dfeec247 | 50 | s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); |
60c5eb7d XL |
51 | let body = s.each(|bi| { |
52 | let attrs = parse_attributes(bi.ast()); | |
53 | if attrs.ignore { | |
dfeec247 | 54 | quote! {} |
60c5eb7d | 55 | } else if let Some(project) = attrs.project { |
dfeec247 | 56 | quote! { |
60c5eb7d XL |
57 | &#bi.#project.hash_stable(__hcx, __hasher); |
58 | } | |
59 | } else { | |
dfeec247 | 60 | quote! { |
60c5eb7d XL |
61 | #bi.hash_stable(__hcx, __hasher); |
62 | } | |
63 | } | |
64 | }); | |
65 | ||
66 | let discriminant = match s.ast().data { | |
67 | syn::Data::Enum(_) => quote! { | |
68 | ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); | |
69 | }, | |
70 | syn::Data::Struct(_) => quote! {}, | |
71 | syn::Data::Union(_) => panic!("cannot derive on union"), | |
72 | }; | |
73 | ||
dfeec247 XL |
74 | s.bound_impl( |
75 | quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), | |
76 | quote! { | |
77 | fn hash_stable( | |
78 | &self, | |
79 | __hcx: &mut __CTX, | |
80 | __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { | |
81 | #discriminant | |
82 | match *self { #body } | |
83 | } | |
84 | }, | |
85 | ) | |
60c5eb7d XL |
86 | } |
87 | ||
532ac7d7 XL |
88 | pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { |
89 | let generic: syn::GenericParam = parse_quote!('__ctx); | |
90 | s.add_bounds(synstructure::AddBounds::Generics); | |
91 | s.add_impl_generic(generic); | |
92 | let body = s.each(|bi| { | |
93 | let attrs = parse_attributes(bi.ast()); | |
94 | if attrs.ignore { | |
dfeec247 | 95 | quote! {} |
532ac7d7 | 96 | } else if let Some(project) = attrs.project { |
dfeec247 | 97 | quote! { |
532ac7d7 XL |
98 | &#bi.#project.hash_stable(__hcx, __hasher); |
99 | } | |
100 | } else { | |
dfeec247 | 101 | quote! { |
532ac7d7 XL |
102 | #bi.hash_stable(__hcx, __hasher); |
103 | } | |
104 | } | |
105 | }); | |
106 | ||
107 | let discriminant = match s.ast().data { | |
108 | syn::Data::Enum(_) => quote! { | |
109 | ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); | |
110 | }, | |
111 | syn::Data::Struct(_) => quote! {}, | |
112 | syn::Data::Union(_) => panic!("cannot derive on union"), | |
113 | }; | |
114 | ||
dfeec247 XL |
115 | s.bound_impl( |
116 | quote!( | |
117 | ::rustc_data_structures::stable_hasher::HashStable< | |
ba9703b0 | 118 | ::rustc_middle::ich::StableHashingContext<'__ctx>, |
dfeec247 XL |
119 | > |
120 | ), | |
121 | quote! { | |
122 | fn hash_stable( | |
123 | &self, | |
ba9703b0 | 124 | __hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>, |
dfeec247 XL |
125 | __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { |
126 | #discriminant | |
127 | match *self { #body } | |
128 | } | |
129 | }, | |
130 | ) | |
532ac7d7 | 131 | } |