]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use proc_macro2::{self, Ident}; |
2 | use quote::quote; | |
3 | use syn::{self, parse_quote, Meta, NestedMeta}; | |
4 | ||
5 | struct Attributes { | |
6 | ignore: bool, | |
7 | project: Option<Ident>, | |
8 | } | |
9 | ||
10 | fn parse_attributes(field: &syn::Field) -> Attributes { | |
11 | let mut attrs = Attributes { ignore: false, project: None }; | |
12 | for attr in &field.attrs { | |
13 | if let Ok(meta) = attr.parse_meta() { | |
14 | if !meta.path().is_ident("stable_hasher") { | |
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 { | |
21 | if meta.path().is_ident("ignore") { | |
22 | attrs.ignore = true; | |
23 | any_attr = true; | |
24 | } | |
25 | if meta.path().is_ident("project") { | |
26 | if let Meta::List(list) = meta { | |
27 | if let Some(nested) = list.nested.iter().next() { | |
28 | if let NestedMeta::Meta(meta) = nested { | |
29 | attrs.project = meta.path().get_ident().cloned(); | |
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 | ||
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); | |
50 | s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); | |
51 | let body = s.each(|bi| { | |
52 | let attrs = parse_attributes(bi.ast()); | |
53 | if attrs.ignore { | |
54 | quote! {} | |
55 | } else if let Some(project) = attrs.project { | |
56 | quote! { | |
57 | &#bi.#project.hash_stable(__hcx, __hasher); | |
58 | } | |
59 | } else { | |
60 | quote! { | |
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 | ||
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 | ) | |
86 | } | |
87 | ||
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 { | |
95 | quote! {} | |
96 | } else if let Some(project) = attrs.project { | |
97 | quote! { | |
98 | &#bi.#project.hash_stable(__hcx, __hasher); | |
99 | } | |
100 | } else { | |
101 | quote! { | |
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 | ||
115 | s.bound_impl( | |
116 | quote!( | |
117 | ::rustc_data_structures::stable_hasher::HashStable< | |
118 | ::rustc_middle::ich::StableHashingContext<'__ctx>, | |
119 | > | |
120 | ), | |
121 | quote! { | |
122 | fn hash_stable( | |
123 | &self, | |
124 | __hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>, | |
125 | __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { | |
126 | #discriminant | |
127 | match *self { #body } | |
128 | } | |
129 | }, | |
130 | ) | |
131 | } |