]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | use crate::ich; |
9fa01778 | 2 | use crate::middle::cstore::CrateStore; |
dfeec247 | 3 | use crate::ty::{fast_reject, TyCtxt}; |
cc61c64b | 4 | |
3dfed10e | 5 | use rustc_ast as ast; |
dfeec247 | 6 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
ba9703b0 | 7 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
60c5eb7d | 8 | use rustc_data_structures::sync::Lrc; |
dfeec247 | 9 | use rustc_hir as hir; |
ba9703b0 XL |
10 | use rustc_hir::def_id::{DefId, LocalDefId}; |
11 | use rustc_hir::definitions::{DefPathHash, Definitions}; | |
12 | use rustc_session::Session; | |
dfeec247 XL |
13 | use rustc_span::source_map::SourceMap; |
14 | use rustc_span::symbol::Symbol; | |
ba9703b0 | 15 | use rustc_span::{BytePos, CachingSourceMapView, SourceFile}; |
dfeec247 | 16 | |
3dfed10e | 17 | use rustc_span::def_id::{CrateNum, CRATE_DEF_INDEX}; |
b7449926 | 18 | use smallvec::SmallVec; |
dfeec247 | 19 | use std::cmp::Ord; |
ea8adc8c | 20 | |
b7449926 | 21 | fn compute_ignored_attr_names() -> FxHashSet<Symbol> { |
74b04a01 XL |
22 | debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); |
23 | ich::IGNORED_ATTRIBUTES.iter().copied().collect() | |
2c00a5a8 | 24 | } |
cc61c64b XL |
25 | |
26 | /// This is the context state available during incr. comp. hashing. It contains | |
e1599b0c XL |
27 | /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., |
28 | /// a reference to the `TyCtxt`) and it holds a few caches for speeding up various | |
29 | /// things (e.g., each `DefId`/`DefPath` is only hashed once). | |
ea8adc8c | 30 | #[derive(Clone)] |
0531ce1d XL |
31 | pub struct StableHashingContext<'a> { |
32 | sess: &'a Session, | |
33 | definitions: &'a Definitions, | |
34 | cstore: &'a dyn CrateStore, | |
dfeec247 | 35 | pub(super) body_resolver: BodyResolver<'a>, |
cc61c64b XL |
36 | hash_spans: bool, |
37 | hash_bodies: bool, | |
dfeec247 | 38 | pub(super) node_id_hashing_mode: NodeIdHashingMode, |
ea8adc8c XL |
39 | |
40 | // Very often, we are hashing something that does not need the | |
e1599b0c | 41 | // `CachingSourceMapView`, so we initialize it lazily. |
b7449926 XL |
42 | raw_source_map: &'a SourceMap, |
43 | caching_source_map: Option<CachingSourceMapView<'a>>, | |
cc61c64b XL |
44 | } |
45 | ||
46 | #[derive(PartialEq, Eq, Clone, Copy)] | |
47 | pub enum NodeIdHashingMode { | |
48 | Ignore, | |
49 | HashDefPath, | |
cc61c64b XL |
50 | } |
51 | ||
e1599b0c XL |
52 | /// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. |
53 | /// We could also just store a plain reference to the `hir::Crate` but we want | |
ea8adc8c XL |
54 | /// to avoid that the crate is used to get untracked access to all of the HIR. |
55 | #[derive(Clone, Copy)] | |
dfeec247 | 56 | pub(super) struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>); |
ea8adc8c | 57 | |
dc9dc135 | 58 | impl<'tcx> BodyResolver<'tcx> { |
e1599b0c XL |
59 | /// Returns a reference to the `hir::Body` with the given `BodyId`. |
60 | /// **Does not do any tracking**; use carefully. | |
dfeec247 | 61 | pub(super) fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> { |
ea8adc8c XL |
62 | self.0.body(id) |
63 | } | |
64 | } | |
cc61c64b | 65 | |
0531ce1d | 66 | impl<'a> StableHashingContext<'a> { |
e1599b0c XL |
67 | /// The `krate` here is only used for mapping `BodyId`s to `Body`s. |
68 | /// Don't use it for anything else or you'll run the risk of | |
69 | /// leaking data out of the tracking system. | |
0731742a | 70 | #[inline] |
f035d41b | 71 | fn new_with_or_without_spans( |
dfeec247 XL |
72 | sess: &'a Session, |
73 | krate: &'a hir::Crate<'a>, | |
74 | definitions: &'a Definitions, | |
75 | cstore: &'a dyn CrateStore, | |
f035d41b | 76 | always_ignore_spans: bool, |
dfeec247 | 77 | ) -> Self { |
f035d41b XL |
78 | let hash_spans_initial = |
79 | !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans; | |
ea8adc8c | 80 | |
cc61c64b | 81 | StableHashingContext { |
ea8adc8c XL |
82 | sess, |
83 | body_resolver: BodyResolver(krate), | |
84 | definitions, | |
85 | cstore, | |
b7449926 XL |
86 | caching_source_map: None, |
87 | raw_source_map: sess.source_map(), | |
cc61c64b XL |
88 | hash_spans: hash_spans_initial, |
89 | hash_bodies: true, | |
cc61c64b | 90 | node_id_hashing_mode: NodeIdHashingMode::HashDefPath, |
cc61c64b XL |
91 | } |
92 | } | |
93 | ||
f035d41b XL |
94 | #[inline] |
95 | pub fn new( | |
96 | sess: &'a Session, | |
97 | krate: &'a hir::Crate<'a>, | |
98 | definitions: &'a Definitions, | |
99 | cstore: &'a dyn CrateStore, | |
100 | ) -> Self { | |
101 | Self::new_with_or_without_spans( | |
102 | sess, | |
103 | krate, | |
104 | definitions, | |
105 | cstore, | |
106 | /*always_ignore_spans=*/ false, | |
107 | ) | |
108 | } | |
109 | ||
110 | #[inline] | |
111 | pub fn ignore_spans( | |
112 | sess: &'a Session, | |
113 | krate: &'a hir::Crate<'a>, | |
114 | definitions: &'a Definitions, | |
115 | cstore: &'a dyn CrateStore, | |
116 | ) -> Self { | |
117 | let always_ignore_spans = true; | |
118 | Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans) | |
119 | } | |
120 | ||
ea8adc8c | 121 | #[inline] |
0531ce1d | 122 | pub fn sess(&self) -> &'a Session { |
ea8adc8c XL |
123 | self.sess |
124 | } | |
125 | ||
cc61c64b | 126 | #[inline] |
dfeec247 | 127 | pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self, hash_bodies: bool, f: F) { |
cc61c64b XL |
128 | let prev_hash_bodies = self.hash_bodies; |
129 | self.hash_bodies = hash_bodies; | |
130 | f(self); | |
131 | self.hash_bodies = prev_hash_bodies; | |
132 | } | |
133 | ||
134 | #[inline] | |
dfeec247 | 135 | pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) { |
cc61c64b XL |
136 | let prev_hash_spans = self.hash_spans; |
137 | self.hash_spans = hash_spans; | |
138 | f(self); | |
139 | self.hash_spans = prev_hash_spans; | |
140 | } | |
141 | ||
142 | #[inline] | |
dfeec247 XL |
143 | pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>( |
144 | &mut self, | |
145 | mode: NodeIdHashingMode, | |
146 | f: F, | |
147 | ) { | |
cc61c64b XL |
148 | let prev = self.node_id_hashing_mode; |
149 | self.node_id_hashing_mode = mode; | |
150 | f(self); | |
151 | self.node_id_hashing_mode = prev; | |
152 | } | |
153 | ||
154 | #[inline] | |
ea8adc8c | 155 | pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { |
ba9703b0 XL |
156 | if let Some(def_id) = def_id.as_local() { |
157 | self.local_def_path_hash(def_id) | |
ea8adc8c XL |
158 | } else { |
159 | self.cstore.def_path_hash(def_id) | |
160 | } | |
161 | } | |
162 | ||
163 | #[inline] | |
ba9703b0 XL |
164 | pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { |
165 | self.definitions.def_path_hash(def_id) | |
cc61c64b XL |
166 | } |
167 | ||
cc61c64b XL |
168 | #[inline] |
169 | pub fn hash_bodies(&self) -> bool { | |
170 | self.hash_bodies | |
171 | } | |
172 | ||
173 | #[inline] | |
b7449926 XL |
174 | pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { |
175 | match self.caching_source_map { | |
74b04a01 | 176 | Some(ref mut sm) => sm, |
ea8adc8c | 177 | ref mut none => { |
b7449926 | 178 | *none = Some(CachingSourceMapView::new(self.raw_source_map)); |
ea8adc8c XL |
179 | none.as_mut().unwrap() |
180 | } | |
181 | } | |
cc61c64b XL |
182 | } |
183 | ||
184 | #[inline] | |
185 | pub fn is_ignored_attr(&self, name: Symbol) -> bool { | |
b7449926 XL |
186 | thread_local! { |
187 | static IGNORED_ATTRIBUTES: FxHashSet<Symbol> = compute_ignored_attr_names(); | |
188 | } | |
189 | IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) | |
cc61c64b | 190 | } |
cc61c64b XL |
191 | } |
192 | ||
0531ce1d XL |
193 | /// Something that can provide a stable hashing context. |
194 | pub trait StableHashingContextProvider<'a> { | |
195 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a>; | |
196 | } | |
197 | ||
dfeec247 | 198 | impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b T { |
0531ce1d XL |
199 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { |
200 | (**self).get_stable_hashing_context() | |
201 | } | |
202 | } | |
203 | ||
dfeec247 | 204 | impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b mut T { |
0531ce1d XL |
205 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { |
206 | (**self).get_stable_hashing_context() | |
ea8adc8c XL |
207 | } |
208 | } | |
209 | ||
dc9dc135 XL |
210 | impl StableHashingContextProvider<'tcx> for TyCtxt<'tcx> { |
211 | fn get_stable_hashing_context(&self) -> StableHashingContext<'tcx> { | |
0531ce1d XL |
212 | (*self).create_stable_hashing_context() |
213 | } | |
214 | } | |
ea8adc8c | 215 | |
0531ce1d XL |
216 | impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { |
217 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { | |
ea8adc8c XL |
218 | self.clone() |
219 | } | |
220 | } | |
221 | ||
0531ce1d | 222 | impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId { |
74b04a01 XL |
223 | fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { |
224 | panic!("Node IDs should not appear in incremental state"); | |
ea8adc8c XL |
225 | } |
226 | } | |
227 | ||
dfeec247 | 228 | impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { |
60c5eb7d XL |
229 | fn hash_spans(&self) -> bool { |
230 | self.hash_spans | |
cc61c64b | 231 | } |
cc61c64b | 232 | |
3dfed10e XL |
233 | #[inline] |
234 | fn hash_crate_num(&mut self, cnum: CrateNum, hasher: &mut StableHasher) { | |
235 | let hcx = self; | |
236 | hcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher); | |
237 | } | |
238 | ||
74b04a01 XL |
239 | #[inline] |
240 | fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) { | |
241 | let hcx = self; | |
242 | hcx.def_path_hash(def_id).hash_stable(hcx, hasher); | |
243 | } | |
244 | ||
dfeec247 XL |
245 | fn byte_pos_to_line_and_col( |
246 | &mut self, | |
247 | byte: BytePos, | |
248 | ) -> Option<(Lrc<SourceFile>, usize, BytePos)> { | |
60c5eb7d | 249 | self.source_map().byte_pos_to_line_and_col(byte) |
b7449926 XL |
250 | } |
251 | } | |
252 | ||
e74abb32 | 253 | pub fn hash_stable_trait_impls<'a>( |
0531ce1d | 254 | hcx: &mut StableHashingContext<'a>, |
e74abb32 | 255 | hasher: &mut StableHasher, |
8faf50e0 | 256 | blanket_impls: &[DefId], |
dc9dc135 | 257 | non_blanket_impls: &FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>, |
e74abb32 | 258 | ) { |
ea8adc8c | 259 | { |
dfeec247 XL |
260 | let mut blanket_impls: SmallVec<[_; 8]> = |
261 | blanket_impls.iter().map(|&def_id| hcx.def_path_hash(def_id)).collect(); | |
cc61c64b | 262 | |
ea8adc8c XL |
263 | if blanket_impls.len() > 1 { |
264 | blanket_impls.sort_unstable(); | |
265 | } | |
7cac9316 | 266 | |
ea8adc8c XL |
267 | blanket_impls.hash_stable(hcx, hasher); |
268 | } | |
3b2f2976 | 269 | |
ea8adc8c | 270 | { |
b7449926 | 271 | let mut keys: SmallVec<[_; 8]> = |
dfeec247 | 272 | non_blanket_impls.keys().map(|k| (k, k.map_def(|d| hcx.def_path_hash(d)))).collect(); |
ea8adc8c XL |
273 | keys.sort_unstable_by(|&(_, ref k1), &(_, ref k2)| k1.cmp(k2)); |
274 | keys.len().hash_stable(hcx, hasher); | |
275 | for (key, ref stable_key) in keys { | |
276 | stable_key.hash_stable(hcx, hasher); | |
dfeec247 XL |
277 | let mut impls: SmallVec<[_; 8]> = |
278 | non_blanket_impls[key].iter().map(|&impl_id| hcx.def_path_hash(impl_id)).collect(); | |
ea8adc8c XL |
279 | |
280 | if impls.len() > 1 { | |
281 | impls.sort_unstable(); | |
282 | } | |
7cac9316 | 283 | |
ea8adc8c XL |
284 | impls.hash_stable(hcx, hasher); |
285 | } | |
7cac9316 XL |
286 | } |
287 | } |