]>
Commit | Line | Data |
---|---|---|
9fa01778 | 1 | use crate::hir::map::definitions::Definitions; |
dfeec247 | 2 | use crate::hir::map::DefPathHash; |
60c5eb7d | 3 | use crate::ich::{self, CachingSourceMapView}; |
9fa01778 | 4 | use crate::middle::cstore::CrateStore; |
9fa01778 | 5 | use crate::session::Session; |
dfeec247 | 6 | use crate::ty::{fast_reject, TyCtxt}; |
cc61c64b | 7 | |
74b04a01 | 8 | use rustc_ast::ast; |
dfeec247 XL |
9 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
10 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; | |
60c5eb7d | 11 | use rustc_data_structures::sync::Lrc; |
dfeec247 XL |
12 | use rustc_hir as hir; |
13 | use rustc_hir::def_id::{DefId, DefIndex}; | |
14 | use rustc_span::source_map::SourceMap; | |
15 | use rustc_span::symbol::Symbol; | |
16 | use rustc_span::{BytePos, SourceFile}; | |
dfeec247 | 17 | |
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] |
dfeec247 XL |
71 | pub fn new( |
72 | sess: &'a Session, | |
73 | krate: &'a hir::Crate<'a>, | |
74 | definitions: &'a Definitions, | |
75 | cstore: &'a dyn CrateStore, | |
76 | ) -> Self { | |
ff7c6d11 | 77 | let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans; |
ea8adc8c | 78 | |
cc61c64b | 79 | StableHashingContext { |
ea8adc8c XL |
80 | sess, |
81 | body_resolver: BodyResolver(krate), | |
82 | definitions, | |
83 | cstore, | |
b7449926 XL |
84 | caching_source_map: None, |
85 | raw_source_map: sess.source_map(), | |
cc61c64b XL |
86 | hash_spans: hash_spans_initial, |
87 | hash_bodies: true, | |
cc61c64b | 88 | node_id_hashing_mode: NodeIdHashingMode::HashDefPath, |
cc61c64b XL |
89 | } |
90 | } | |
91 | ||
ea8adc8c | 92 | #[inline] |
0531ce1d | 93 | pub fn sess(&self) -> &'a Session { |
ea8adc8c XL |
94 | self.sess |
95 | } | |
96 | ||
cc61c64b | 97 | #[inline] |
dfeec247 | 98 | pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self, hash_bodies: bool, f: F) { |
cc61c64b XL |
99 | let prev_hash_bodies = self.hash_bodies; |
100 | self.hash_bodies = hash_bodies; | |
101 | f(self); | |
102 | self.hash_bodies = prev_hash_bodies; | |
103 | } | |
104 | ||
105 | #[inline] | |
dfeec247 | 106 | pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) { |
cc61c64b XL |
107 | let prev_hash_spans = self.hash_spans; |
108 | self.hash_spans = hash_spans; | |
109 | f(self); | |
110 | self.hash_spans = prev_hash_spans; | |
111 | } | |
112 | ||
113 | #[inline] | |
dfeec247 XL |
114 | pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>( |
115 | &mut self, | |
116 | mode: NodeIdHashingMode, | |
117 | f: F, | |
118 | ) { | |
cc61c64b XL |
119 | let prev = self.node_id_hashing_mode; |
120 | self.node_id_hashing_mode = mode; | |
121 | f(self); | |
122 | self.node_id_hashing_mode = prev; | |
123 | } | |
124 | ||
125 | #[inline] | |
ea8adc8c XL |
126 | pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { |
127 | if def_id.is_local() { | |
128 | self.definitions.def_path_hash(def_id.index) | |
129 | } else { | |
130 | self.cstore.def_path_hash(def_id) | |
131 | } | |
132 | } | |
133 | ||
134 | #[inline] | |
135 | pub fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash { | |
136 | self.definitions.def_path_hash(def_index) | |
cc61c64b XL |
137 | } |
138 | ||
139 | #[inline] | |
ea8adc8c XL |
140 | pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId { |
141 | self.definitions.node_to_hir_id(node_id) | |
cc61c64b XL |
142 | } |
143 | ||
cc61c64b XL |
144 | #[inline] |
145 | pub fn hash_bodies(&self) -> bool { | |
146 | self.hash_bodies | |
147 | } | |
148 | ||
149 | #[inline] | |
b7449926 XL |
150 | pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { |
151 | match self.caching_source_map { | |
74b04a01 | 152 | Some(ref mut sm) => sm, |
ea8adc8c | 153 | ref mut none => { |
b7449926 | 154 | *none = Some(CachingSourceMapView::new(self.raw_source_map)); |
ea8adc8c XL |
155 | none.as_mut().unwrap() |
156 | } | |
157 | } | |
cc61c64b XL |
158 | } |
159 | ||
160 | #[inline] | |
161 | pub fn is_ignored_attr(&self, name: Symbol) -> bool { | |
b7449926 XL |
162 | thread_local! { |
163 | static IGNORED_ATTRIBUTES: FxHashSet<Symbol> = compute_ignored_attr_names(); | |
164 | } | |
165 | IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) | |
cc61c64b XL |
166 | } |
167 | ||
ff7c6d11 | 168 | pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) { |
cc61c64b XL |
169 | let prev_hash_node_ids = self.node_id_hashing_mode; |
170 | self.node_id_hashing_mode = NodeIdHashingMode::Ignore; | |
171 | ||
172 | f(self); | |
173 | ||
174 | self.node_id_hashing_mode = prev_hash_node_ids; | |
cc61c64b XL |
175 | } |
176 | } | |
177 | ||
0531ce1d XL |
178 | /// Something that can provide a stable hashing context. |
179 | pub trait StableHashingContextProvider<'a> { | |
180 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a>; | |
181 | } | |
182 | ||
dfeec247 | 183 | impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b T { |
0531ce1d XL |
184 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { |
185 | (**self).get_stable_hashing_context() | |
186 | } | |
187 | } | |
188 | ||
dfeec247 | 189 | impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b mut T { |
0531ce1d XL |
190 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { |
191 | (**self).get_stable_hashing_context() | |
ea8adc8c XL |
192 | } |
193 | } | |
194 | ||
dc9dc135 XL |
195 | impl StableHashingContextProvider<'tcx> for TyCtxt<'tcx> { |
196 | fn get_stable_hashing_context(&self) -> StableHashingContext<'tcx> { | |
0531ce1d XL |
197 | (*self).create_stable_hashing_context() |
198 | } | |
199 | } | |
ea8adc8c | 200 | |
0531ce1d XL |
201 | impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { |
202 | fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { | |
ea8adc8c XL |
203 | self.clone() |
204 | } | |
205 | } | |
206 | ||
e1599b0c | 207 | impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {} |
ea8adc8c | 208 | |
0531ce1d | 209 | impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::HirId { |
ea8adc8c XL |
210 | type KeyType = (DefPathHash, hir::ItemLocalId); |
211 | ||
212 | #[inline] | |
dfeec247 XL |
213 | fn to_stable_hash_key( |
214 | &self, | |
215 | hcx: &StableHashingContext<'a>, | |
216 | ) -> (DefPathHash, hir::ItemLocalId) { | |
ea8adc8c XL |
217 | let def_path_hash = hcx.local_def_path_hash(self.owner); |
218 | (def_path_hash, self.local_id) | |
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 | |
74b04a01 XL |
233 | #[inline] |
234 | fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) { | |
235 | let hcx = self; | |
236 | hcx.def_path_hash(def_id).hash_stable(hcx, hasher); | |
237 | } | |
238 | ||
dfeec247 XL |
239 | fn byte_pos_to_line_and_col( |
240 | &mut self, | |
241 | byte: BytePos, | |
242 | ) -> Option<(Lrc<SourceFile>, usize, BytePos)> { | |
60c5eb7d | 243 | self.source_map().byte_pos_to_line_and_col(byte) |
b7449926 XL |
244 | } |
245 | } | |
246 | ||
e74abb32 | 247 | pub fn hash_stable_trait_impls<'a>( |
0531ce1d | 248 | hcx: &mut StableHashingContext<'a>, |
e74abb32 | 249 | hasher: &mut StableHasher, |
8faf50e0 | 250 | blanket_impls: &[DefId], |
dc9dc135 | 251 | non_blanket_impls: &FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>, |
e74abb32 | 252 | ) { |
ea8adc8c | 253 | { |
dfeec247 XL |
254 | let mut blanket_impls: SmallVec<[_; 8]> = |
255 | blanket_impls.iter().map(|&def_id| hcx.def_path_hash(def_id)).collect(); | |
cc61c64b | 256 | |
ea8adc8c XL |
257 | if blanket_impls.len() > 1 { |
258 | blanket_impls.sort_unstable(); | |
259 | } | |
7cac9316 | 260 | |
ea8adc8c XL |
261 | blanket_impls.hash_stable(hcx, hasher); |
262 | } | |
3b2f2976 | 263 | |
ea8adc8c | 264 | { |
b7449926 | 265 | let mut keys: SmallVec<[_; 8]> = |
dfeec247 | 266 | non_blanket_impls.keys().map(|k| (k, k.map_def(|d| hcx.def_path_hash(d)))).collect(); |
ea8adc8c XL |
267 | keys.sort_unstable_by(|&(_, ref k1), &(_, ref k2)| k1.cmp(k2)); |
268 | keys.len().hash_stable(hcx, hasher); | |
269 | for (key, ref stable_key) in keys { | |
270 | stable_key.hash_stable(hcx, hasher); | |
dfeec247 XL |
271 | let mut impls: SmallVec<[_; 8]> = |
272 | non_blanket_impls[key].iter().map(|&impl_id| hcx.def_path_hash(impl_id)).collect(); | |
ea8adc8c XL |
273 | |
274 | if impls.len() > 1 { | |
275 | impls.sort_unstable(); | |
276 | } | |
7cac9316 | 277 | |
ea8adc8c XL |
278 | impls.hash_stable(hcx, hasher); |
279 | } | |
7cac9316 XL |
280 | } |
281 | } |