Skip to content

Commit 7bd385d

Browse files
committed
Auto merge of rust-lang#117580 - compiler-errors:hash-stable-simplify-rustc_type_ir, r=jackh726
Add `HashStable_NoContext` to simplify `HashStable` implementations in `rustc_type_ir` adds `derive(HashStable_NoContext)` which is a derived `HashStable` implementation that has no `HashStableContext` bound, and which adds `where` bounds for `HashStable` based off of *fields* and not generics. This means we can `derive(HashStable_NoContext)` in more places in `rustc_type_ir` rather than having to hand-roll implementations.
2 parents c5af061 + c9143ea commit 7bd385d

File tree

10 files changed

+79
-316
lines changed

10 files changed

+79
-316
lines changed

compiler/rustc_ast/src/lib.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5959
/// Requirements for a `StableHashingContext` to be used in this crate.
6060
/// This is a hack to allow using the `HashStable_Generic` derive macro
6161
/// instead of implementing everything in `rustc_middle`.
62-
pub trait HashStableContext:
63-
rustc_type_ir::HashStableContext + rustc_span::HashStableContext
64-
{
62+
pub trait HashStableContext: rustc_span::HashStableContext {
6563
fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
6664
}
6765

compiler/rustc_macros/src/hash_stable.rs

+54-25
Original file line numberDiff line numberDiff line change
@@ -38,51 +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_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
68-
let generic: syn::GenericParam = parse_quote!('__ctx);
69-
s.add_bounds(synstructure::AddBounds::Generics);
68+
fn hash_stable_derive_with_mode(
69+
mut s: synstructure::Structure<'_>,
70+
mode: HashStableMode,
71+
) -> proc_macro2::TokenStream {
72+
let generic: syn::GenericParam = match mode {
73+
HashStableMode::Normal => parse_quote!('__ctx),
74+
HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX),
75+
};
76+
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+
}
91+
7092
s.add_impl_generic(generic);
7193

7294
let discriminant = hash_stable_discriminant(&mut s);
7395
let body = hash_stable_body(&mut s);
7496

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+
75104
s.bound_impl(
76105
quote!(
77106
::rustc_data_structures::stable_hasher::HashStable<
78-
::rustc_query_system::ich::StableHashingContext<'__ctx>,
107+
#context
79108
>
80109
),
81110
quote! {
82111
#[inline]
83112
fn hash_stable(
84113
&self,
85-
__hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
114+
__hcx: &mut #context,
86115
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
87116
#discriminant
88117
match *self { #body }

compiler/rustc_macros/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ decl_derive!(
4848
[HashStable_Generic, attributes(stable_hasher)] =>
4949
hash_stable::hash_stable_generic_derive
5050
);
51+
decl_derive!(
52+
[HashStable_NoContext] =>
53+
/// `HashStable` implementation that has no `HashStableContext` bound and
54+
/// which adds `where` bounds for `HashStable` based off of fields and not
55+
/// generics. This is suitable for use in crates like `rustc_type_ir`.
56+
hash_stable::hash_stable_no_context_derive
57+
);
5158

5259
decl_derive!([Decodable] => serialize::decodable_derive);
5360
decl_derive!([Encodable] => serialize::encodable_derive);

compiler/rustc_query_system/src/ich/impls_syntax.rs

-2
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,3 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
123123
});
124124
}
125125
}
126-
127-
impl<'ctx> rustc_type_ir::HashStableContext for StableHashingContext<'ctx> {}

compiler/rustc_type_ir/src/canonical.rs

+1-17
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ use std::fmt;
22
use std::hash::Hash;
33
use std::ops::ControlFlow;
44

5-
#[cfg(feature = "nightly")]
6-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
7-
85
use crate::fold::{FallibleTypeFolder, TypeFoldable};
96
use crate::visit::{TypeVisitable, TypeVisitor};
107
use crate::{Interner, UniverseIndex};
@@ -14,7 +11,7 @@ use crate::{Interner, UniverseIndex};
1411
/// numbered starting from 0 in order of first appearance.
1512
#[derive(derivative::Derivative)]
1613
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
17-
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
14+
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
1815
pub struct Canonical<I: Interner, V> {
1916
pub value: V,
2017
pub max_universe: UniverseIndex,
@@ -61,19 +58,6 @@ impl<I: Interner, V> Canonical<I, V> {
6158
}
6259
}
6360

64-
#[cfg(feature = "nightly")]
65-
impl<CTX: crate::HashStableContext, I: Interner, V: HashStable<CTX>> HashStable<CTX>
66-
for Canonical<I, V>
67-
where
68-
I::CanonicalVars: HashStable<CTX>,
69-
{
70-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
71-
self.value.hash_stable(hcx, hasher);
72-
self.max_universe.hash_stable(hcx, hasher);
73-
self.variables.hash_stable(hcx, hasher);
74-
}
75-
}
76-
7761
impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
7862

7963
impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {

compiler/rustc_type_ir/src/const_kind.rs

+1-44
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use self::ConstKind::*;
1616
Ord = "feature_allow_slow_enum",
1717
Hash(bound = "")
1818
)]
19-
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
19+
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
2020
pub enum ConstKind<I: Interner> {
2121
/// A const generic parameter.
2222
Param(I::ParamConst),
@@ -47,49 +47,6 @@ pub enum ConstKind<I: Interner> {
4747
Expr(I::ExprConst),
4848
}
4949

50-
#[cfg(feature = "nightly")]
51-
const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
52-
match value {
53-
Param(_) => 0,
54-
Infer(_) => 1,
55-
Bound(_, _) => 2,
56-
Placeholder(_) => 3,
57-
Unevaluated(_) => 4,
58-
Value(_) => 5,
59-
Error(_) => 6,
60-
Expr(_) => 7,
61-
}
62-
}
63-
64-
#[cfg(feature = "nightly")]
65-
impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
66-
where
67-
I::ParamConst: HashStable<CTX>,
68-
I::BoundConst: HashStable<CTX>,
69-
I::PlaceholderConst: HashStable<CTX>,
70-
I::AliasConst: HashStable<CTX>,
71-
I::ValueConst: HashStable<CTX>,
72-
I::ErrorGuaranteed: HashStable<CTX>,
73-
I::ExprConst: HashStable<CTX>,
74-
{
75-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
76-
const_kind_discriminant(self).hash_stable(hcx, hasher);
77-
match self {
78-
Param(p) => p.hash_stable(hcx, hasher),
79-
Infer(i) => i.hash_stable(hcx, hasher),
80-
Bound(d, b) => {
81-
d.hash_stable(hcx, hasher);
82-
b.hash_stable(hcx, hasher);
83-
}
84-
Placeholder(p) => p.hash_stable(hcx, hasher),
85-
Unevaluated(u) => u.hash_stable(hcx, hasher),
86-
Value(v) => v.hash_stable(hcx, hasher),
87-
Error(e) => e.hash_stable(hcx, hasher),
88-
Expr(e) => e.hash_stable(hcx, hasher),
89-
}
90-
}
91-
}
92-
9350
impl<I: Interner> PartialEq for ConstKind<I> {
9451
fn eq(&self, other: &Self) -> bool {
9552
match (self, other) {

compiler/rustc_type_ir/src/lib.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ pub use region_kind::*;
5151
pub use ty_info::*;
5252
pub use ty_kind::*;
5353

54-
/// Needed so we can use #[derive(HashStable_Generic)]
55-
pub trait HashStableContext {}
56-
5754
rustc_index::newtype_index! {
5855
/// A [De Bruijn index][dbi] is a standard means of representing
5956
/// regions (and perhaps later types) in a higher-ranked setting. In
@@ -94,7 +91,7 @@ rustc_index::newtype_index! {
9491
/// is the outer fn.
9592
///
9693
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
97-
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
94+
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
9895
#[debug_format = "DebruijnIndex({})"]
9996
#[gate_rustc_only]
10097
pub struct DebruijnIndex {
@@ -179,7 +176,7 @@ pub fn debug_bound_var<T: std::fmt::Write>(
179176
}
180177

181178
#[derive(Copy, Clone, PartialEq, Eq)]
182-
#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_Generic))]
179+
#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_NoContext))]
183180
#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
184181
pub enum Variance {
185182
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
@@ -295,7 +292,7 @@ rustc_index::newtype_index! {
295292
/// declared, but a type name in a non-zero universe is a placeholder
296293
/// type -- an idealized representative of "types in general" that we
297294
/// use for checking generic functions.
298-
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
295+
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
299296
#[debug_format = "U{}"]
300297
#[gate_rustc_only]
301298
pub struct UniverseIndex {}

0 commit comments

Comments
 (0)