]>
Commit | Line | Data |
---|---|---|
5869c6ff | 1 | //! Nodes in the dependency graph. |
3dfed10e | 2 | //! |
5869c6ff XL |
3 | //! A node in the [dependency graph] is represented by a [`DepNode`]. |
4 | //! A `DepNode` consists of a [`DepKind`] (which | |
5 | //! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.) | |
6 | //! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which | |
041b39d2 XL |
7 | //! depends on the node's `DepKind`. Together, the kind and the fingerprint |
8 | //! fully identify a dependency node, even across multiple compilation sessions. | |
9 | //! In other words, the value of the fingerprint does not depend on anything | |
10 | //! that is specific to a given compilation session, like an unpredictable | |
5869c6ff | 11 | //! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a |
041b39d2 | 12 | //! pointer. The concept behind this could be compared to how git commit hashes |
5869c6ff XL |
13 | //! uniquely identify a given commit. The fingerprinting approach has |
14 | //! a few advantages: | |
041b39d2 XL |
15 | //! |
16 | //! * A `DepNode` can simply be serialized to disk and loaded in another session | |
3dfed10e XL |
17 | //! without the need to do any "rebasing" (like we have to do for Spans and |
18 | //! NodeIds) or "retracing" (like we had to do for `DefId` in earlier | |
19 | //! implementations of the dependency graph). | |
041b39d2 XL |
20 | //! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to |
21 | //! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. | |
22 | //! * Since we just have a bit pattern, `DepNode` can be mapped from disk into | |
0731742a | 23 | //! memory without any post-processing (e.g., "abomination-style" pointer |
041b39d2 XL |
24 | //! reconstruction). |
25 | //! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that | |
26 | //! refer to things that do not exist anymore. In previous implementations | |
27 | //! `DepNode` contained a `DefId`. A `DepNode` referring to something that | |
28 | //! had been removed between the previous and the current compilation session | |
29 | //! could not be instantiated because the current compilation session | |
30 | //! contained no `DefId` for thing that had been removed. | |
31 | //! | |
32 | //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro | |
5869c6ff XL |
33 | //! defines the `DepKind` enum. Each `DepKind` has its own parameters that are |
34 | //! needed at runtime in order to construct a valid `DepNode` fingerprint. | |
cdc7bbd5 XL |
35 | //! However, only `CompileCodegenUnit` and `CompileMonoItem` are constructed |
36 | //! explicitly (with `make_compile_codegen_unit` cq `make_compile_mono_item`). | |
041b39d2 XL |
37 | //! |
38 | //! Because the macro sees what parameters a given `DepKind` requires, it can | |
39 | //! "infer" some properties for each kind of `DepNode`: | |
40 | //! | |
41 | //! * Whether a `DepNode` of a given kind has any parameters at all. Some | |
ba9703b0 | 42 | //! `DepNode`s could represent global concepts with only one value. |
041b39d2 XL |
43 | //! * Whether it is possible, in principle, to reconstruct a query key from a |
44 | //! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, | |
45 | //! in which case it is possible to map the node's fingerprint back to the | |
46 | //! `DefId` it was computed from. In other cases, too much information gets | |
47 | //! lost during fingerprint computation. | |
48 | //! | |
cdc7bbd5 XL |
49 | //! `make_compile_codegen_unit` and `make_compile_mono_items`, together with |
50 | //! `DepNode::new()`, ensures that only valid `DepNode` instances can be | |
51 | //! constructed. For example, the API does not allow for constructing | |
52 | //! parameterless `DepNode`s with anything other than a zeroed out fingerprint. | |
53 | //! More generally speaking, it relieves the user of the `DepNode` API of | |
54 | //! having to know how to compute the expected fingerprint for a given set of | |
55 | //! node parameters. | |
5869c6ff XL |
56 | //! |
57 | //! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html | |
041b39d2 | 58 | |
cdc7bbd5 | 59 | use crate::mir::mono::MonoItem; |
5869c6ff | 60 | use crate::ty::TyCtxt; |
dfeec247 | 61 | |
ba9703b0 | 62 | use rustc_data_structures::fingerprint::Fingerprint; |
04454e1e | 63 | use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; |
ba9703b0 | 64 | use rustc_hir::definitions::DefPathHash; |
dfeec247 | 65 | use rustc_hir::HirId; |
c295e0f8 | 66 | use rustc_query_system::dep_graph::FingerprintStyle; |
dfeec247 | 67 | use rustc_span::symbol::Symbol; |
dfeec247 | 68 | use std::hash::Hash; |
041b39d2 | 69 | |
ba9703b0 XL |
70 | pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; |
71 | ||
5869c6ff XL |
72 | /// This struct stores metadata about each DepKind. |
73 | /// | |
74 | /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value | |
75 | /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual | |
76 | /// jump table instead of large matches. | |
77 | pub struct DepKindStruct { | |
5869c6ff XL |
78 | /// Anonymous queries cannot be replayed from one compiler invocation to the next. |
79 | /// When their result is needed, it is recomputed. They are useful for fine-grained | |
80 | /// dependency tracking, and caching within one compiler invocation. | |
3c0e092e | 81 | pub is_anon: bool, |
5869c6ff XL |
82 | |
83 | /// Eval-always queries do not track their dependencies, and are always recomputed, even if | |
84 | /// their inputs have not changed since the last compiler invocation. The result is still | |
85 | /// cached within one compiler invocation. | |
3c0e092e | 86 | pub is_eval_always: bool, |
5869c6ff XL |
87 | |
88 | /// Whether the query key can be recovered from the hashed fingerprint. | |
89 | /// See [DepNodeParams] trait for the behaviour of each key type. | |
3c0e092e XL |
90 | pub fingerprint_style: FingerprintStyle, |
91 | ||
92 | /// The red/green evaluation system will try to mark a specific DepNode in the | |
93 | /// dependency graph as green by recursively trying to mark the dependencies of | |
94 | /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` | |
95 | /// where we don't know if it is red or green and we therefore actually have | |
96 | /// to recompute its value in order to find out. Since the only piece of | |
97 | /// information that we have at that point is the `DepNode` we are trying to | |
98 | /// re-evaluate, we need some way to re-run a query from just that. This is what | |
99 | /// `force_from_dep_node()` implements. | |
100 | /// | |
101 | /// In the general case, a `DepNode` consists of a `DepKind` and an opaque | |
102 | /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint | |
103 | /// is usually constructed by computing a stable hash of the query-key that the | |
104 | /// `DepNode` corresponds to. Consequently, it is not in general possible to go | |
105 | /// back from hash to query-key (since hash functions are not reversible). For | |
106 | /// this reason `force_from_dep_node()` is expected to fail from time to time | |
107 | /// because we just cannot find out, from the `DepNode` alone, what the | |
108 | /// corresponding query-key is and therefore cannot re-run the query. | |
109 | /// | |
110 | /// The system deals with this case letting `try_mark_green` fail which forces | |
111 | /// the root query to be re-evaluated. | |
112 | /// | |
113 | /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. | |
114 | /// Fortunately, we can use some contextual information that will allow us to | |
115 | /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we | |
116 | /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a | |
117 | /// valid `DefPathHash`. Since we also always build a huge table that maps every | |
118 | /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have | |
119 | /// everything we need to re-run the query. | |
120 | /// | |
121 | /// Take the `mir_promoted` query as an example. Like many other queries, it | |
122 | /// just has a single parameter: the `DefId` of the item it will compute the | |
123 | /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` | |
124 | /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` | |
125 | /// is actually a `DefPathHash`, and can therefore just look up the corresponding | |
126 | /// `DefId` in `tcx.def_path_hash_to_def_id`. | |
127 | pub force_from_dep_node: Option<fn(tcx: TyCtxt<'_>, dep_node: DepNode) -> bool>, | |
128 | ||
129 | /// Invoke a query to put the on-disk cached value in memory. | |
130 | pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'_>, DepNode)>, | |
5869c6ff XL |
131 | } |
132 | ||
133 | impl DepKind { | |
134 | #[inline(always)] | |
3c0e092e | 135 | pub fn fingerprint_style(self, tcx: TyCtxt<'_>) -> FingerprintStyle { |
5869c6ff | 136 | // Only fetch the DepKindStruct once. |
3c0e092e | 137 | let data = tcx.query_kind(self); |
5869c6ff | 138 | if data.is_anon { |
c295e0f8 | 139 | return FingerprintStyle::Opaque; |
5869c6ff | 140 | } |
3c0e092e | 141 | data.fingerprint_style |
5869c6ff | 142 | } |
5869c6ff XL |
143 | } |
144 | ||
145 | macro_rules! define_dep_nodes { | |
146 | (<$tcx:tt> | |
147 | $( | |
148 | [$($attrs:tt)*] | |
149 | $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* | |
150 | ,)* | |
151 | ) => ( | |
6a06907d XL |
152 | #[macro_export] |
153 | macro_rules! make_dep_kind_array { | |
3c0e092e | 154 | ($mod:ident) => {[ $($mod::$variant()),* ]}; |
6a06907d XL |
155 | } |
156 | ||
3c0e092e | 157 | /// This enum serves as an index into arrays built by `make_dep_kind_array`. |
5869c6ff XL |
158 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] |
159 | #[allow(non_camel_case_types)] | |
160 | pub enum DepKind { | |
161 | $($variant),* | |
162 | } | |
163 | ||
164 | fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> { | |
165 | match label { | |
166 | $(stringify!($variant) => Ok(DepKind::$variant),)* | |
167 | _ => Err(()), | |
ea8adc8c XL |
168 | } |
169 | } | |
170 | ||
171 | /// Contains variant => str representations for constructing | |
172 | /// DepNode groups for tests. | |
173 | #[allow(dead_code, non_upper_case_globals)] | |
174 | pub mod label_strs { | |
175 | $( | |
0731742a | 176 | pub const $variant: &str = stringify!($variant); |
ea8adc8c | 177 | )* |
041b39d2 XL |
178 | } |
179 | ); | |
180 | } | |
181 | ||
532ac7d7 | 182 | rustc_dep_node_append!([define_dep_nodes!][ <'tcx> |
0531ce1d XL |
183 | // We use this for most things when incr. comp. is turned off. |
184 | [] Null, | |
185 | ||
3b2f2976 | 186 | [anon] TraitSelect, |
041b39d2 | 187 | |
5869c6ff | 188 | // WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below. |
e74abb32 | 189 | [] CompileCodegenUnit(Symbol), |
cdc7bbd5 XL |
190 | |
191 | // WARNING: if `MonoItem` is changed, make sure you update `make_compile_mono_item` below. | |
192 | // Only used by rustc_codegen_cranelift | |
193 | [] CompileMonoItem(MonoItem), | |
532ac7d7 XL |
194 | ]); |
195 | ||
5869c6ff XL |
196 | // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. |
197 | // Be very careful changing this type signature! | |
923072b8 | 198 | pub(crate) fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode { |
5869c6ff XL |
199 | DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name) |
200 | } | |
201 | ||
cdc7bbd5 XL |
202 | // WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys. |
203 | // Be very careful changing this type signature! | |
923072b8 FG |
204 | pub(crate) fn make_compile_mono_item<'tcx>( |
205 | tcx: TyCtxt<'tcx>, | |
206 | mono_item: &MonoItem<'tcx>, | |
207 | ) -> DepNode { | |
cdc7bbd5 XL |
208 | DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) |
209 | } | |
210 | ||
5869c6ff XL |
211 | pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>; |
212 | ||
213 | // We keep a lot of `DepNode`s in memory during compilation. It's not | |
214 | // required that their size stay the same, but we don't want to change | |
215 | // it inadvertently. This assert just ensures we're aware of any change. | |
216 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | |
17df50a5 | 217 | static_assert_size!(DepNode, 18); |
5869c6ff XL |
218 | |
219 | #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] | |
220 | static_assert_size!(DepNode, 24); | |
221 | ||
222 | pub trait DepNodeExt: Sized { | |
223 | /// Construct a DepNode from the given DepKind and DefPathHash. This | |
224 | /// method will assert that the given DepKind actually requires a | |
225 | /// single DefId/DefPathHash parameter. | |
3c0e092e | 226 | fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> Self; |
5869c6ff XL |
227 | |
228 | /// Extracts the DefId corresponding to this DepNode. This will work | |
229 | /// if two conditions are met: | |
230 | /// | |
231 | /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and | |
232 | /// 2. the item that the DefPath refers to exists in the current tcx. | |
233 | /// | |
234 | /// Condition (1) is determined by the DepKind variant of the | |
235 | /// DepNode. Condition (2) might not be fulfilled if a DepNode | |
236 | /// refers to something from the previous compilation session that | |
237 | /// has been removed. | |
238 | fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>; | |
239 | ||
240 | /// Used in testing | |
3c0e092e XL |
241 | fn from_label_string( |
242 | tcx: TyCtxt<'_>, | |
243 | label: &str, | |
244 | def_path_hash: DefPathHash, | |
245 | ) -> Result<Self, ()>; | |
5869c6ff XL |
246 | |
247 | /// Used in testing | |
248 | fn has_label_string(label: &str) -> bool; | |
249 | } | |
250 | ||
251 | impl DepNodeExt for DepNode { | |
252 | /// Construct a DepNode from the given DepKind and DefPathHash. This | |
253 | /// method will assert that the given DepKind actually requires a | |
254 | /// single DefId/DefPathHash parameter. | |
3c0e092e XL |
255 | fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode { |
256 | debug_assert!(kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash); | |
5869c6ff XL |
257 | DepNode { kind, hash: def_path_hash.0.into() } |
258 | } | |
259 | ||
260 | /// Extracts the DefId corresponding to this DepNode. This will work | |
261 | /// if two conditions are met: | |
262 | /// | |
263 | /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and | |
264 | /// 2. the item that the DefPath refers to exists in the current tcx. | |
265 | /// | |
266 | /// Condition (1) is determined by the DepKind variant of the | |
267 | /// DepNode. Condition (2) might not be fulfilled if a DepNode | |
268 | /// refers to something from the previous compilation session that | |
269 | /// has been removed. | |
a2a8927a | 270 | fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> { |
3c0e092e | 271 | if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { |
5099ac24 FG |
272 | Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || { |
273 | panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash) | |
274 | })) | |
5869c6ff XL |
275 | } else { |
276 | None | |
277 | } | |
278 | } | |
279 | ||
280 | /// Used in testing | |
3c0e092e XL |
281 | fn from_label_string( |
282 | tcx: TyCtxt<'_>, | |
283 | label: &str, | |
284 | def_path_hash: DefPathHash, | |
285 | ) -> Result<DepNode, ()> { | |
5869c6ff XL |
286 | let kind = dep_kind_from_label_string(label)?; |
287 | ||
3c0e092e | 288 | match kind.fingerprint_style(tcx) { |
c295e0f8 | 289 | FingerprintStyle::Opaque => Err(()), |
3c0e092e XL |
290 | FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)), |
291 | FingerprintStyle::DefPathHash => { | |
292 | Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind)) | |
c295e0f8 | 293 | } |
5869c6ff XL |
294 | } |
295 | } | |
296 | ||
297 | /// Used in testing | |
298 | fn has_label_string(label: &str) -> bool { | |
299 | dep_kind_from_label_string(label).is_ok() | |
300 | } | |
301 | } | |
302 | ||
303 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () { | |
304 | #[inline(always)] | |
c295e0f8 XL |
305 | fn fingerprint_style() -> FingerprintStyle { |
306 | FingerprintStyle::Unit | |
5869c6ff XL |
307 | } |
308 | ||
3c0e092e | 309 | #[inline(always)] |
5869c6ff XL |
310 | fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { |
311 | Fingerprint::ZERO | |
312 | } | |
313 | ||
3c0e092e | 314 | #[inline(always)] |
5869c6ff XL |
315 | fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> { |
316 | Some(()) | |
317 | } | |
318 | } | |
319 | ||
ba9703b0 | 320 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId { |
5869c6ff | 321 | #[inline(always)] |
c295e0f8 XL |
322 | fn fingerprint_style() -> FingerprintStyle { |
323 | FingerprintStyle::DefPathHash | |
f035d41b | 324 | } |
041b39d2 | 325 | |
3c0e092e | 326 | #[inline(always)] |
ba9703b0 | 327 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
c295e0f8 | 328 | tcx.def_path_hash(*self).0 |
041b39d2 XL |
329 | } |
330 | ||
3c0e092e | 331 | #[inline(always)] |
dc9dc135 | 332 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
532ac7d7 | 333 | tcx.def_path_str(*self) |
041b39d2 | 334 | } |
74b04a01 | 335 | |
3c0e092e | 336 | #[inline(always)] |
74b04a01 XL |
337 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
338 | dep_node.extract_def_id(tcx) | |
339 | } | |
041b39d2 | 340 | } |
9e0c209e | 341 | |
ba9703b0 | 342 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId { |
5869c6ff | 343 | #[inline(always)] |
c295e0f8 XL |
344 | fn fingerprint_style() -> FingerprintStyle { |
345 | FingerprintStyle::DefPathHash | |
f035d41b | 346 | } |
ea8adc8c | 347 | |
3c0e092e | 348 | #[inline(always)] |
ba9703b0 XL |
349 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
350 | self.to_def_id().to_fingerprint(tcx) | |
ea8adc8c XL |
351 | } |
352 | ||
3c0e092e | 353 | #[inline(always)] |
dc9dc135 | 354 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
ba9703b0 | 355 | self.to_def_id().to_debug_str(tcx) |
ea8adc8c | 356 | } |
74b04a01 | 357 | |
3c0e092e | 358 | #[inline(always)] |
74b04a01 | 359 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
ba9703b0 | 360 | dep_node.extract_def_id(tcx).map(|id| id.expect_local()) |
74b04a01 | 361 | } |
ea8adc8c XL |
362 | } |
363 | ||
ba9703b0 | 364 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum { |
5869c6ff | 365 | #[inline(always)] |
c295e0f8 XL |
366 | fn fingerprint_style() -> FingerprintStyle { |
367 | FingerprintStyle::DefPathHash | |
f035d41b | 368 | } |
ea8adc8c | 369 | |
3c0e092e | 370 | #[inline(always)] |
ba9703b0 | 371 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
04454e1e | 372 | let def_id = self.as_def_id(); |
fc512014 | 373 | def_id.to_fingerprint(tcx) |
ea8adc8c XL |
374 | } |
375 | ||
3c0e092e | 376 | #[inline(always)] |
dc9dc135 | 377 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
60c5eb7d | 378 | tcx.crate_name(*self).to_string() |
ea8adc8c | 379 | } |
74b04a01 | 380 | |
3c0e092e | 381 | #[inline(always)] |
74b04a01 XL |
382 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
383 | dep_node.extract_def_id(tcx).map(|id| id.krate) | |
384 | } | |
ea8adc8c XL |
385 | } |
386 | ||
ba9703b0 | 387 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) { |
5869c6ff | 388 | #[inline(always)] |
c295e0f8 XL |
389 | fn fingerprint_style() -> FingerprintStyle { |
390 | FingerprintStyle::Opaque | |
f035d41b | 391 | } |
041b39d2 XL |
392 | |
393 | // We actually would not need to specialize the implementation of this | |
394 | // method but it's faster to combine the hashes than to instantiate a full | |
395 | // hashing context and stable-hashing state. | |
3c0e092e | 396 | #[inline(always)] |
ba9703b0 | 397 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
041b39d2 XL |
398 | let (def_id_0, def_id_1) = *self; |
399 | ||
400 | let def_path_hash_0 = tcx.def_path_hash(def_id_0); | |
401 | let def_path_hash_1 = tcx.def_path_hash(def_id_1); | |
402 | ||
403 | def_path_hash_0.0.combine(def_path_hash_1.0) | |
404 | } | |
405 | ||
3c0e092e | 406 | #[inline(always)] |
dc9dc135 | 407 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
041b39d2 XL |
408 | let (def_id_0, def_id_1) = *self; |
409 | ||
dfeec247 | 410 | format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1)) |
041b39d2 XL |
411 | } |
412 | } | |
413 | ||
ba9703b0 | 414 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId { |
5869c6ff | 415 | #[inline(always)] |
c295e0f8 XL |
416 | fn fingerprint_style() -> FingerprintStyle { |
417 | FingerprintStyle::Opaque | |
f035d41b | 418 | } |
041b39d2 XL |
419 | |
420 | // We actually would not need to specialize the implementation of this | |
421 | // method but it's faster to combine the hashes than to instantiate a full | |
422 | // hashing context and stable-hashing state. | |
3c0e092e | 423 | #[inline(always)] |
ba9703b0 | 424 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
dfeec247 | 425 | let HirId { owner, local_id } = *self; |
041b39d2 | 426 | |
ba9703b0 | 427 | let def_path_hash = tcx.def_path_hash(owner.to_def_id()); |
a1dfa0c6 | 428 | let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); |
041b39d2 | 429 | |
ea8adc8c | 430 | def_path_hash.0.combine(local_id) |
54a0048b SL |
431 | } |
432 | } |