From 9918693037dce8aa4bb6f08741b6812923486c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 Jun 2024 11:26:03 +0200 Subject: Merging upstream version 1.76.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_macros/src/hash_stable.rs | 140 ++++++++++++++++++------------- 1 file changed, 80 insertions(+), 60 deletions(-) (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 index 75a2f7009..a6396ba68 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -1,6 +1,6 @@ -use proc_macro2::{self, Ident}; +use proc_macro2::Ident; use quote::quote; -use syn::{self, parse_quote}; +use syn::parse_quote; struct Attributes { ignore: bool, @@ -38,41 +38,80 @@ fn parse_attributes(field: &syn::Field) -> Attributes { 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); - } - } +pub(crate) fn hash_stable_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::Normal) +} + +pub(crate) fn hash_stable_generic_derive( + s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::Generic) +} + +pub(crate) fn hash_stable_no_context_derive( + s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::NoContext) +} + +enum HashStableMode { + // Use the query-system aware stable hashing context. + Normal, + // Emit a generic implementation that uses a crate-local `StableHashingContext` + // trait, when the crate is upstream of `rustc_middle`. + Generic, + // Emit a hash-stable implementation that takes no context, + // and emits per-field where clauses for (almost-)perfect derives. + NoContext, +} + +fn hash_stable_derive_with_mode( + mut s: synstructure::Structure<'_>, + mode: HashStableMode, +) -> proc_macro2::TokenStream { + let generic: syn::GenericParam = match mode { + HashStableMode::Normal => parse_quote!('__ctx), + HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX), + }; + + // no_context impl is able to derive by-field, which is closer to a perfect derive. + s.add_bounds(match mode { + HashStableMode::Normal | HashStableMode::Generic => synstructure::AddBounds::Generics, + HashStableMode::NoContext => synstructure::AddBounds::Fields, }); - 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"), + // For generic impl, add `where __CTX: HashStableContext`. + match mode { + HashStableMode::Normal => {} + HashStableMode::Generic => { + s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); + } + HashStableMode::NoContext => {} + } + + s.add_impl_generic(generic); + + let discriminant = hash_stable_discriminant(&mut s); + let body = hash_stable_body(&mut s); + + let context: syn::Type = match mode { + HashStableMode::Normal => { + parse_quote!(::rustc_query_system::ich::StableHashingContext<'__ctx>) + } + HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX), }; s.bound_impl( - quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), + quote!( + ::rustc_data_structures::stable_hasher::HashStable< + #context + > + ), quote! { #[inline] fn hash_stable( &self, - __hcx: &mut __CTX, + __hcx: &mut #context, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { #discriminant match *self { #body } @@ -81,11 +120,18 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma ) } -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| { +fn hash_stable_discriminant(s: &mut synstructure::Structure<'_>) -> proc_macro2::TokenStream { + 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"), + } +} + +fn hash_stable_body(s: &mut synstructure::Structure<'_>) -> proc_macro2::TokenStream { + s.each(|bi| { let attrs = parse_attributes(bi.ast()); if attrs.ignore { quote! {} @@ -98,31 +144,5 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To #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