Skip to content

Commit b94f779

Browse files
Add HashStable_NoContext to simplify HashStable implementations in rustc_type_ir
1 parent f81d6f0 commit b94f779

File tree

10 files changed

+75
-285
lines changed

10 files changed

+75
-285
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
@@ -81,6 +81,50 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma
8181
)
8282
}
8383

84+
pub fn hash_stable_no_context_derive(
85+
mut s: synstructure::Structure<'_>,
86+
) -> proc_macro2::TokenStream {
87+
let generic: syn::GenericParam = parse_quote!(__CTX);
88+
s.add_bounds(synstructure::AddBounds::Fields);
89+
s.add_impl_generic(generic);
90+
let body = s.each(|bi| {
91+
let attrs = parse_attributes(bi.ast());
92+
if attrs.ignore {
93+
quote! {}
94+
} else if let Some(project) = attrs.project {
95+
quote! {
96+
(&#bi.#project).hash_stable(__hcx, __hasher);
97+
}
98+
} else {
99+
quote! {
100+
#bi.hash_stable(__hcx, __hasher);
101+
}
102+
}
103+
});
104+
105+
let discriminant = match s.ast().data {
106+
syn::Data::Enum(_) => quote! {
107+
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
108+
},
109+
syn::Data::Struct(_) => quote! {},
110+
syn::Data::Union(_) => panic!("cannot derive on union"),
111+
};
112+
113+
s.bound_impl(
114+
quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>),
115+
quote! {
116+
#[inline]
117+
fn hash_stable(
118+
&self,
119+
__hcx: &mut __CTX,
120+
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
121+
#discriminant
122+
match *self { #body }
123+
}
124+
},
125+
)
126+
}
127+
84128
pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
85129
let generic: syn::GenericParam = parse_quote!('__ctx);
86130
s.add_bounds(synstructure::AddBounds::Generics);

compiler/rustc_macros/src/lib.rs

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

7178
decl_derive!([Decodable] => serialize::decodable_derive);
7279
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-13
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ use std::fmt;
22
use std::hash::Hash;
33
use std::ops::ControlFlow;
44

5-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
65
use rustc_serialize::{Decodable, Encodable};
76

87
use crate::fold::{FallibleTypeFolder, TypeFoldable};
98
use crate::visit::{TypeVisitable, TypeVisitor};
109
use crate::TyDecoder;
11-
use crate::{HashStableContext, Interner, TyEncoder, UniverseIndex};
10+
use crate::{Interner, TyEncoder, UniverseIndex};
1211

1312
/// A "canonicalized" type `V` is one where all free inference
1413
/// variables have been rewritten to "canonical vars". These are
1514
/// numbered starting from 0 in order of first appearance.
1615
#[derive(derivative::Derivative)]
1716
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
17+
#[derive(HashStable_NoContext)]
1818
pub struct Canonical<I: Interner, V> {
1919
pub value: V,
2020
pub max_universe: UniverseIndex,
@@ -61,17 +61,6 @@ impl<I: Interner, V> Canonical<I, V> {
6161
}
6262
}
6363

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

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

compiler/rustc_type_ir/src/const_kind.rs

+2-33
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
use rustc_data_structures::stable_hasher::HashStable;
2-
use rustc_data_structures::stable_hasher::StableHasher;
31
use rustc_serialize::{Decodable, Decoder, Encodable};
42
use std::fmt;
53

64
use crate::{
7-
DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder,
8-
TyEncoder, WithInfcx,
5+
DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, TyDecoder, TyEncoder, WithInfcx,
96
};
107

118
use self::ConstKind::*;
@@ -20,6 +17,7 @@ use self::ConstKind::*;
2017
Ord = "feature_allow_slow_enum",
2118
Hash(bound = "")
2219
)]
20+
#[derive(HashStable_NoContext)]
2321
pub enum ConstKind<I: Interner> {
2422
/// A const generic parameter.
2523
Param(I::ParamConst),
@@ -63,35 +61,6 @@ const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
6361
}
6462
}
6563

66-
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
67-
where
68-
I::ParamConst: HashStable<CTX>,
69-
I::InferConst: HashStable<CTX>,
70-
I::BoundConst: HashStable<CTX>,
71-
I::PlaceholderConst: HashStable<CTX>,
72-
I::AliasConst: HashStable<CTX>,
73-
I::ValueConst: HashStable<CTX>,
74-
I::ErrorGuaranteed: HashStable<CTX>,
75-
I::ExprConst: HashStable<CTX>,
76-
{
77-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
78-
const_kind_discriminant(self).hash_stable(hcx, hasher);
79-
match self {
80-
Param(p) => p.hash_stable(hcx, hasher),
81-
Infer(i) => i.hash_stable(hcx, hasher),
82-
Bound(d, b) => {
83-
d.hash_stable(hcx, hasher);
84-
b.hash_stable(hcx, hasher);
85-
}
86-
Placeholder(p) => p.hash_stable(hcx, hasher),
87-
Unevaluated(u) => u.hash_stable(hcx, hasher),
88-
Value(v) => v.hash_stable(hcx, hasher),
89-
Error(e) => e.hash_stable(hcx, hasher),
90-
Expr(e) => e.hash_stable(hcx, hasher),
91-
}
92-
}
93-
}
94-
9564
impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
9665
where
9766
I::ParamConst: Decodable<D>,

