]>
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! | |
198 | crate fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode { | |
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! | |
a2a8927a | 204 | crate fn make_compile_mono_item<'tcx>(tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>) -> DepNode { |
cdc7bbd5 XL |
205 | DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) |
206 | } | |
207 | ||
5869c6ff XL |
208 | pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>; |
209 | ||
210 | // We keep a lot of `DepNode`s in memory during compilation. It's not | |
211 | // required that their size stay the same, but we don't want to change | |
212 | // it inadvertently. This assert just ensures we're aware of any change. | |
213 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | |
17df50a5 | 214 | static_assert_size!(DepNode, 18); |
5869c6ff XL |
215 | |
216 | #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] | |
217 | static_assert_size!(DepNode, 24); | |
218 | ||
219 | pub trait DepNodeExt: Sized { | |
220 | /// Construct a DepNode from the given DepKind and DefPathHash. This | |
221 | /// method will assert that the given DepKind actually requires a | |
222 | /// single DefId/DefPathHash parameter. | |
3c0e092e | 223 | fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> Self; |
5869c6ff XL |
224 | |
225 | /// Extracts the DefId corresponding to this DepNode. This will work | |
226 | /// if two conditions are met: | |
227 | /// | |
228 | /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and | |
229 | /// 2. the item that the DefPath refers to exists in the current tcx. | |
230 | /// | |
231 | /// Condition (1) is determined by the DepKind variant of the | |
232 | /// DepNode. Condition (2) might not be fulfilled if a DepNode | |
233 | /// refers to something from the previous compilation session that | |
234 | /// has been removed. | |
235 | fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>; | |
236 | ||
237 | /// Used in testing | |
3c0e092e XL |
238 | fn from_label_string( |
239 | tcx: TyCtxt<'_>, | |
240 | label: &str, | |
241 | def_path_hash: DefPathHash, | |
242 | ) -> Result<Self, ()>; | |
5869c6ff XL |
243 | |
244 | /// Used in testing | |
245 | fn has_label_string(label: &str) -> bool; | |
246 | } | |
247 | ||
248 | impl DepNodeExt for DepNode { | |
249 | /// Construct a DepNode from the given DepKind and DefPathHash. This | |
250 | /// method will assert that the given DepKind actually requires a | |
251 | /// single DefId/DefPathHash parameter. | |
3c0e092e XL |
252 | fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode { |
253 | debug_assert!(kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash); | |
5869c6ff XL |
254 | DepNode { kind, hash: def_path_hash.0.into() } |
255 | } | |
256 | ||
257 | /// Extracts the DefId corresponding to this DepNode. This will work | |
258 | /// if two conditions are met: | |
259 | /// | |
260 | /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and | |
261 | /// 2. the item that the DefPath refers to exists in the current tcx. | |
262 | /// | |
263 | /// Condition (1) is determined by the DepKind variant of the | |
264 | /// DepNode. Condition (2) might not be fulfilled if a DepNode | |
265 | /// refers to something from the previous compilation session that | |
266 | /// has been removed. | |
a2a8927a | 267 | fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> { |
3c0e092e | 268 | if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { |
5099ac24 FG |
269 | Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || { |
270 | panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash) | |
271 | })) | |
5869c6ff XL |
272 | } else { |
273 | None | |
274 | } | |
275 | } | |
276 | ||
277 | /// Used in testing | |
3c0e092e XL |
278 | fn from_label_string( |
279 | tcx: TyCtxt<'_>, | |
280 | label: &str, | |
281 | def_path_hash: DefPathHash, | |
282 | ) -> Result<DepNode, ()> { | |
5869c6ff XL |
283 | let kind = dep_kind_from_label_string(label)?; |
284 | ||
3c0e092e | 285 | match kind.fingerprint_style(tcx) { |
c295e0f8 | 286 | FingerprintStyle::Opaque => Err(()), |
3c0e092e XL |
287 | FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)), |
288 | FingerprintStyle::DefPathHash => { | |
289 | Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind)) | |
c295e0f8 | 290 | } |
5869c6ff XL |
291 | } |
292 | } | |
293 | ||
294 | /// Used in testing | |
295 | fn has_label_string(label: &str) -> bool { | |
296 | dep_kind_from_label_string(label).is_ok() | |
297 | } | |
298 | } | |
299 | ||
300 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () { | |
301 | #[inline(always)] | |
c295e0f8 XL |
302 | fn fingerprint_style() -> FingerprintStyle { |
303 | FingerprintStyle::Unit | |
5869c6ff XL |
304 | } |
305 | ||
3c0e092e | 306 | #[inline(always)] |
5869c6ff XL |
307 | fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { |
308 | Fingerprint::ZERO | |
309 | } | |
310 | ||
3c0e092e | 311 | #[inline(always)] |
5869c6ff XL |
312 | fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> { |
313 | Some(()) | |
314 | } | |
315 | } | |
316 | ||
ba9703b0 | 317 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId { |
5869c6ff | 318 | #[inline(always)] |
c295e0f8 XL |
319 | fn fingerprint_style() -> FingerprintStyle { |
320 | FingerprintStyle::DefPathHash | |
f035d41b | 321 | } |
041b39d2 | 322 | |
3c0e092e | 323 | #[inline(always)] |
ba9703b0 | 324 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
c295e0f8 | 325 | tcx.def_path_hash(*self).0 |
041b39d2 XL |
326 | } |
327 | ||
3c0e092e | 328 | #[inline(always)] |
dc9dc135 | 329 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
532ac7d7 | 330 | tcx.def_path_str(*self) |
041b39d2 | 331 | } |
74b04a01 | 332 | |
3c0e092e | 333 | #[inline(always)] |
74b04a01 XL |
334 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
335 | dep_node.extract_def_id(tcx) | |
336 | } | |
041b39d2 | 337 | } |
9e0c209e | 338 | |
ba9703b0 | 339 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId { |
5869c6ff | 340 | #[inline(always)] |
c295e0f8 XL |
341 | fn fingerprint_style() -> FingerprintStyle { |
342 | FingerprintStyle::DefPathHash | |
f035d41b | 343 | } |
ea8adc8c | 344 | |
3c0e092e | 345 | #[inline(always)] |
ba9703b0 XL |
346 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
347 | self.to_def_id().to_fingerprint(tcx) | |
ea8adc8c XL |
348 | } |
349 | ||
3c0e092e | 350 | #[inline(always)] |
dc9dc135 | 351 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
ba9703b0 | 352 | self.to_def_id().to_debug_str(tcx) |
ea8adc8c | 353 | } |
74b04a01 | 354 | |
3c0e092e | 355 | #[inline(always)] |
74b04a01 | 356 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
ba9703b0 | 357 | dep_node.extract_def_id(tcx).map(|id| id.expect_local()) |
74b04a01 | 358 | } |
ea8adc8c XL |
359 | } |
360 | ||
ba9703b0 | 361 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum { |
5869c6ff | 362 | #[inline(always)] |
c295e0f8 XL |
363 | fn fingerprint_style() -> FingerprintStyle { |
364 | FingerprintStyle::DefPathHash | |
f035d41b | 365 | } |
ea8adc8c | 366 | |
3c0e092e | 367 | #[inline(always)] |
ba9703b0 | 368 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
04454e1e | 369 | let def_id = self.as_def_id(); |
fc512014 | 370 | def_id.to_fingerprint(tcx) |
ea8adc8c XL |
371 | } |
372 | ||
3c0e092e | 373 | #[inline(always)] |
dc9dc135 | 374 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
60c5eb7d | 375 | tcx.crate_name(*self).to_string() |
ea8adc8c | 376 | } |
74b04a01 | 377 | |
3c0e092e | 378 | #[inline(always)] |
74b04a01 XL |
379 | fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { |
380 | dep_node.extract_def_id(tcx).map(|id| id.krate) | |
381 | } | |
ea8adc8c XL |
382 | } |
383 | ||
ba9703b0 | 384 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) { |
5869c6ff | 385 | #[inline(always)] |
c295e0f8 XL |
386 | fn fingerprint_style() -> FingerprintStyle { |
387 | FingerprintStyle::Opaque | |
f035d41b | 388 | } |
041b39d2 XL |
389 | |
390 | // We actually would not need to specialize the implementation of this | |
391 | // method but it's faster to combine the hashes than to instantiate a full | |
392 | // hashing context and stable-hashing state. | |
3c0e092e | 393 | #[inline(always)] |
ba9703b0 | 394 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
041b39d2 XL |
395 | let (def_id_0, def_id_1) = *self; |
396 | ||
397 | let def_path_hash_0 = tcx.def_path_hash(def_id_0); | |
398 | let def_path_hash_1 = tcx.def_path_hash(def_id_1); | |
399 | ||
400 | def_path_hash_0.0.combine(def_path_hash_1.0) | |
401 | } | |
402 | ||
3c0e092e | 403 | #[inline(always)] |
dc9dc135 | 404 | fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { |
041b39d2 XL |
405 | let (def_id_0, def_id_1) = *self; |
406 | ||
dfeec247 | 407 | format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1)) |
041b39d2 XL |
408 | } |
409 | } | |
410 | ||
ba9703b0 | 411 | impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId { |
5869c6ff | 412 | #[inline(always)] |
c295e0f8 XL |
413 | fn fingerprint_style() -> FingerprintStyle { |
414 | FingerprintStyle::Opaque | |
f035d41b | 415 | } |
041b39d2 XL |
416 | |
417 | // We actually would not need to specialize the implementation of this | |
418 | // method but it's faster to combine the hashes than to instantiate a full | |
419 | // hashing context and stable-hashing state. | |
3c0e092e | 420 | #[inline(always)] |
ba9703b0 | 421 | fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { |
dfeec247 | 422 | let HirId { owner, local_id } = *self; |
041b39d2 | 423 | |
ba9703b0 | 424 | let def_path_hash = tcx.def_path_hash(owner.to_def_id()); |
a1dfa0c6 | 425 | let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); |
041b39d2 | 426 | |
ea8adc8c | 427 | def_path_hash.0.combine(local_id) |
54a0048b SL |
428 | } |
429 | } |