Skip to content

Commit c9143ea

Browse files
Unify HashStable implementations
1 parent 426bc70 commit c9143ea

File tree

1 file changed

+49
-64
lines changed

1 file changed

+49
-64
lines changed

compiler/rustc_macros/src/hash_stable.rs

+49-64
Original file line numberDiff line numberDiff line change
@@ -38,95 +38,80 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
3838
attrs
3939
}
4040

41+
pub(crate) fn hash_stable_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
42+
hash_stable_derive_with_mode(s, HashStableMode::Normal)
43+
}
44+
4145
pub(crate) fn hash_stable_generic_derive(
42-
mut s: synstructure::Structure<'_>,
46+
s: synstructure::Structure<'_>,
4347
) -> proc_macro2::TokenStream {
44-
let generic: syn::GenericParam = parse_quote!(__CTX);
45-
s.add_bounds(synstructure::AddBounds::Generics);
46-
s.add_impl_generic(generic);
47-
s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext });
48+
hash_stable_derive_with_mode(s, HashStableMode::Generic)
49+
}
4850

49-
let discriminant = hash_stable_discriminant(&mut s);
50-
let body = hash_stable_body(&mut s);
51+
pub(crate) fn hash_stable_no_context_derive(
52+
s: synstructure::Structure<'_>,
53+
) -> proc_macro2::TokenStream {
54+
hash_stable_derive_with_mode(s, HashStableMode::NoContext)
55+
}
5156

52-
s.bound_impl(
53-
quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>),
54-
quote! {
55-
#[inline]
56-
fn hash_stable(
57-
&self,
58-
__hcx: &mut __CTX,
59-
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
60-
#discriminant
61-
match *self { #body }
62-
}
63-
},
64-
)
57+
enum HashStableMode {
58+
// Use the query-system aware stable hashing context.
59+
Normal,
60+
// Emit a generic implementation that uses a crate-local `StableHashingContext`
61+
// trait, when the crate is upstream of `rustc_middle`.
62+
Generic,
63+
// Emit a hash-stable implementation that takes no context,
64+
// and emits per-field where clauses for (almost-)perfect derives.
65+
NoContext,
6566
}
6667

67-
pub(crate) fn hash_stable_no_context_derive(
68+
fn hash_stable_derive_with_mode(
6869
mut s: synstructure::Structure<'_>,
70+
mode: HashStableMode,
6971
) -> proc_macro2::TokenStream {
70-
let generic: syn::GenericParam = parse_quote!(__CTX);
71-
s.add_bounds(synstructure::AddBounds::Fields);
72-
s.add_impl_generic(generic);
73-
let body = s.each(|bi| {
74-
let attrs = parse_attributes(bi.ast());
75-
if attrs.ignore {
76-
quote! {}
77-
} else if let Some(project) = attrs.project {
78-
quote! {
79-
(&#bi.#project).hash_stable(__hcx, __hasher);
80-
}
81-
} else {
82-
quote! {
83-
#bi.hash_stable(__hcx, __hasher);
84-
}
85-
}
86-
});
87-
88-
let discriminant = match s.ast().data {
89-
syn::Data::Enum(_) => quote! {
90-
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
91-
},
92-
syn::Data::Struct(_) => quote! {},
93-
syn::Data::Union(_) => panic!("cannot derive on union"),
72+
let generic: syn::GenericParam = match mode {
73+
HashStableMode::Normal => parse_quote!('__ctx),
74+
HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX),
9475
};
9576

96-
s.bound_impl(
97-
quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>),
98-
quote! {
99-
#[inline]
100-
fn hash_stable(
101-
&self,
102-
__hcx: &mut __CTX,
103-
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
104-
#discriminant
105-
match *self { #body }
106-
}
107-
},
108-
)
109-
}
77+
// no_context impl is able to derive by-field, which is closer to a perfect derive.
78+
s.add_bounds(match mode {
79+
HashStableMode::Normal | HashStableMode::Generic => synstructure::AddBounds::Generics,
80+
HashStableMode::NoContext => synstructure::AddBounds::Fields,
81+
});
82+
83+
// For generic impl, add `where __CTX: HashStableContext`.
84+
match mode {
85+
HashStableMode::Normal => {}
86+
HashStableMode::Generic => {
87+
s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext });
88+
}
89+
HashStableMode::NoContext => {}
90+
}
11091

111-
pub(crate) fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
112-
let generic: syn::GenericParam = parse_quote!('__ctx);
113-
s.add_bounds(synstructure::AddBounds::Generics);
11492
s.add_impl_generic(generic);
11593

11694
let discriminant = hash_stable_discriminant(&mut s);
11795
let body = hash_stable_body(&mut s);
11896

97+
let context: syn::Type = match mode {
98+
HashStableMode::Normal => {
99+
parse_quote!(::rustc_query_system::ich::StableHashingContext<'__ctx>)
100+
}
101+
HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX),
102+
};
103+
119104
s.bound_impl(
120105
quote!(
121106
::rustc_data_structures::stable_hasher::HashStable<
122-
::rustc_query_system::ich::StableHashingContext<'__ctx>,
107+
#context
123108
>
124109
),
125110
quote! {
126111
#[inline]
127112
fn hash_stable(
128113
&self,
129-
__hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
114+
__hcx: &mut #context,
130115
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
131116
#discriminant
132117
match *self { #body }

0 commit comments

Comments
 (0)