compiler/rustc_type_ir/src/lib.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ pub use region_kind::*;
4545
pub use ty_info::*;
4646
pub use ty_kind::*;
4747

48-
/// Needed so we can use #[derive(HashStable_Generic)]
49-
pub trait HashStableContext {}
50-
5148
rustc_index::newtype_index! {
5249
/// A [De Bruijn index][dbi] is a standard means of representing
5350
/// regions (and perhaps later types) in a higher-ranked setting. In
@@ -88,7 +85,7 @@ rustc_index::newtype_index! {
8885
/// is the outer fn.
8986
///
9087
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
91-
#[derive(HashStable_Generic)]
88+
#[derive(HashStable_NoContext)]
9289
#[debug_format = "DebruijnIndex({})"]
9390
pub struct DebruijnIndex {
9491
const INNERMOST = 0;
@@ -171,7 +168,7 @@ pub fn debug_bound_var<T: std::fmt::Write>(
171168
}
172169
}
173170

174-
#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)]
171+
#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_NoContext)]
175172
#[rustc_pass_by_value]
176173
pub enum Variance {
177174
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
@@ -287,7 +284,7 @@ rustc_index::newtype_index! {
287284
/// declared, but a type name in a non-zero universe is a placeholder
288285
/// type -- an idealized representative of "types in general" that we
289286
/// use for checking generic functions.
290-
#[derive(HashStable_Generic)]
287+
#[derive(HashStable_NoContext)]
291288
#[debug_format = "U{}"]
292289
pub struct UniverseIndex {}
293290
}

compiler/rustc_type_ir/src/predicate_kind.rs

+4-67
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
21
use rustc_serialize::Decoder;
32
use rustc_serialize::{Decodable, Encodable};
43
use std::fmt;
54
use std::ops::ControlFlow;
65

76
use crate::fold::{FallibleTypeFolder, TypeFoldable};
87
use crate::visit::{TypeVisitable, TypeVisitor};
9-
use crate::{HashStableContext, Interner};
8+
use crate::Interner;
109
use crate::{TyDecoder, TyEncoder};
1110

1211
/// A clause is something that can appear in where bounds or be inferred
1312
/// by implied bounds.
1413
#[derive(derivative::Derivative)]
1514
#[derivative(Clone(bound = ""), Hash(bound = ""))]
15+
#[derive(HashStable_NoContext)]
1616
pub enum ClauseKind<I: Interner> {
1717
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
1818
/// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -81,33 +81,6 @@ fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> usize {
8181
}
8282
}
8383

84-
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ClauseKind<I>
85-
where
86-
I::Ty: HashStable<CTX>,
87-
I::Const: HashStable<CTX>,
88-
I::GenericArg: HashStable<CTX>,
89-
I::TraitPredicate: HashStable<CTX>,
90-
I::ProjectionPredicate: HashStable<CTX>,
91-
I::TypeOutlivesPredicate: HashStable<CTX>,
92-
I::RegionOutlivesPredicate: HashStable<CTX>,
93-
{
94-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
95-
clause_kind_discriminant(self).hash_stable(hcx, hasher);
96-
match self {
97-
ClauseKind::Trait(p) => p.hash_stable(hcx, hasher),
98-
ClauseKind::RegionOutlives(p) => p.hash_stable(hcx, hasher),
99-
ClauseKind::TypeOutlives(p) => p.hash_stable(hcx, hasher),
100-
ClauseKind::Projection(p) => p.hash_stable(hcx, hasher),
101-
ClauseKind::ConstArgHasType(c, t) => {
102-
c.hash_stable(hcx, hasher);
103-
t.hash_stable(hcx, hasher);
104-
}
105-
ClauseKind::WellFormed(t) => t.hash_stable(hcx, hasher),
106-
ClauseKind::ConstEvaluatable(c) => c.hash_stable(hcx, hasher),
107-
}
108-
}
109-
}
110-
11184
impl<I: Interner> TypeFoldable<I> for ClauseKind<I>
11285
where
11386
I::Ty: TypeFoldable<I>,
@@ -220,6 +193,7 @@ where
220193

221194
#[derive(derivative::Derivative)]
222195
#[derivative(Clone(bound = ""), Hash(bound = ""))]
196+
#[derive(HashStable_NoContext)]
223197
pub enum PredicateKind<I: Interner> {
224198
/// Prove a clause
225199
Clause(ClauseKind<I>),
@@ -310,43 +284,6 @@ fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> usize {
310284
}
311285
}
312286

313-
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for PredicateKind<I>
314-
where
315-
I::DefId: HashStable<CTX>,
316-
I::Const: HashStable<CTX>,
317-
I::GenericArgs: HashStable<CTX>,
318-
I::Term: HashStable<CTX>,
319-
I::CoercePredicate: HashStable<CTX>,
320-
I::SubtypePredicate: HashStable<CTX>,
321-
I::ClosureKind: HashStable<CTX>,
322-
ClauseKind<I>: HashStable<CTX>,
323-
{
324-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
325-
predicate_kind_discriminant(self).hash_stable(hcx, hasher);
326-
match self {
327-
PredicateKind::Clause(p) => p.hash_stable(hcx, hasher),
328-
PredicateKind::ObjectSafe(d) => d.hash_stable(hcx, hasher),
329-
PredicateKind::ClosureKind(d, g, k) => {
330-
d.hash_stable(hcx, hasher);
331-
g.hash_stable(hcx, hasher);
332-
k.hash_stable(hcx, hasher);
333-
}
334-
PredicateKind::Subtype(p) => p.hash_stable(hcx, hasher),
335-
PredicateKind::Coerce(p) => p.hash_stable(hcx, hasher),
336-
PredicateKind::ConstEquate(c1, c2) => {
337-
c1.hash_stable(hcx, hasher);
338-
c2.hash_stable(hcx, hasher);
339-
}
340-
PredicateKind::Ambiguous => {}
341-
PredicateKind::AliasRelate(t1, t2, r) => {
342-
t1.hash_stable(hcx, hasher);
343-
t2.hash_stable(hcx, hasher);
344-
r.hash_stable(hcx, hasher);
345-
}
346-
}
347-
}
348-
}
349-
350287
impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
351288
where
352289
I::DefId: TypeFoldable<I>,
@@ -496,7 +433,7 @@ where
496433
}
497434

