mirror of https://github.com/rust-lang/rust.git
Unify HashStable implementations
This commit is contained in:
parent
426bc70ad6
commit
c9143ea1d9
|
@ -38,95 +38,80 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
|
||||||
attrs
|
attrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
pub(crate) fn hash_stable_generic_derive(
|
||||||
mut s: synstructure::Structure<'_>,
|
s: synstructure::Structure<'_>,
|
||||||
) -> proc_macro2::TokenStream {
|
) -> proc_macro2::TokenStream {
|
||||||
let generic: syn::GenericParam = parse_quote!(__CTX);
|
hash_stable_derive_with_mode(s, HashStableMode::Generic)
|
||||||
s.add_bounds(synstructure::AddBounds::Generics);
|
|
||||||
s.add_impl_generic(generic);
|
|
||||||
s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext });
|
|
||||||
|
|
||||||
let discriminant = hash_stable_discriminant(&mut s);
|
|
||||||
let body = hash_stable_body(&mut s);
|
|
||||||
|
|
||||||
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(crate) fn hash_stable_no_context_derive(
|
pub(crate) fn hash_stable_no_context_derive(
|
||||||
mut s: synstructure::Structure<'_>,
|
s: synstructure::Structure<'_>,
|
||||||
) -> proc_macro2::TokenStream {
|
) -> proc_macro2::TokenStream {
|
||||||
let generic: syn::GenericParam = parse_quote!(__CTX);
|
hash_stable_derive_with_mode(s, HashStableMode::NoContext)
|
||||||
s.add_bounds(synstructure::AddBounds::Fields);
|
|
||||||
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<__CTX>),
|
|
||||||
quote! {
|
|
||||||
#[inline]
|
|
||||||
fn hash_stable(
|
|
||||||
&self,
|
|
||||||
__hcx: &mut __CTX,
|
|
||||||
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
|
|
||||||
#discriminant
|
|
||||||
match *self { #body }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
enum HashStableMode {
|
||||||
let generic: syn::GenericParam = parse_quote!('__ctx);
|
// Use the query-system aware stable hashing context.
|
||||||
s.add_bounds(synstructure::AddBounds::Generics);
|
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,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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);
|
s.add_impl_generic(generic);
|
||||||
|
|
||||||
let discriminant = hash_stable_discriminant(&mut s);
|
let discriminant = hash_stable_discriminant(&mut s);
|
||||||
let body = hash_stable_body(&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(
|
s.bound_impl(
|
||||||
quote!(
|
quote!(
|
||||||
::rustc_data_structures::stable_hasher::HashStable<
|
::rustc_data_structures::stable_hasher::HashStable<
|
||||||
::rustc_query_system::ich::StableHashingContext<'__ctx>,
|
#context
|
||||||
>
|
>
|
||||||
),
|
),
|
||||||
quote! {
|
quote! {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash_stable(
|
fn hash_stable(
|
||||||
&self,
|
&self,
|
||||||
__hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
|
__hcx: &mut #context,
|
||||||
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
|
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
|
||||||
#discriminant
|
#discriminant
|
||||||
match *self { #body }
|
match *self { #body }
|
||||||
|
|
Loading…
Reference in New Issue