2019-03-04 22:53:16 -06:00
|
|
|
use proc_macro2::{self, Ident};
|
2019-03-05 12:27:50 -06:00
|
|
|
use quote::quote;
|
2019-12-22 16:42:04 -06:00
|
|
|
use syn::{self, parse_quote, Meta, NestedMeta};
|
2018-12-15 21:44:12 -06:00
|
|
|
|
|
|
|
struct Attributes {
|
|
|
|
ignore: bool,
|
2019-03-04 22:53:16 -06:00
|
|
|
project: Option<Ident>,
|
2018-12-15 21:44:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_attributes(field: &syn::Field) -> Attributes {
|
2019-12-22 16:42:04 -06:00
|
|
|
let mut attrs = Attributes { ignore: false, project: None };
|
2018-12-15 21:44:12 -06:00
|
|
|
for attr in &field.attrs {
|
|
|
|
if let Ok(meta) = attr.parse_meta() {
|
2019-10-04 07:43:23 -05:00
|
|
|
if !meta.path().is_ident("stable_hasher") {
|
2018-12-15 21:44:12 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let mut any_attr = false;
|
|
|
|
if let Meta::List(list) = meta {
|
|
|
|
for nested in list.nested.iter() {
|
|
|
|
if let NestedMeta::Meta(meta) = nested {
|
2019-10-04 07:43:23 -05:00
|
|
|
if meta.path().is_ident("ignore") {
|
2018-12-15 21:44:12 -06:00
|
|
|
attrs.ignore = true;
|
|
|
|
any_attr = true;
|
|
|
|
}
|
2019-10-04 07:43:23 -05:00
|
|
|
if meta.path().is_ident("project") {
|
2018-12-15 21:44:12 -06:00
|
|
|
if let Meta::List(list) = meta {
|
2021-11-07 03:33:27 -06:00
|
|
|
if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() {
|
|
|
|
attrs.project = meta.path().get_ident().cloned();
|
|
|
|
any_attr = true;
|
2018-12-15 21:44:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !any_attr {
|
|
|
|
panic!("error parsing stable_hasher");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
attrs
|
|
|
|
}
|
2018-12-02 18:14:35 -06:00
|
|
|
|
2019-11-09 13:34:55 -06:00
|
|
|
pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
|
|
|
let generic: syn::GenericParam = parse_quote!(__CTX);
|
|
|
|
s.add_bounds(synstructure::AddBounds::Generics);
|
|
|
|
s.add_impl_generic(generic);
|
2019-12-22 16:42:04 -06:00
|
|
|
s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext });
|
2019-11-09 13:34:55 -06:00
|
|
|
let body = s.each(|bi| {
|
|
|
|
let attrs = parse_attributes(bi.ast());
|
|
|
|
if attrs.ignore {
|
2019-12-22 16:42:04 -06:00
|
|
|
quote! {}
|
2019-11-09 13:34:55 -06:00
|
|
|
} else if let Some(project) = attrs.project {
|
2019-12-22 16:42:04 -06:00
|
|
|
quote! {
|
2021-06-18 02:09:40 -05:00
|
|
|
(&#bi.#project).hash_stable(__hcx, __hasher);
|
2019-11-09 13:34:55 -06:00
|
|
|
}
|
|
|
|
} else {
|
2019-12-22 16:42:04 -06:00
|
|
|
quote! {
|
2019-11-09 13:34:55 -06:00
|
|
|
#bi.hash_stable(__hcx, __hasher);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let discriminant = match s.ast().data {
|
|
|
|
syn::Data::Enum(_) => quote! {
|
|
|
|
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
|
|
|
|
},
|
|
|
|
syn::Data::Struct(_) => quote! {},
|
|
|
|
syn::Data::Union(_) => panic!("cannot derive on union"),
|
|
|
|
};
|
|
|
|
|
2019-12-22 16:42:04 -06:00
|
|
|
s.bound_impl(
|
|
|
|
quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>),
|
|
|
|
quote! {
|
2021-03-11 04:49:23 -06:00
|
|
|
#[inline]
|
2019-12-22 16:42:04 -06:00
|
|
|
fn hash_stable(
|
|
|
|
&self,
|
|
|
|
__hcx: &mut __CTX,
|
|
|
|
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
|
|
|
|
#discriminant
|
|
|
|
match *self { #body }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
2019-11-09 13:34:55 -06:00
|
|
|
}
|
|
|
|
|
2019-03-05 12:27:50 -06:00
|
|
|
pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
2018-12-02 18:14:35 -06:00
|
|
|
let generic: syn::GenericParam = parse_quote!('__ctx);
|
|
|
|
s.add_bounds(synstructure::AddBounds::Generics);
|
|
|
|
s.add_impl_generic(generic);
|
2018-12-15 21:44:12 -06:00
|
|
|
let body = s.each(|bi| {
|
|
|
|
let attrs = parse_attributes(bi.ast());
|
|
|
|
if attrs.ignore {
|
2019-12-22 16:42:04 -06:00
|
|
|
quote! {}
|
2018-12-15 21:44:12 -06:00
|
|
|
} else if let Some(project) = attrs.project {
|
2019-12-22 16:42:04 -06:00
|
|
|
quote! {
|
2021-06-18 02:09:40 -05:00
|
|
|
(&#bi.#project).hash_stable(__hcx, __hasher);
|
2018-12-15 21:44:12 -06:00
|
|
|
}
|
|
|
|
} else {
|
2019-12-22 16:42:04 -06:00
|
|
|
quote! {
|
2018-12-15 21:44:12 -06:00
|
|
|
#bi.hash_stable(__hcx, __hasher);
|
|
|
|
}
|
|
|
|
}
|
2018-12-02 18:14:35 -06:00
|
|
|
});
|
|
|
|
|
|
|
|
let discriminant = match s.ast().data {
|
|
|
|
syn::Data::Enum(_) => quote! {
|
|
|
|
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
|
|
|
|
},
|
|
|
|
syn::Data::Struct(_) => quote! {},
|
|
|
|
syn::Data::Union(_) => panic!("cannot derive on union"),
|
|
|
|
};
|
|
|
|
|
2019-12-22 16:42:04 -06:00
|
|
|
s.bound_impl(
|
|
|
|
quote!(
|
|
|
|
::rustc_data_structures::stable_hasher::HashStable<
|
2020-11-14 09:48:54 -06:00
|
|
|
::rustc_query_system::ich::StableHashingContext<'__ctx>,
|
2019-12-22 16:42:04 -06:00
|
|
|
>
|
|
|
|
),
|
|
|
|
quote! {
|
2021-03-11 04:49:23 -06:00
|
|
|
#[inline]
|
2019-12-22 16:42:04 -06:00
|
|
|
fn hash_stable(
|
|
|
|
&self,
|
2020-11-14 09:48:54 -06:00
|
|
|
__hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
|
2019-12-22 16:42:04 -06:00
|
|
|
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
|
|
|
|
#discriminant
|
|
|
|
match *self { #body }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
2018-12-02 18:14:35 -06:00
|
|
|
}
|