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 rustc_data_structures::fingerprint::Fingerprint;
8 use rustc_data_structures::fx::FxHashMap;
9 use rustc_data_structures::stable_hasher::HashingControls;
10 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
11 use rustc_query_system::ich::StableHashingContext;
12 use std::cell::RefCell;
15 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
17 T: HashStable<StableHashingContext<'a>>,
19 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
21 static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> =
22 RefCell::new(Default::default());
25 let hash = CACHE.with(|cache| {
26 let key = (self.as_ptr() as usize, self.len(), hcx.hashing_controls());
27 if let Some(&hash) = cache.borrow().get(&key) {
31 let mut hasher = StableHasher::new();
32 (&self[..]).hash_stable(hcx, &mut hasher);
34 let hash: Fingerprint = hasher.finish();
35 cache.borrow_mut().insert(key, hash);
39 hash.hash_stable(hcx, hasher);
43 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
45 T: HashStable<StableHashingContext<'a>>,
47 type KeyType = Fingerprint;
50 fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
51 let mut hasher = StableHasher::new();
52 let mut hcx: StableHashingContext<'a> = hcx.clone();
53 self.hash_stable(&mut hcx, &mut hasher);
58 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
59 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
60 self.unpack().hash_stable(hcx, hasher);
64 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
65 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
66 mem::discriminant(self).hash_stable(hcx, hasher);
68 ty::ReErased | ty::ReStatic => {
69 // No variant fields to hash for these ...
71 ty::ReEmpty(universe) => {
72 universe.hash_stable(hcx, hasher);
74 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
75 db.hash_stable(hcx, hasher);
76 i.hash_stable(hcx, hasher);
78 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => {
79 db.hash_stable(hcx, hasher);
80 def_id.hash_stable(hcx, hasher);
81 name.hash_stable(hcx, hasher);
83 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
84 db.hash_stable(hcx, hasher);
86 ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
87 def_id.hash_stable(hcx, hasher);
88 index.hash_stable(hcx, hasher);
89 name.hash_stable(hcx, hasher);
91 ty::ReFree(ref free_region) => {
92 free_region.hash_stable(hcx, hasher);
94 ty::RePlaceholder(p) => {
95 p.hash_stable(hcx, hasher);
98 bug!("StableHasher: unexpected region {:?}", *self)
104 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
106 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
107 self.index().hash_stable(hcx, hasher);
111 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> {
113 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
114 self.index.hash_stable(hcx, hasher);
118 impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar {
120 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
121 self.index().hash_stable(hcx, hasher);
125 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<'tcx, T>
127 T: HashStable<StableHashingContext<'a>>,
129 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
130 self.as_ref().skip_binder().hash_stable(hcx, hasher);
131 self.bound_vars().hash_stable(hcx, hasher);
135 // AllocIds get resolved to whatever they point to (to be stable)
136 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
137 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
138 ty::tls::with_opt(|tcx| {
139 trace!("hashing {:?}", *self);
140 let tcx = tcx.expect("can't hash AllocIds during hir lowering");
141 tcx.get_global_alloc(*self).hash_stable(hcx, hasher);
146 // `Relocations` with default type parameters is a sorted map.
147 impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag>
149 Tag: HashStable<StableHashingContext<'a>>,
151 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
152 self.len().hash_stable(hcx, hasher);
153 for reloc in self.iter() {
154 reloc.hash_stable(hcx, hasher);
159 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
160 type KeyType = region::Scope;
163 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {