]> git.proxmox.com Git - rustc.git/blame - src/librustc_macros/src/hash_stable.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustc_macros / src / hash_stable.rs
CommitLineData
532ac7d7
XL
1use proc_macro2::{self, Ident};
2use quote::quote;
dfeec247 3use syn::{self, parse_quote, Meta, NestedMeta};
532ac7d7
XL
4
5struct Attributes {
6 ignore: bool,
7 project: Option<Ident>,
8}
9
10fn 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
46pub 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
88pub 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}