Skip to content

Commit 543d9d3

Browse files
Add HashStable_NoContext to simplify HashStable implementations in rustc_type_ir
1 parent 069a4af commit 543d9d3

File tree

10 files changed

+76
-292
lines changed

10 files changed

+76
-292
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

+44
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,50 @@ pub(crate) fn hash_stable_generic_derive(
6464
)
6565
}
6666

67+
pub(crate) fn hash_stable_no_context_derive(
68+
mut s: synstructure::Structure<'_>,
69+
) -> 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"),
94+
};
95+
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+
}
110+
67111
pub(crate) fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
68112
let generic: syn::GenericParam = parse_quote!('__ctx);
69113
s.add_bounds(synstructure::AddBounds::Generics);

compiler/rustc_macros/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ decl_derive!(
7070
[HashStable_Generic, attributes(stable_hasher)] =>
7171
hash_stable::hash_stable_generic_derive
7272
);
73+
decl_derive!(
74+
[HashStable_NoContext] =>
75+
/// `HashStable` implementation that has no `HashStableContext` bound and
76+
/// which adds `where` bounds for `HashStable` based off of fields and not
77+
/// generics. This is suitable for use in crates like `rustc_type_ir`.
78+
hash_stable::hash_stable_no_context_derive
79+
);
7380

7481
decl_derive!([Decodable] => serialize::decodable_derive);
7582
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

+2-15
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ use std::fmt;
22
use std::hash::Hash;
33
use std::ops::ControlFlow;
44

5-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
6-
75
use crate::fold::{FallibleTypeFolder, TypeFoldable};
86
use crate::visit::{TypeVisitable, TypeVisitor};
9-
use crate::{HashStableContext, Interner, UniverseIndex};
7+
use crate::{Interner, UniverseIndex};
108

119
/// A "canonicalized" type `V` is one where all free inference
1210
/// variables have been rewritten to "canonical vars". These are
1311
/// numbered starting from 0 in order of first appearance.
1412
#[derive(derivative::Derivative)]
1513
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
16-
#[derive(TyEncodable, TyDecodable)]
14+
#[derive(TyEncodable, TyDecodable, HashStable_NoContext)]
1715
pub struct Canonical<I: Interner, V> {
1816
pub value: V,
1917
pub max_universe: UniverseIndex,
@@ -60,17 +58,6 @@ impl<I: Interner, V> Canonical<I, V> {
6058
}
6159
}
6260

63-
impl<CTX: HashStableContext, I: Interner, V: HashStable<CTX>> HashStable<CTX> for Canonical<I, V>
64-
where
65-
I::CanonicalVars: HashStable<CTX>,
66-
{
67-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
68-
self.value.hash_stable(hcx, hasher);
69-
self.max_universe.hash_stable(hcx, hasher);
70-
self.variables.hash_stable(hcx, hasher);
71-
}
72-
}
73-
7461
impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
7562

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

compiler/rustc_type_ir/src/const_kind.rs

+2-46
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
use rustc_data_structures::stable_hasher::HashStable;
2-
use rustc_data_structures::stable_hasher::StableHasher;
31
use std::fmt;
42

5-
use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
3+
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
64

75
use self::ConstKind::*;
86

