summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_macros/src/hash_stable.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_macros/src/hash_stable.rs
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_macros/src/hash_stable.rs')
-rw-r--r--compiler/rustc_macros/src/hash_stable.rs140
1 files changed, 80 insertions, 60 deletions
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 }
- }
- },
- )
+ })
}