From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_macros/src/hash_stable.rs | 131 +++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 compiler/rustc_macros/src/hash_stable.rs (limited to 'compiler/rustc_macros/src/hash_stable.rs') diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs new file mode 100644 index 000000000..63bdcea87 --- /dev/null +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -0,0 +1,131 @@ +use proc_macro2::{self, Ident}; +use quote::quote; +use syn::{self, parse_quote, Meta, NestedMeta}; + +struct Attributes { + ignore: bool, + project: Option, +} + +fn parse_attributes(field: &syn::Field) -> Attributes { + let mut attrs = Attributes { ignore: false, project: None }; + for attr in &field.attrs { + if let Ok(meta) = attr.parse_meta() { + if !meta.path().is_ident("stable_hasher") { + continue; + } + let mut any_attr = false; + if let Meta::List(list) = meta { + for nested in list.nested.iter() { + if let NestedMeta::Meta(meta) = nested { + if meta.path().is_ident("ignore") { + attrs.ignore = true; + any_attr = true; + } + if meta.path().is_ident("project") { + if let Meta::List(list) = meta { + if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() { + attrs.project = meta.path().get_ident().cloned(); + any_attr = true; + } + } + } + } + } + } + if !any_attr { + panic!("error parsing stable_hasher"); + } + } + } + attrs +} + +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); + s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); + let body = s.each(|bi| { + let attrs = parse_attributes(bi.ast()); + if attrs.ignore { + quote! {} + } else if let Some(project) = attrs.project { + quote! { + (&#bi.#project).hash_stable(__hcx, __hasher); + } + } else { + quote! { + #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"), + }; + + s.bound_impl( + quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), + quote! { + #[inline] + fn hash_stable( + &self, + __hcx: &mut __CTX, + __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + #discriminant + match *self { #body } + } + }, + ) +} + +pub fn hash_stable_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); + let body = s.each(|bi| { + let attrs = parse_attributes(bi.ast()); + if attrs.ignore { + quote! {} + } else if let Some(project) = attrs.project { + quote! { + (&#bi.#project).hash_stable(__hcx, __hasher); + } + } else { + quote! { + #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"), + }; + + s.bound_impl( + quote!( + ::rustc_data_structures::stable_hasher::HashStable< + ::rustc_query_system::ich::StableHashingContext<'__ctx>, + > + ), + quote! { + #[inline] + fn hash_stable( + &self, + __hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>, + __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + #discriminant + match *self { #body } + } + }, + ) +} -- cgit v1.2.3