]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/impls_ty.rs
Auto merge of #92130 - Kobzol:stable-hash-str, r=cjgillot
[rust.git] / compiler / rustc_middle / src / ty / impls_ty.rs
1 //! This module contains `HashStable` implementations for various data types
2 //! from `rustc_middle::ty` in no particular order.
3
4 use crate::middle::region;
5 use crate::mir;
6 use crate::ty;
7 use rustc_data_structures::fingerprint::Fingerprint;
8 use rustc_data_structures::fx::FxHashMap;
9 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
10 use rustc_query_system::ich::StableHashingContext;
11 use std::cell::RefCell;
12 use std::mem;
13
14 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
15 where
16     T: HashStable<StableHashingContext<'a>>,
17 {
18     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
19         thread_local! {
20             static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
21                 RefCell::new(Default::default());
22         }
23
24         let hash = CACHE.with(|cache| {
25             let key = (self.as_ptr() as usize, self.len());
26             if let Some(&hash) = cache.borrow().get(&key) {
27                 return hash;
28             }
29
30             let mut hasher = StableHasher::new();
31             (&self[..]).hash_stable(hcx, &mut hasher);
32
33             let hash: Fingerprint = hasher.finish();
34             cache.borrow_mut().insert(key, hash);
35             hash
36         });
37
38         hash.hash_stable(hcx, hasher);
39     }
40 }
41
42 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
43 where
44     T: HashStable<StableHashingContext<'a>>,
45 {
46     type KeyType = Fingerprint;
47
48     #[inline]
49     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
50         let mut hasher = StableHasher::new();
51         let mut hcx: StableHashingContext<'a> = hcx.clone();
52         self.hash_stable(&mut hcx, &mut hasher);
53         hasher.finish()
54     }
55 }
56
57 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
58     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
59         self.unpack().hash_stable(hcx, hasher);
60     }
61 }
62
63 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
64     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
65         mem::discriminant(self).hash_stable(hcx, hasher);
66         match *self {
67             ty::ReErased | ty::ReStatic => {
68                 // No variant fields to hash for these ...
69             }
70             ty::ReEmpty(universe) => {
71                 universe.hash_stable(hcx, hasher);
72             }
73             ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
74                 db.hash_stable(hcx, hasher);
75                 i.hash_stable(hcx, hasher);
76             }
77             ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => {
78                 db.hash_stable(hcx, hasher);
79                 def_id.hash_stable(hcx, hasher);
80                 name.hash_stable(hcx, hasher);
81             }
82             ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
83                 db.hash_stable(hcx, hasher);
84             }
85             ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
86                 def_id.hash_stable(hcx, hasher);
87                 index.hash_stable(hcx, hasher);
88                 name.hash_stable(hcx, hasher);
89             }
90             ty::ReFree(ref free_region) => {
91                 free_region.hash_stable(hcx, hasher);
92             }
93             ty::RePlaceholder(p) => {
94                 p.hash_stable(hcx, hasher);
95             }
96             ty::ReVar(..) => {
97                 bug!("StableHasher: unexpected region {:?}", *self)
98             }
99         }
100     }
101 }
102
103 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
104     #[inline]
105     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
106         self.index().hash_stable(hcx, hasher);
107     }
108 }
109
110 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> {
111     #[inline]
112     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
113         self.index.hash_stable(hcx, hasher);
114     }
115 }
116
117 impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar {
118     #[inline]
119     fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
120         self.index().hash_stable(hcx, hasher);
121     }
122 }
123
124 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<'tcx, T>
125 where
126     T: HashStable<StableHashingContext<'a>>,
127 {
128     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
129         self.as_ref().skip_binder().hash_stable(hcx, hasher);
130         self.bound_vars().hash_stable(hcx, hasher);
131     }
132 }
133
134 // AllocIds get resolved to whatever they point to (to be stable)
135 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
136     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
137         ty::tls::with_opt(|tcx| {
138             trace!("hashing {:?}", *self);
139             let tcx = tcx.expect("can't hash AllocIds during hir lowering");
140             tcx.get_global_alloc(*self).hash_stable(hcx, hasher);
141         });
142     }
143 }
144
145 // `Relocations` with default type parameters is a sorted map.
146 impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag>
147 where
148     Tag: HashStable<StableHashingContext<'a>>,
149 {
150     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
151         self.len().hash_stable(hcx, hasher);
152         for reloc in self.iter() {
153             reloc.hash_stable(hcx, hasher);
154         }
155     }
156 }
157
158 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
159     type KeyType = region::Scope;
160
161     #[inline]
162     fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
163         *self
164     }
165 }