From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/derivative/src/hash.rs | 97 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 vendor/derivative/src/hash.rs (limited to 'vendor/derivative/src/hash.rs') diff --git a/vendor/derivative/src/hash.rs b/vendor/derivative/src/hash.rs new file mode 100644 index 000000000..8f13f80f2 --- /dev/null +++ b/vendor/derivative/src/hash.rs @@ -0,0 +1,97 @@ +use proc_macro2; + +use ast; +use attr; +use matcher; +use paths; +use syn; +use utils; + +pub fn derive(input: &ast::Input) -> proc_macro2::TokenStream { + let hasher_trait_path = hasher_trait_path(); + let hash_trait_path = hash_trait_path(); + + let discriminant = if let ast::Body::Enum(_) = input.body { + let discriminant = paths::discriminant_path(); + Some(quote!( + #hash_trait_path::hash(&#discriminant(self), __state); + )) + } else { + None + }; + + let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed).build_arms( + input, + "__arg", + |_, _, _, _, _, bis| { + let field_prints = bis.iter().filter_map(|bi| { + if bi.field.attrs.ignore_hash() { + return None; + } + + let arg = &bi.expr; + + if let Some(hash_with) = bi.field.attrs.hash_with() { + Some(quote! { + #hash_with(&#arg, __state); + }) + } else { + Some(quote! { + #hash_trait_path::hash(&#arg, __state); + }) + } + }); + + quote! { + #(#field_prints)* + } + }, + ); + + let name = &input.ident; + let generics = utils::build_impl_generics( + input, + &hash_trait_path, + needs_hash_bound, + |field| field.hash_bound(), + |input| input.hash_bound(), + ); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let hasher_ty_parameter = utils::hygienic_type_parameter(input, "__H"); + quote! { + #[allow(unused_qualifications)] + impl #impl_generics #hash_trait_path for #name #ty_generics #where_clause { + fn hash<#hasher_ty_parameter>(&self, __state: &mut #hasher_ty_parameter) + where #hasher_ty_parameter: #hasher_trait_path + { + #discriminant + match *self { + #body + } + } + } + } +} + +fn needs_hash_bound(attrs: &attr::Field) -> bool { + !attrs.ignore_hash() && attrs.hash_bound().is_none() +} + +/// Return the path of the `Hash` trait, that is `::std::hash::Hash`. +fn hash_trait_path() -> syn::Path { + if cfg!(feature = "use_core") { + parse_quote!(::core::hash::Hash) + } else { + parse_quote!(::std::hash::Hash) + } +} + +/// Return the path of the `Hasher` trait, that is `::std::hash::Hasher`. +fn hasher_trait_path() -> syn::Path { + if cfg!(feature = "use_core") { + parse_quote!(::core::hash::Hasher) + } else { + parse_quote!(::std::hash::Hasher) + } +} -- cgit v1.2.3