]>
Commit | Line | Data |
---|---|---|
041b39d2 XL |
1 | //! This module defines the `DepNode` type which the compiler uses to represent |
2 | //! nodes in the dependency graph. A `DepNode` consists of a `DepKind` (which | |
3 | //! specifies the kind of thing it represents, like a piece of HIR, MIR, etc) | |
4 | //! and a `Fingerprint`, a 128 bit hash value the exact meaning of which | |
5 | //! depends on the node's `DepKind`. Together, the kind and the fingerprint | |
6 | //! fully identify a dependency node, even across multiple compilation sessions. | |
7 | //! In other words, the value of the fingerprint does not depend on anything | |
8 | //! that is specific to a given compilation session, like an unpredictable | |
0731742a | 9 | //! interning key (e.g., NodeId, DefId, Symbol) or the numeric value of a |
041b39d2 XL |
10 | //! pointer. The concept behind this could be compared to how git commit hashes |
11 | //! uniquely identify a given commit and has a few advantages: | |
12 | //! | |
13 | //! * A `DepNode` can simply be serialized to disk and loaded in another session | |
14 | //! without the need to do any "rebasing (like we have to do for Spans and | |
15 | //! NodeIds) or "retracing" like we had to do for `DefId` in earlier | |
16 | //! implementations of the dependency graph. | |
17 | //! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to | |
18 | //! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. | |
19 | //! * Since we just have a bit pattern, `DepNode` can be mapped from disk into | |
0731742a | 20 | //! memory without any post-processing (e.g., "abomination-style" pointer |
041b39d2 XL |
21 | //! reconstruction). |
22 | //! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that | |
23 | //! refer to things that do not exist anymore. In previous implementations | |
24 | //! `DepNode` contained a `DefId`. A `DepNode` referring to something that | |
25 | //! had been removed between the previous and the current compilation session | |
26 | //! could not be instantiated because the current compilation session | |
27 | //! contained no `DefId` for thing that had been removed. | |
28 | //! | |
29 | //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro | |
30 | //! defines the `DepKind` enum and a corresponding `DepConstructor` enum. The | |
31 | //! `DepConstructor` enum links a `DepKind` to the parameters that are needed at | |
32 | //! runtime in order to construct a valid `DepNode` fingerprint. | |
33 | //! | |
34 | //! Because the macro sees what parameters a given `DepKind` requires, it can | |
35 | //! "infer" some properties for each kind of `DepNode`: | |
36 | //! | |
37 | //! * Whether a `DepNode` of a given kind has any parameters at all. Some | |
38 | //! `DepNode`s, like `Krate`, represent global concepts with only one value. | |
39 | //! * Whether it is possible, in principle, to reconstruct a query key from a | |
40 | //! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, | |
41 | //! in which case it is possible to map the node's fingerprint back to the | |
42 | //! `DefId` it was computed from. In other cases, too much information gets | |
43 | //! lost during fingerprint computation. | |
44 | //! | |
45 | //! The `DepConstructor` enum, together with `DepNode::new()` ensures that only | |
46 | //! valid `DepNode` instances can be constructed. For example, the API does not | |
47 | //! allow for constructing parameterless `DepNode`s with anything other | |
48 | //! than a zeroed out fingerprint. More generally speaking, it relieves the | |
49 | //! user of the `DepNode` API of having to know how to compute the expected | |
50 | //! fingerprint for a given set of node parameters. | |
51 | ||
dc9dc135 | 52 | use crate::mir; |
9fa01778 XL |
53 | use crate::mir::interpret::GlobalId; |
54 | use crate::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; | |
55 | use crate::hir::map::DefPathHash; | |
56 | use crate::hir::HirId; | |
041b39d2 | 57 | |
9fa01778 | 58 | use crate::ich::{Fingerprint, StableHashingContext}; |
041b39d2 | 59 | use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; |
041b39d2 XL |
60 | use std::fmt; |
61 | use std::hash::Hash; | |
ea8adc8c | 62 | use syntax_pos::symbol::InternedString; |
9fa01778 XL |
63 | use crate::traits; |
64 | use crate::traits::query::{ | |
0bf4aa26 XL |
65 | CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, |
66 | CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal, | |
67 | CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, | |
8faf50e0 | 68 | }; |
532ac7d7 XL |
69 | use crate::ty::{self, TyCtxt, ParamEnvAnd, Ty}; |
70 | use crate::ty::subst::SubstsRef; | |
041b39d2 XL |
71 | |
72 | // erase!() just makes tokens go away. It's used to specify which macro argument | |
0731742a | 73 | // is repeated (i.e., which sub-expression of the macro we are in) but don't need |
041b39d2 XL |
74 | // to actually use any of the arguments. |
75 | macro_rules! erase { | |
76 | ($x:tt) => ({}) | |
77 | } | |
78 | ||
0531ce1d XL |
79 | macro_rules! replace { |
80 | ($x:tt with $($y:tt)*) => ($($y)*) | |
81 | } | |
82 | ||
ea8adc8c XL |
83 | macro_rules! is_anon_attr { |
84 | (anon) => (true); | |
85 | ($attr:ident) => (false); | |
86 | } | |
87 | ||
abe05a73 XL |
88 | macro_rules! is_eval_always_attr { |
89 | (eval_always) => (true); | |
90 | ($attr:ident) => (false); | |
91 | } | |
92 | ||
ea8adc8c XL |
93 | macro_rules! contains_anon_attr { |
94 | ($($attr:ident),*) => ({$(is_anon_attr!($attr) | )* false}); | |
95 | } | |
96 | ||
abe05a73 XL |
97 | macro_rules! contains_eval_always_attr { |
98 | ($($attr:ident),*) => ({$(is_eval_always_attr!($attr) | )* false}); | |
99 | } | |
100 | ||
041b39d2 XL |
101 | macro_rules! define_dep_nodes { |
102 | (<$tcx:tt> | |
103 | $( | |
ea8adc8c | 104 | [$($attr:ident),* ] |
9fa01778 | 105 | $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* |
041b39d2 XL |
106 | $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* |
107 | ,)* | |
108 | ) => ( | |
109 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, | |
110 | RustcEncodable, RustcDecodable)] | |
111 | pub enum DepKind { | |
112 | $($variant),* | |
113 | } | |
114 | ||
115 | impl DepKind { | |
116 | #[allow(unreachable_code)] | |
117 | #[inline] | |
118 | pub fn can_reconstruct_query_key<$tcx>(&self) -> bool { | |
119 | match *self { | |
120 | $( | |
121 | DepKind :: $variant => { | |
ea8adc8c XL |
122 | if contains_anon_attr!($($attr),*) { |
123 | return false; | |
124 | } | |
3b2f2976 | 125 | |
041b39d2 XL |
126 | // tuple args |
127 | $({ | |
0531ce1d | 128 | return <$tuple_arg_ty as DepNodeParams> |
041b39d2 XL |
129 | ::CAN_RECONSTRUCT_QUERY_KEY; |
130 | })* | |
131 | ||
132 | // struct args | |
133 | $({ | |
3b2f2976 | 134 | |
041b39d2 XL |
135 | return <( $($struct_arg_ty,)* ) as DepNodeParams> |
136 | ::CAN_RECONSTRUCT_QUERY_KEY; | |
137 | })* | |
138 | ||
139 | true | |
140 | } | |
141 | )* | |
142 | } | |
143 | } | |
144 | ||
ea8adc8c | 145 | pub fn is_anon(&self) -> bool { |
041b39d2 XL |
146 | match *self { |
147 | $( | |
ea8adc8c XL |
148 | DepKind :: $variant => { contains_anon_attr!($($attr),*) } |
149 | )* | |
150 | } | |
151 | } | |
152 | ||
0731742a | 153 | #[inline(always)] |
abe05a73 XL |
154 | pub fn is_eval_always(&self) -> bool { |
155 | match *self { | |
156 | $( | |
157 | DepKind :: $variant => { contains_eval_always_attr!($($attr), *) } | |
158 | )* | |
159 | } | |
160 | } | |
161 | ||
041b39d2 | 162 | #[allow(unreachable_code)] |
041b39d2 XL |
163 | pub fn has_params(&self) -> bool { |
164 | match *self { | |
165 | $( | |
166 | DepKind :: $variant => { | |
167 | // tuple args | |
168 | $({ | |
0531ce1d | 169 | erase!($tuple_arg_ty); |
041b39d2 XL |
170 | return true; |
171 | })* | |
172 | ||
173 | // struct args | |
174 | $({ | |
175 | $(erase!($struct_arg_name);)* | |
176 | return true; | |
177 | })* | |
178 | ||
179 | false | |
180 | } | |
181 | )* | |
182 | } | |
183 | } | |
184 | } | |
185 | ||
186 | pub enum DepConstructor<$tcx> { | |
187 | $( | |
0531ce1d | 188 | $variant $(( $tuple_arg_ty ))* |
041b39d2 XL |
189 | $({ $($struct_arg_name : $struct_arg_ty),* })* |
190 | ),* | |
191 | } | |
192 | ||
193 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, | |
194 | RustcEncodable, RustcDecodable)] | |
195 | pub struct DepNode { | |
196 | pub kind: DepKind, | |
197 | pub hash: Fingerprint, | |
3157f602 | 198 | } |
041b39d2 XL |
199 | |
200 | impl DepNode { | |
201 | #[allow(unreachable_code, non_snake_case)] | |
0731742a | 202 | #[inline(always)] |
dc9dc135 XL |
203 | pub fn new<'tcx>(tcx: TyCtxt<'tcx>, |
204 | dep: DepConstructor<'tcx>) | |
041b39d2 | 205 | -> DepNode |
041b39d2 XL |
206 | { |
207 | match dep { | |
208 | $( | |
0531ce1d | 209 | DepConstructor :: $variant $(( replace!(($tuple_arg_ty) with arg) ))* |
041b39d2 XL |
210 | $({ $($struct_arg_name),* })* |
211 | => | |
212 | { | |
213 | // tuple args | |
214 | $({ | |
0531ce1d XL |
215 | erase!($tuple_arg_ty); |
216 | let hash = DepNodeParams::to_fingerprint(&arg, tcx); | |
041b39d2 XL |
217 | let dep_node = DepNode { |
218 | kind: DepKind::$variant, | |
219 | hash | |
220 | }; | |
221 | ||
222 | if cfg!(debug_assertions) && | |
223 | !dep_node.kind.can_reconstruct_query_key() && | |
224 | (tcx.sess.opts.debugging_opts.incremental_info || | |
225 | tcx.sess.opts.debugging_opts.query_dep_graph) | |
226 | { | |
227 | tcx.dep_graph.register_dep_node_debug_str(dep_node, || { | |
0531ce1d | 228 | arg.to_debug_str(tcx) |
041b39d2 XL |
229 | }); |
230 | } | |
231 | ||
232 | return dep_node; | |
233 | })* | |
234 | ||
235 | // struct args | |
236 | $({ | |
237 | let tupled_args = ( $($struct_arg_name,)* ); | |
238 | let hash = DepNodeParams::to_fingerprint(&tupled_args, | |
239 | tcx); | |
240 | let dep_node = DepNode { | |
241 | kind: DepKind::$variant, | |
242 | hash | |
243 | }; | |
244 | ||
245 | if cfg!(debug_assertions) && | |
246 | !dep_node.kind.can_reconstruct_query_key() && | |
247 | (tcx.sess.opts.debugging_opts.incremental_info || | |
248 | tcx.sess.opts.debugging_opts.query_dep_graph) | |
249 | { | |
250 | tcx.dep_graph.register_dep_node_debug_str(dep_node, || { | |
251 | tupled_args.to_debug_str(tcx) | |
252 | }); | |
253 | } | |
254 | ||
255 | return dep_node; | |
256 | })* | |
257 | ||
258 | DepNode { | |
259 | kind: DepKind::$variant, | |
ff7c6d11 | 260 | hash: Fingerprint::ZERO, |
041b39d2 XL |
261 | } |
262 | } | |
263 | )* | |
264 | } | |
265 | } | |
266 | ||
267 | /// Construct a DepNode from the given DepKind and DefPathHash. This | |
268 | /// method will assert that the given DepKind actually requires a | |
269 | /// single DefId/DefPathHash parameter. | |
0731742a | 270 | #[inline(always)] |
041b39d2 XL |
271 | pub fn from_def_path_hash(kind: DepKind, |
272 | def_path_hash: DefPathHash) | |
273 | -> DepNode { | |
0731742a | 274 | debug_assert!(kind.can_reconstruct_query_key() && kind.has_params()); |
041b39d2 XL |
275 | DepNode { |
276 | kind, | |
277 | hash: def_path_hash.0, | |
278 | } | |
279 | } | |
280 | ||
9fa01778 | 281 | /// Creates a new, parameterless DepNode. This method will assert |
041b39d2 XL |
282 | /// that the DepNode corresponding to the given DepKind actually |
283 | /// does not require any parameters. | |
0731742a | 284 | #[inline(always)] |
041b39d2 | 285 | pub fn new_no_params(kind: DepKind) -> DepNode { |
0731742a | 286 | debug_assert!(!kind.has_params()); |
041b39d2 XL |
287 | DepNode { |
288 | kind, | |
ff7c6d11 | 289 | hash: Fingerprint::ZERO, |
041b39d2 XL |
290 | } |
291 | } | |
292 | ||
9fa01778 | 293 | /// Extracts the DefId corresponding to this DepNode. This will work |
041b39d2 XL |
294 | /// if two conditions are met: |
295 | /// | |
296 | /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and | |
297 | /// 2. the item that the DefPath refers to exists in the current tcx. | |
298 | /// | |
299 | /// Condition (1) is determined by the DepKind variant of the | |
300 | /// DepNode. Condition (2) might not be fulfilled if a DepNode | |
301 | /// refers to something from the previous compilation session that | |
302 | /// has been removed. | |
303 | #[inline] | |
dc9dc135 | 304 | pub fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> { |
041b39d2 XL |
305 | if self.kind.can_reconstruct_query_key() { |
306 | let def_path_hash = DefPathHash(self.hash); | |
8faf50e0 XL |
307 | tcx.def_path_hash_to_def_id.as_ref()? |
308 | .get(&def_path_hash).cloned() | |
041b39d2 XL |
309 | } else { |
310 | None | |
311 | } | |
312 | } | |
313 | ||
314 | /// Used in testing | |
315 | pub fn from_label_string(label: &str, | |
316 | def_path_hash: DefPathHash) | |
317 | -> Result<DepNode, ()> { | |
318 | let kind = match label { | |
319 | $( | |
320 | stringify!($variant) => DepKind::$variant, | |
321 | )* | |
322 | _ => return Err(()), | |
323 | }; | |
324 | ||
325 | if !kind.can_reconstruct_query_key() { | |
326 | return Err(()); | |
327 | } | |
328 | ||
329 | if kind.has_params() { | |
330 | Ok(def_path_hash.to_dep_node(kind)) | |
331 | } else { | |
332 | Ok(DepNode::new_no_params(kind)) | |
333 | } | |
334 | } | |
ea8adc8c XL |
335 | |
336 | /// Used in testing | |
337 | pub fn has_label_string(label: &str) -> bool { | |
338 | match label { | |
339 | $( | |
340 | stringify!($variant) => true, | |
341 | )* | |
342 | _ => false, | |
343 | } | |
344 | } | |
345 | } | |
346 | ||
347 | /// Contains variant => str representations for constructing | |
348 | /// DepNode groups for tests. | |
349 | #[allow(dead_code, non_upper_case_globals)] | |
350 | pub mod label_strs { | |
351 | $( | |
0731742a | 352 | pub const $variant: &str = stringify!($variant); |
ea8adc8c | 353 | )* |
041b39d2 XL |
354 | } |
355 | ); | |
356 | } | |
357 | ||
358 | impl fmt::Debug for DepNode { | |
0bf4aa26 | 359 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
041b39d2 XL |
360 | write!(f, "{:?}", self.kind)?; |
361 | ||
ea8adc8c | 362 | if !self.kind.has_params() && !self.kind.is_anon() { |
041b39d2 XL |
363 | return Ok(()); |
364 | } | |
365 | ||
366 | write!(f, "(")?; | |
367 | ||
9fa01778 | 368 | crate::ty::tls::with_opt(|opt_tcx| { |
041b39d2 XL |
369 | if let Some(tcx) = opt_tcx { |
370 | if let Some(def_id) = self.extract_def_id(tcx) { | |
ea8adc8c | 371 | write!(f, "{}", tcx.def_path_debug_str(def_id))?; |
041b39d2 XL |
372 | } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) { |
373 | write!(f, "{}", s)?; | |
374 | } else { | |
ea8adc8c | 375 | write!(f, "{}", self.hash)?; |
041b39d2 XL |
376 | } |
377 | } else { | |
ea8adc8c | 378 | write!(f, "{}", self.hash)?; |
041b39d2 XL |
379 | } |
380 | Ok(()) | |
381 | })?; | |
382 | ||
383 | write!(f, ")") | |
384 | } | |
385 | } | |
386 | ||
387 | ||
388 | impl DefPathHash { | |
0731742a | 389 | #[inline(always)] |
041b39d2 XL |
390 | pub fn to_dep_node(self, kind: DepKind) -> DepNode { |
391 | DepNode::from_def_path_hash(kind, self) | |
392 | } | |
393 | } | |
394 | ||
395 | impl DefId { | |
0731742a | 396 | #[inline(always)] |
dc9dc135 | 397 | pub fn to_dep_node(self, tcx: TyCtxt<'_>, kind: DepKind) -> DepNode { |
041b39d2 XL |
398 | DepNode::from_def_path_hash(kind, tcx.def_path_hash(self)) |
399 | } | |
3157f602 XL |
400 | } |
401 | ||
532ac7d7 | 402 | rustc_dep_node_append!([define_dep_nodes!][ <'tcx> |
0531ce1d XL |
403 | // We use this for most things when incr. comp. is turned off. |
404 | [] Null, | |
405 | ||
041b39d2 XL |
406 | // Represents the `Krate` as a whole (the `hir::Krate` value) (as |
407 | // distinct from the krate module). This is basically a hash of | |
408 | // the entire krate, so if you read from `Krate` (e.g., by calling | |
0731742a | 409 | // `tcx.hir().krate()`), we will have to assume that any change |
041b39d2 XL |
410 | // means that you need to be recompiled. This is because the |
411 | // `Krate` value gives you access to all other items. To avoid | |
0731742a | 412 | // this fate, do not call `tcx.hir().krate()`; instead, prefer |
041b39d2 XL |
413 | // wrappers like `tcx.visit_all_items_in_krate()`. If there is no |
414 | // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain | |
415 | // access to the krate, but you must remember to add suitable | |
416 | // edges yourself for the individual items that you read. | |
532ac7d7 | 417 | [eval_always] Krate, |
041b39d2 XL |
418 | |
419 | // Represents the body of a function or method. The def-id is that of the | |
420 | // function/method. | |
532ac7d7 | 421 | [eval_always] HirBody(DefId), |
041b39d2 | 422 | |
ea8adc8c | 423 | // Represents the HIR node with the given node-id |
532ac7d7 | 424 | [eval_always] Hir(DefId), |
ea8adc8c XL |
425 | |
426 | // Represents metadata from an extern crate. | |
532ac7d7 XL |
427 | [eval_always] CrateMetadata(CrateNum), |
428 | ||
429 | [eval_always] AllLocalTraitImpls, | |
abe05a73 | 430 | |
3b2f2976 | 431 | [anon] TraitSelect, |
041b39d2 | 432 | |
ea8adc8c | 433 | [] CompileCodegenUnit(InternedString), |
532ac7d7 XL |
434 | |
435 | [eval_always] Analysis(CrateNum), | |
436 | ]); | |
437 | ||
438 | pub trait RecoverKey<'tcx>: Sized { | |
dc9dc135 | 439 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>; |
532ac7d7 XL |
440 | } |
441 | ||
442 | impl RecoverKey<'tcx> for CrateNum { | |
dc9dc135 | 443 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
532ac7d7 XL |
444 | dep_node.extract_def_id(tcx).map(|id| id.krate) |
445 | } | |
446 | } | |
447 | ||
448 | impl RecoverKey<'tcx> for DefId { | |
dc9dc135 | 449 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
532ac7d7 XL |
450 | dep_node.extract_def_id(tcx) |
451 | } | |
452 | } | |
453 | ||
454 | impl RecoverKey<'tcx> for DefIndex { | |
dc9dc135 | 455 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
532ac7d7 XL |
456 | dep_node.extract_def_id(tcx).map(|id| id.index) |
457 | } | |
458 | } | |
041b39d2 | 459 | |
dc9dc135 | 460 | trait DepNodeParams<'tcx>: fmt::Debug { |
041b39d2 XL |
461 | const CAN_RECONSTRUCT_QUERY_KEY: bool; |
462 | ||
463 | /// This method turns the parameters of a DepNodeConstructor into an opaque | |
464 | /// Fingerprint to be used in DepNode. | |
465 | /// Not all DepNodeParams support being turned into a Fingerprint (they | |
466 | /// don't need to if the corresponding DepNode is anonymous). | |
dc9dc135 | 467 | fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { |
041b39d2 XL |
468 | panic!("Not implemented. Accidentally called on anonymous node?") |
469 | } | |
470 | ||
dc9dc135 | 471 | fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String { |
041b39d2 XL |
472 | format!("{:?}", self) |
473 | } | |
54a0048b SL |
474 | } |
475 | ||
dc9dc135 XL |
476 | impl<'tcx, T> DepNodeParams<'tcx> for T |
477 | where | |
478 | T: HashStable<StableHashingContext<'tcx>> + fmt::Debug, | |
041b39d2 XL |
479 | { |
480 | default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; | |
54a0048b | 481 | |
dc9dc135 | 482 | default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
ea8adc8c | 483 | let mut hcx = tcx.create_stable_hashing_context(); |
041b39d2 XL |
484 | let mut hasher = StableHasher::new(); |
485 | ||
486 | self.hash_stable(&mut hcx, &mut hasher); | |
487 | ||
488 | hasher.finish() | |
489 | } | |
490 | ||
dc9dc135 | 491 | default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String { |
041b39d2 XL |
492 | format!("{:?}", *self) |
493 | } | |
494 | } | |
495 | ||
dc9dc135 | 496 | impl<'tcx> DepNodeParams<'tcx> for DefId { |
041b39d2 XL |
497 | const CAN_RECONSTRUCT_QUERY_KEY: bool = true; |
498 | ||
dc9dc135 | 499 | fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { |
0531ce1d | 500 | tcx.def_path_hash(*self).0 |
041b39d2 XL |
501 | } |
502 | ||
dc9dc135 | 503 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
532ac7d7 | 504 | tcx.def_path_str(*self) |
041b39d2 XL |
505 | } |
506 | } | |
9e0c209e | 507 | |
dc9dc135 | 508 | impl<'tcx> DepNodeParams<'tcx> for DefIndex { |
ea8adc8c XL |
509 | const CAN_RECONSTRUCT_QUERY_KEY: bool = true; |
510 | ||
dc9dc135 | 511 | fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { |
0731742a | 512 | tcx.hir().definitions().def_path_hash(*self).0 |
ea8adc8c XL |
513 | } |
514 | ||
dc9dc135 | 515 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
532ac7d7 | 516 | tcx.def_path_str(DefId::local(*self)) |
ea8adc8c XL |
517 | } |
518 | } | |
519 | ||
dc9dc135 | 520 | impl<'tcx> DepNodeParams<'tcx> for CrateNum { |
ea8adc8c XL |
521 | const CAN_RECONSTRUCT_QUERY_KEY: bool = true; |
522 | ||
dc9dc135 | 523 | fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { |
ea8adc8c | 524 | let def_id = DefId { |
0531ce1d | 525 | krate: *self, |
ea8adc8c XL |
526 | index: CRATE_DEF_INDEX, |
527 | }; | |
528 | tcx.def_path_hash(def_id).0 | |
529 | } | |
530 | ||
dc9dc135 | 531 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
0531ce1d | 532 | tcx.crate_name(*self).as_str().to_string() |
ea8adc8c XL |
533 | } |
534 | } | |
535 | ||
dc9dc135 | 536 | impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) { |
041b39d2 XL |
537 | const CAN_RECONSTRUCT_QUERY_KEY: bool = false; |
538 | ||
539 | // We actually would not need to specialize the implementation of this | |
540 | // method but it's faster to combine the hashes than to instantiate a full | |
541 | // hashing context and stable-hashing state. | |
dc9dc135 | 542 | fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { |
041b39d2 XL |
543 | let (def_id_0, def_id_1) = *self; |
544 | ||
545 | let def_path_hash_0 = tcx.def_path_hash(def_id_0); | |
546 | let def_path_hash_1 = tcx.def_path_hash(def_id_1); | |
547 | ||
548 | def_path_hash_0.0.combine(def_path_hash_1.0) | |
549 | } | |
550 | ||
dc9dc135 | 551 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
041b39d2 XL |
552 | let (def_id_0, def_id_1) = *self; |
553 | ||
554 | format!("({}, {})", | |
ea8adc8c XL |
555 | tcx.def_path_debug_str(def_id_0), |
556 | tcx.def_path_debug_str(def_id_1)) | |
041b39d2 XL |
557 | } |
558 | } | |
559 | ||
dc9dc135 | 560 | impl<'tcx> DepNodeParams<'tcx> for HirId { |
041b39d2 XL |
561 | const CAN_RECONSTRUCT_QUERY_KEY: bool = false; |
562 | ||
563 | // We actually would not need to specialize the implementation of this | |
564 | // method but it's faster to combine the hashes than to instantiate a full | |
565 | // hashing context and stable-hashing state. | |
dc9dc135 | 566 | fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { |
0531ce1d | 567 | let HirId { |
ea8adc8c | 568 | owner, |
a1dfa0c6 | 569 | local_id, |
0531ce1d | 570 | } = *self; |
041b39d2 | 571 | |
ea8adc8c | 572 | let def_path_hash = tcx.def_path_hash(DefId::local(owner)); |
a1dfa0c6 | 573 | let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); |
041b39d2 | 574 | |
ea8adc8c | 575 | def_path_hash.0.combine(local_id) |
54a0048b SL |
576 | } |
577 | } | |
5bcae85e SL |
578 | |
579 | /// A "work product" corresponds to a `.o` (or other) file that we | |
9fa01778 | 580 | /// save in between runs. These IDs do not have a `DefId` but rather |
5bcae85e SL |
581 | /// some independent path or string that persists between runs without |
582 | /// the need to be mapped or unmapped. (This ensures we can serialize | |
583 | /// them even in the absence of a tcx.) | |
041b39d2 XL |
584 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, |
585 | RustcEncodable, RustcDecodable)] | |
586 | pub struct WorkProductId { | |
587 | hash: Fingerprint | |
588 | } | |
589 | ||
590 | impl WorkProductId { | |
591 | pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { | |
592 | let mut hasher = StableHasher::new(); | |
593 | cgu_name.len().hash(&mut hasher); | |
594 | cgu_name.hash(&mut hasher); | |
595 | WorkProductId { | |
596 | hash: hasher.finish() | |
597 | } | |
598 | } | |
599 | ||
600 | pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId { | |
601 | WorkProductId { | |
602 | hash: fingerprint | |
603 | } | |
604 | } | |
7cac9316 | 605 | } |
041b39d2 | 606 | |
9fa01778 | 607 | impl_stable_hash_for!(struct crate::dep_graph::WorkProductId { |
041b39d2 XL |
608 | hash |
609 | }); |