]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/impls_ty.rs
Rollup merge of #97210 - Milo123459:clippy-args, r=jyn514
[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 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;
14
15 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
16 where
17     T: HashStable<StableHashingContext<'a>>,
18 {
19     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
20         thread_local! {
21             static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> =
22                 RefCell::new(Default::default());
23         }
24
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) {
28                 return hash;
29             }
30
31             let mut hasher = StableHasher::new();
32             (&self[..]).hash_stable(hcx, &mut hasher);
33
34             let hash: Fingerprint = hasher.finish();
35             cache.borrow_mut().insert(key, hash);
36             hash
37         });
38
39         hash.hash_stable(hcx, hasher);
40     }
41 }
42
43 impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
44 where
45     T: HashStable<StableHashingContext<'a>>,
46 {
47     type KeyType = Fingerprint;
48
49     #[inline]
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);
54         hasher.finish()
55     }
56 }
57
58 impl<'a> ToStableHashKey<StableHashingContext<'a>> for SimplifiedType {
59     type KeyType = Fingerprint;
60
61     #[inline]
62     fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
63         let mut hasher = StableHasher::new();
64         let mut hcx: StableHashingContext<'a> = hcx.clone();
65         self.hash_stable(&mut hcx, &mut hasher);
66         hasher.finish()
67     }
68 }
69
70 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
71     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
72         self.unpack().hash_stable(hcx, hasher);
73     }
74 }
75
76 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
77     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
78         match self {
79             // WARNING: We dedup cache the `HashStable` results for `List`
80             // while ignoring types and freely transmute
81             // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
82             // See `fn intern_type_list` for more details.
83             //
84             // We therefore hash types without adding a hash for their discriminant.
85             //
86             // In order to make it very unlikely for the sequence of bytes being hashed for
87             // a `GenericArgKind::Type` to be the same as the sequence of bytes being
88             // hashed for one of the other variants, we hash some very high number instead
89             // of their actual discriminant since `TyKind` should never start with anything
90             // that high.
91             ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
92             ty::subst::GenericArgKind::Const(ct) => {
93                 0xF3u8.hash_stable(hcx, hasher);
94                 ct.hash_stable(hcx, hasher);
95             }
96             ty::subst::GenericArgKind::Lifetime(lt) => {
97                 0xF5u8.hash_stable(hcx, hasher);
98                 lt.hash_stable(hcx, hasher);
99             }
100         }
101     }
102 }
103
104 impl<'a> HashStable<StableHashingContext<'a>> for ty::EarlyBoundRegion {
105     #[inline]
106     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
107         self.def_id.hash_stable(hcx, hasher);
108         self.index.hash_stable(hcx, hasher);
109         self.name.hash_stable(hcx, hasher);
110     }
111 }
112
113 impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
114     #[inline]
115     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
116         self.index().hash_stable(hcx, hasher);
117     }
118 }
119
120 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::ConstVid<'tcx> {
121     #[inline]
122     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
123         self.index.hash_stable(hcx, hasher);
124     }
125 }
126
127 impl<'tcx> HashStable<StableHashingContext<'tcx>> for ty::BoundVar {
128     #[inline]
129     fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
130         self.index().hash_stable(hcx, hasher);
131     }
132 }
133
134 impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<'tcx, T>
135 where
136     T: HashStable<StableHashingContext<'a>>,
137 {
138     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
139         self.as_ref().skip_binder().hash_stable(hcx, hasher);
140         self.bound_vars().hash_stable(hcx, hasher);
141     }
142 }
143
144 // AllocIds get resolved to whatever they point to (to be stable)
145 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
146     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
147         ty::tls::with_opt(|tcx| {
148             trace!("hashing {:?}", *self);
149             let tcx = tcx.expect("can't hash AllocIds during hir lowering");
150             tcx.get_global_alloc(*self).hash_stable(hcx, hasher);
151         });
152     }
153 }
154
155 // `Relocations` with default type parameters is a sorted map.
156 impl<'a, Tag> HashStable<StableHashingContext<'a>> for mir::interpret::Relocations<Tag>
157 where
158     Tag: HashStable<StableHashingContext<'a>>,
159 {
160     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
161         self.len().hash_stable(hcx, hasher);
162         for reloc in self.iter() {
163             reloc.hash_stable(hcx, hasher);
164         }
165     }
166 }
167
168 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
169     type KeyType = region::Scope;
170
171     #[inline]
172     fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
173         *self
174     }
175 }