rust/compiler/rustc_macros/src/hash_stable.rs

129 lines
3.9 KiB
Rust
Raw Normal View History

2019-03-05 05:53:16 +01:00
use proc_macro2::{self, Ident};
2019-03-05 19:27:50 +01:00
use quote::quote;
2023-03-27 13:44:06 +00:00
use syn::{self, parse_quote};
2018-12-16 04:44:12 +01:00
struct Attributes {
ignore: bool,
2019-03-05 05:53:16 +01:00
project: Option<Ident>,
2018-12-16 04:44:12 +01:00
}
fn parse_attributes(field: &syn::Field) -> Attributes {
2019-12-22 17:42:04 -05:00
let mut attrs = Attributes { ignore: false, project: None };
2018-12-16 04:44:12 +01:00
for attr in &field.attrs {
2023-03-27 13:44:06 +00:00
let meta = &attr.meta;
if !meta.path().is_ident("stable_hasher") {
continue;
}
let mut any_attr = false;
let _ = attr.parse_nested_meta(|nested| {
if nested.path.is_ident("ignore") {
attrs.ignore = true;
any_attr = true;
2018-12-16 04:44:12 +01:00
}
2023-03-27 13:44:06 +00:00
if nested.path.is_ident("project") {
let _ = nested.parse_nested_meta(|meta| {
if attrs.project.is_none() {
attrs.project = meta.path.get_ident().cloned();
2018-12-16 04:44:12 +01:00
}
2023-03-27 13:44:06 +00:00
any_attr = true;
Ok(())
});
2018-12-16 04:44:12 +01:00
}
2023-03-27 13:44:06 +00:00
Ok(())
});
if !any_attr {
panic!("error parsing stable_hasher");
2018-12-16 04:44:12 +01:00
}
}
attrs
}
2018-12-03 01:14:35 +01:00
2019-11-09 20:34:55 +01: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 17:42:04 -05:00
s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext });
2019-11-09 20:34:55 +01:00
let body = s.each(|bi| {
let attrs = parse_attributes(bi.ast());
if attrs.ignore {
2019-12-22 17:42:04 -05:00
quote! {}
2019-11-09 20:34:55 +01:00
} else if let Some(project) = attrs.project {
2019-12-22 17:42:04 -05:00
quote! {
(&#bi.#project).hash_stable(__hcx, __hasher);
2019-11-09 20:34:55 +01:00
}
} else {
2019-12-22 17:42:04 -05:00
quote! {
2019-11-09 20:34:55 +01: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 17:42:04 -05:00
s.bound_impl(
quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>),
quote! {
2021-03-11 11:49:23 +01:00
#[inline]
2019-12-22 17:42:04 -05:00
fn hash_stable(
&self,
__hcx: &mut __CTX,
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
#discriminant
match *self { #body }
}
},
)
2019-11-09 20:34:55 +01:00
}
2019-03-05 19:27:50 +01:00
pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
2018-12-03 01:14:35 +01:00
let generic: syn::GenericParam = parse_quote!('__ctx);
s.add_bounds(synstructure::AddBounds::Generics);
s.add_impl_generic(generic);
2018-12-16 04:44:12 +01:00
let body = s.each(|bi| {
let attrs = parse_attributes(bi.ast());
if attrs.ignore {
2019-12-22 17:42:04 -05:00
quote! {}
2018-12-16 04:44:12 +01:00
} else if let Some(project) = attrs.project {
2019-12-22 17:42:04 -05:00
quote! {
(&#bi.#project).hash_stable(__hcx, __hasher);
2018-12-16 04:44:12 +01:00
}
} else {
2019-12-22 17:42:04 -05:00
quote! {
2018-12-16 04:44:12 +01:00
#bi.hash_stable(__hcx, __hasher);
}
}
2018-12-03 01:14:35 +01: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 17:42:04 -05:00
s.bound_impl(
quote!(
::rustc_data_structures::stable_hasher::HashStable<
2020-11-14 16:48:54 +01:00
::rustc_query_system::ich::StableHashingContext<'__ctx>,
2019-12-22 17:42:04 -05:00
>
),
quote! {
2021-03-11 11:49:23 +01:00
#[inline]
2019-12-22 17:42:04 -05:00
fn hash_stable(
&self,
2020-11-14 16:48:54 +01:00
__hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
2019-12-22 17:42:04 -05:00
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
#discriminant
match *self { #body }
}
},
)
2018-12-03 01:14:35 +01:00
}