1 //! This module contains `HashStable` implementations for various data types
2 //! from `rustc_middle::ty` in no particular order.
4 use crate::middle
::region
;
7 use crate::ty
::fast_reject
::SimplifiedType
;
8 use rustc_data_structures
::fingerprint
::Fingerprint
;
9 use rustc_data_structures
::fx
::FxHashMap
;
10 use rustc_data_structures
::stable_hasher
::HashingControls
;
11 use rustc_data_structures
::stable_hasher
::{HashStable, StableHasher, ToStableHashKey}
;
12 use rustc_query_system
::ich
::StableHashingContext
;
13 use std
::cell
::RefCell
;
16 impl<'a
, 'tcx
, T
> HashStable
<StableHashingContext
<'a
>> for &'tcx ty
::List
<T
>
18 T
: HashStable
<StableHashingContext
<'a
>>,
20 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
22 static CACHE
: RefCell
<FxHashMap
<(usize, usize, HashingControls
), Fingerprint
>> =
23 RefCell
::new(Default
::default());
26 let hash
= CACHE
.with(|cache
| {
27 let key
= (self.as_ptr() as usize, self.len(), hcx
.hashing_controls());
28 if let Some(&hash
) = cache
.borrow().get(&key
) {
32 let mut hasher
= StableHasher
::new();
33 (&self[..]).hash_stable(hcx
, &mut hasher
);
35 let hash
: Fingerprint
= hasher
.finish();
36 cache
.borrow_mut().insert(key
, hash
);
40 hash
.hash_stable(hcx
, hasher
);
44 impl<'a
, 'tcx
, T
> ToStableHashKey
<StableHashingContext
<'a
>> for &'tcx ty
::List
<T
>
46 T
: HashStable
<StableHashingContext
<'a
>>,
48 type KeyType
= Fingerprint
;
51 fn to_stable_hash_key(&self, hcx
: &StableHashingContext
<'a
>) -> Fingerprint
{
52 let mut hasher
= StableHasher
::new();
53 let mut hcx
: StableHashingContext
<'a
> = hcx
.clone();
54 self.hash_stable(&mut hcx
, &mut hasher
);
59 impl<'a
> ToStableHashKey
<StableHashingContext
<'a
>> for SimplifiedType
{
60 type KeyType
= Fingerprint
;
63 fn to_stable_hash_key(&self, hcx
: &StableHashingContext
<'a
>) -> Fingerprint
{
64 let mut hasher
= StableHasher
::new();
65 let mut hcx
: StableHashingContext
<'a
> = hcx
.clone();
66 self.hash_stable(&mut hcx
, &mut hasher
);
71 impl<'a
, 'tcx
> HashStable
<StableHashingContext
<'a
>> for ty
::subst
::GenericArg
<'tcx
> {
72 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
73 self.unpack().hash_stable(hcx
, hasher
);
77 impl<'a
, 'tcx
> HashStable
<StableHashingContext
<'a
>> for ty
::subst
::GenericArgKind
<'tcx
> {
78 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
80 // WARNING: We dedup cache the `HashStable` results for `List`
81 // while ignoring types and freely transmute
82 // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
83 // See `fn intern_type_list` for more details.
85 // We therefore hash types without adding a hash for their discriminant.
87 // In order to make it very unlikely for the sequence of bytes being hashed for
88 // a `GenericArgKind::Type` to be the same as the sequence of bytes being
89 // hashed for one of the other variants, we hash a `0xFF` byte before hashing
90 // their discriminant (since the discriminant of `TyKind` is unlikely to ever start
92 ty
::subst
::GenericArgKind
::Type(ty
) => ty
.hash_stable(hcx
, hasher
),
93 ty
::subst
::GenericArgKind
::Const(ct
) => {
94 0xFFu8.hash_stable(hcx
, hasher
);
95 mem
::discriminant(self).hash_stable(hcx
, hasher
);
96 ct
.hash_stable(hcx
, hasher
);
98 ty
::subst
::GenericArgKind
::Lifetime(lt
) => {
99 0xFFu8.hash_stable(hcx
, hasher
);
100 mem
::discriminant(self).hash_stable(hcx
, hasher
);
101 lt
.hash_stable(hcx
, hasher
);
107 impl<'a
> HashStable
<StableHashingContext
<'a
>> for ty
::RegionKind
{
108 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
109 mem
::discriminant(self).hash_stable(hcx
, hasher
);
111 ty
::ReErased
| ty
::ReStatic
=> {
112 // No variant fields to hash for these ...
114 ty
::ReEmpty(universe
) => {
115 universe
.hash_stable(hcx
, hasher
);
117 ty
::ReLateBound(db
, ty
::BoundRegion { kind: ty::BrAnon(i), .. }
) => {
118 db
.hash_stable(hcx
, hasher
);
119 i
.hash_stable(hcx
, hasher
);
121 ty
::ReLateBound(db
, ty
::BoundRegion { kind: ty::BrNamed(def_id, name), .. }
) => {
122 db
.hash_stable(hcx
, hasher
);
123 def_id
.hash_stable(hcx
, hasher
);
124 name
.hash_stable(hcx
, hasher
);
126 ty
::ReLateBound(db
, ty
::BoundRegion { kind: ty::BrEnv, .. }
) => {
127 db
.hash_stable(hcx
, hasher
);
129 ty
::ReEarlyBound(ty
::EarlyBoundRegion { def_id, index, name }
) => {
130 def_id
.hash_stable(hcx
, hasher
);
131 index
.hash_stable(hcx
, hasher
);
132 name
.hash_stable(hcx
, hasher
);
134 ty
::ReFree(ref free_region
) => {
135 free_region
.hash_stable(hcx
, hasher
);
137 ty
::RePlaceholder(p
) => {
138 p
.hash_stable(hcx
, hasher
);
141 bug
!("StableHasher: unexpected region {:?}", *self)
147 impl<'a
> HashStable
<StableHashingContext
<'a
>> for ty
::RegionVid
{
149 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
150 self.index().hash_stable(hcx
, hasher
);
154 impl<'a
, 'tcx
> HashStable
<StableHashingContext
<'a
>> for ty
::ConstVid
<'tcx
> {
156 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
157 self.index
.hash_stable(hcx
, hasher
);
161 impl<'tcx
> HashStable
<StableHashingContext
<'tcx
>> for ty
::BoundVar
{
163 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'tcx
>, hasher
: &mut StableHasher
) {
164 self.index().hash_stable(hcx
, hasher
);
168 impl<'a
, 'tcx
, T
> HashStable
<StableHashingContext
<'a
>> for ty
::Binder
<'tcx
, T
>
170 T
: HashStable
<StableHashingContext
<'a
>>,
172 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
173 self.as_ref().skip_binder().hash_stable(hcx
, hasher
);
174 self.bound_vars().hash_stable(hcx
, hasher
);
178 // AllocIds get resolved to whatever they point to (to be stable)
179 impl<'a
> HashStable
<StableHashingContext
<'a
>> for mir
::interpret
::AllocId
{
180 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
181 ty
::tls
::with_opt(|tcx
| {
182 trace
!("hashing {:?}", *self);
183 let tcx
= tcx
.expect("can't hash AllocIds during hir lowering");
184 tcx
.get_global_alloc(*self).hash_stable(hcx
, hasher
);
189 // `Relocations` with default type parameters is a sorted map.
190 impl<'a
, Tag
> HashStable
<StableHashingContext
<'a
>> for mir
::interpret
::Relocations
<Tag
>
192 Tag
: HashStable
<StableHashingContext
<'a
>>,
194 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
195 self.len().hash_stable(hcx
, hasher
);
196 for reloc
in self.iter() {
197 reloc
.hash_stable(hcx
, hasher
);
202 impl<'a
> ToStableHashKey
<StableHashingContext
<'a
>> for region
::Scope
{
203 type KeyType
= region
::Scope
;
206 fn to_stable_hash_key(&self, _
: &StableHashingContext
<'a
>) -> region
::Scope
{