]> git.proxmox.com Git - rustc.git/blame - vendor/rustc-ap-rustc_macros/src/hash_stable.rs
Update upstream source from tag 'upstream/1.52.1+dfsg1'
[rustc.git] / vendor / rustc-ap-rustc_macros / src / hash_stable.rs
CommitLineData
f20569fa
XL
1use proc_macro2::{self, Ident};
2use quote::quote;
3use syn::{self, parse_quote, Meta, NestedMeta};
4
5struct Attributes {
6 ignore: bool,
7 project: Option<Ident>,
8}
9
10fn 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
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);
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
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 {
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}