498435
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
499-
#[derive(HashStable_Generic, Encodable, Decodable)]
436+
#[derive(HashStable_NoContext, Encodable, Decodable)]
500437
pub enum AliasRelationDirection {
501438
Equate,
502439
Subtype,

compiler/rustc_type_ir/src/region_kind.rs

+2-40
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
use rustc_data_structures::stable_hasher::HashStable;
2-
use rustc_data_structures::stable_hasher::StableHasher;
31
use rustc_serialize::{Decodable, Decoder, Encodable};
42
use std::fmt;
53

64
use crate::{
7-
DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder,
8-
TyEncoder, WithInfcx,
5+
DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, TyDecoder, TyEncoder, WithInfcx,
96
};
107

118
use self::RegionKind::*;
@@ -125,6 +122,7 @@ use self::RegionKind::*;
125122
Ord = "feature_allow_slow_enum",
126123
Hash(bound = "")
127124
)]
125+
#[derive(HashStable_NoContext)]
128126
pub enum RegionKind<I: Interner> {
129127
/// Region bound in a type or fn declaration which will be
130128
/// substituted 'early' -- that is, at the same time when type
@@ -310,39 +308,3 @@ where
310308
}
311309
}
312310
}
313-
314-
// This is not a derived impl because a derive would require `I: HashStable`
315-
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
316-
where
317-
I::EarlyBoundRegion: HashStable<CTX>,
318-
I::BoundRegion: HashStable<CTX>,
319-
I::FreeRegion: HashStable<CTX>,
320-
I::InferRegion: HashStable<CTX>,
321-
I::PlaceholderRegion: HashStable<CTX>,
322-
{
323-
#[inline]
324-
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
325-
std::mem::discriminant(self).hash_stable(hcx, hasher);
326-
match self {
327-
ReErased | ReStatic | ReError(_) => {
328-
// No variant fields to hash for these ...
329-
}
330-
ReLateBound(d, r) => {
331-
d.hash_stable(hcx, hasher);
332-
r.hash_stable(hcx, hasher);
333-
}
334-
ReEarlyBound(r) => {
335-
r.hash_stable(hcx, hasher);
336-
}
337-
ReFree(r) => {
338-
r.hash_stable(hcx, hasher);
339-
}
340-
RePlaceholder(r) => {
341-
r.hash_stable(hcx, hasher);
342-
}
343-
ReVar(_) => {
344-
panic!("region variables should not be hashed: {self:?}")
345-
}
346-
}
347-
}
348-
}

0 commit comments

Comments
 (0)