@@ -16,7 +14,7 @@ use self::ConstKind::*;
1614
Ord = "feature_allow_slow_enum",
1715
Hash(bound = "")
1816
)]
19-
#[derive(TyEncodable, TyDecodable)]
17+
#[derive(TyEncodable, TyDecodable, HashStable_NoContext)]
2018
pub enum ConstKind<I: Interner> {
2119
/// A const generic parameter.
2220
Param(I::ParamConst),
@@ -47,48 +45,6 @@ pub enum ConstKind<I: Interner> {
4745
Expr(I::ExprConst),
4846
}
4947

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

compiler/rustc_type_ir/src/lib.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ pub use region_kind::*;
4747
pub use ty_info::*;
4848
pub use ty_kind::*;
4949

50-
/// Needed so we can use #[derive(HashStable_Generic)]
51-
pub trait HashStableContext {}
52-
5350
rustc_index::newtype_index! {
5451
/// A [De Bruijn index][dbi] is a standard means of representing
5552
/// regions (and perhaps later types) in a higher-ranked setting. In
@@ -90,7 +87,7 @@ rustc_index::newtype_index! {
9087
/// is the outer fn.
9188
///
9289
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
93-
#[derive(HashStable_Generic)]
90+
#[derive(HashStable_NoContext)]
9491
#[debug_format = "DebruijnIndex({})"]
9592
pub struct DebruijnIndex {
9693
const INNERMOST = 0;
@@ -173,7 +170,7 @@ pub fn debug_bound_var<T: std::fmt::Write>(
173170
}
174171
}
175172

176-
#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)]
173+
#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_NoContext)]
177174
#[rustc_pass_by_value]
178175
pub enum Variance {
179176
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
@@ -289,7 +286,7 @@ rustc_index::newtype_index! {
289286
/// declared, but a type name in a non-zero universe is a placeholder
290287
/// type -- an idealized representative of "types in general" that we
291288
/// use for checking generic functions.
292-
#[derive(HashStable_Generic)]
289+
#[derive(HashStable_NoContext)]
293290
#[debug_format = "U{}"]
294291
pub struct UniverseIndex {}
295292
}

compiler/rustc_type_ir/src/predicate_kind.rs

+4-94
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
21
use std::fmt;
32
use std::ops::ControlFlow;
43

54
use crate::fold::{FallibleTypeFolder, TypeFoldable};
65
use crate::visit::{TypeVisitable, TypeVisitor};
7-
use crate::{HashStableContext, Interner};
6+
use crate::Interner;
87

98
/// A clause is something that can appear in where bounds or be inferred
109
/// by implied bounds.
1110
#[derive(derivative::Derivative)]
1211
#[derivative(Clone(bound = ""), Hash(bound = ""))]
13-
#[derive(TyEncodable, TyDecodable)]
12+
#[derive(TyEncodable, TyDecodable, HashStable_NoContext)]
1413
pub enum ClauseKind<I: Interner> {
1514
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
1615
/// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -67,45 +66,6 @@ impl<I: Interner> PartialEq for ClauseKind<I> {
6766

6867
impl<I: Interner> Eq for ClauseKind<I> {}
6968

70-
fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> usize {
71-
match value {
72-
ClauseKind::Trait(_) => 0,
73-
ClauseKind::RegionOutlives(_) => 1,
74-
ClauseKind::TypeOutlives(_) => 2,
75-
ClauseKind::Projection(_) => 3,
76-
ClauseKind::ConstArgHasType(_, _) => 4,
77-
ClauseKind::WellFormed(_) => 5,
78-
ClauseKind::ConstEvaluatable(_) => 6,
79-
}
80-
}
81-
82-
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ClauseKind<I>
83-
where
84-
I::Ty: HashStable<CTX>,
85-
I::Const: HashStable<CTX>,
86-
I::GenericArg: HashStable<CTX>,
87-
I::TraitPredicate: HashStable<CTX>,
88-
I::ProjectionPredicate: HashStable<CTX>,
89-
I::TypeOutlivesPredicate: HashStable<CTX>,
90-
I::RegionOutlivesPredicate: HashStable<CTX>,
91-
{
92-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
93-
clause_kind_discriminant(self).hash_stable(hcx, hasher);
94-
match self {
95-
ClauseKind::Trait(p) => p.hash_stable(hcx, hasher),
96-
ClauseKind::RegionOutlives(p) => p.hash_stable(hcx, hasher),
97-
ClauseKind::TypeOutlives(p) => p.hash_stable(hcx, hasher),
98-
ClauseKind::Projection(p) => p.hash_stable(hcx, hasher),
99-
ClauseKind::ConstArgHasType(c, t) => {
100-
c.hash_stable(hcx, hasher);
101-
t.hash_stable(hcx, hasher);
102-
}
103-
ClauseKind::WellFormed(t) => t.hash_stable(hcx, hasher),
104-
ClauseKind::ConstEvaluatable(c) => c.hash_stable(hcx, hasher),
105-
}
106-
}
107-
}
108-
10969
impl<I: Interner> TypeFoldable<I> for ClauseKind<I>
11070
where
11171
I::Ty: TypeFoldable<I>,
@@ -161,7 +121,7 @@ where
161121

162122
#[derive(derivative::Derivative)]
163123
#[derivative(Clone(bound = ""), Hash(bound = ""))]
164-
#[derive(TyEncodable, TyDecodable)]
124+
#[derive(TyEncodable, TyDecodable, HashStable_NoContext)]
165125
pub enum PredicateKind<I: Interner> {
166126
/// Prove a clause
167127
Clause(ClauseKind<I>),
@@ -239,56 +199,6 @@ impl<I: Interner> PartialEq for PredicateKind<I> {
239199

240200
impl<I: Interner> Eq for PredicateKind<I> {}
241201

242-
fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> usize {
243-
match value {
244-
PredicateKind::Clause(_) => 0,
245-
PredicateKind::ObjectSafe(_) => 1,
246-
PredicateKind::ClosureKind(_, _, _) => 2,
247-
PredicateKind::Subtype(_) => 3,
248-
PredicateKind::Coerce(_) => 4,
249-
PredicateKind::ConstEquate(_, _) => 5,
250-
PredicateKind::Ambiguous => 6,
251-
PredicateKind::AliasRelate(_, _, _) => 7,
252-
}
253-
}
254-
255-
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for PredicateKind<I>
256-
where
257-
I::DefId: HashStable<CTX>,
258-
I::Const: HashStable<CTX>,
259-
I::GenericArgs: HashStable<CTX>,
260-
I::Term: HashStable<CTX>,
261-
I::CoercePredicate: HashStable<CTX>,
262-
I::SubtypePredicate: HashStable<CTX>,
263-
I::ClosureKind: HashStable<CTX>,
264-
ClauseKind<I>: HashStable<CTX>,
265-
{
266-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
267-
predicate_kind_discriminant(self).hash_stable(hcx, hasher);
268-
match self {
269-
PredicateKind::Clause(p) => p.hash_stable(hcx, hasher),
270-
PredicateKind::ObjectSafe(d) => d.hash_stable(hcx, hasher),
271-
PredicateKind::ClosureKind(d, g, k) => {
272-
d.hash_stable(hcx, hasher);
273-
g.hash_stable(hcx, hasher);
274-
k.hash_stable(hcx, hasher);
275-
}
276-
PredicateKind::Subtype(p) => p.hash_stable(hcx, hasher),
277-
PredicateKind::Coerce(p) => p.hash_stable(hcx, hasher),
278-
PredicateKind::ConstEquate(c1, c2) => {
279-
c1.hash_stable(hcx, hasher);
280-
c2.hash_stable(hcx, hasher);
281-
}
282-
PredicateKind::Ambiguous => {}
283-
PredicateKind::AliasRelate(t1, t2, r) => {
284-
t1.hash_stable(hcx, hasher);
285-
t2.hash_stable(hcx, hasher);
286-
r.hash_stable(hcx, hasher);
287-
}
288-
}
289-
}
290-
}
291-
292202
impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
293203
where
294204
I::DefId: TypeFoldable<I>,
@@ -361,7 +271,7 @@ where
361271
}
362272

363273
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
364-
#[derive(HashStable_Generic, Encodable, Decodable)]
274+
#[derive(HashStable_NoContext, Encodable, Decodable)]
365275
pub enum AliasRelationDirection {
366276
Equate,
367277
Subtype,

compiler/rustc_type_ir/src/region_kind.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
use rustc_data_structures::stable_hasher::HashStable;
2-
use rustc_data_structures::stable_hasher::StableHasher;
1+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
32
use std::fmt;
43

5-
use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
4+
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
65

76
use self::RegionKind::*;
87

@@ -262,7 +261,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
262261
}
263262

264263
// This is not a derived impl because a derive would require `I: HashStable`
265-
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
264+
impl<CTX, I: Interner> HashStable<CTX> for RegionKind<I>
266265
where
267266
I::EarlyParamRegion: HashStable<CTX>,
268267
I::BoundRegion: HashStable<CTX>,

0 commit comments

Comments
 (0)