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::{HashStable, StableHasher, ToStableHashKey};
10 use rustc_query_system::ich::StableHashingContext;
11 use std::cell::RefCell;
14 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
16 T: HashStable<StableHashingContext<'a>>,
18 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
20 static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
21 RefCell::new(Default::default());
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) {
30 let mut hasher = StableHasher::new();
31 (&self[..]).hash_stable(hcx, &mut hasher);
33 let hash: Fingerprint = hasher.finish();
34 cache.borrow_mut().insert(key, hash);
38 hash.hash_stable(hcx, hasher);
42 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
44 T: HashStable<StableHashingContext<'a>>,
46 type KeyType = Fingerprint;
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);
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);
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);
67 ty::ReErased | ty::ReStatic => {
68 // No variant fields to hash for these ...
70 ty::ReEmpty(universe) => {
71 universe.hash_stable(hcx, hasher);
73 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
74 db.hash_stable(hcx, hasher);
75 i.hash_stable(hcx, hasher);
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);
82 ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
83 db.hash_stable(hcx, hasher);
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);
90 ty::ReFree(ref free_region) => {
91 free_region.hash_stable(hcx, hasher);
93 ty::RePlaceholder(p) => {
94 p.hash_stable(hcx, hasher);
97 bug!("StableHasher: unexpected region {:?}", *self)
103 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
105 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
106 self.index().hash_stable(hcx, hasher);
110 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> {
112 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
113 self.index.hash_stable(hcx, hasher);
117 impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar {
119 fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
120 self.index().hash_stable(hcx, hasher);
124 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<'tcx, T>
126 T: HashStable<StableHashingContext<'a>>,
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);
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);
145 // `Relocations` with default type parameters is a sorted map.
146 impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag>
148 Tag: HashStable<StableHashingContext<'a>>,
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);
158 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
159 type KeyType = region::Scope;
162 fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {