]> git.lizzy.rs Git - rust.git/blob - src/librustc/dep_graph/dep_node.rs
Improve how warnings are displayed
[rust.git] / src / librustc / dep_graph / dep_node.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 //! This module defines the `DepNode` type which the compiler uses to represent
13 //! nodes in the dependency graph. A `DepNode` consists of a `DepKind` (which
14 //! specifies the kind of thing it represents, like a piece of HIR, MIR, etc)
15 //! and a `Fingerprint`, a 128 bit hash value the exact meaning of which
16 //! depends on the node's `DepKind`. Together, the kind and the fingerprint
17 //! fully identify a dependency node, even across multiple compilation sessions.
18 //! In other words, the value of the fingerprint does not depend on anything
19 //! that is specific to a given compilation session, like an unpredictable
20 //! interning key (e.g. NodeId, DefId, Symbol) or the numeric value of a
21 //! pointer. The concept behind this could be compared to how git commit hashes
22 //! uniquely identify a given commit and has a few advantages:
23 //!
24 //! * A `DepNode` can simply be serialized to disk and loaded in another session
25 //!   without the need to do any "rebasing (like we have to do for Spans and
26 //!   NodeIds) or "retracing" like we had to do for `DefId` in earlier
27 //!   implementations of the dependency graph.
28 //! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to
29 //!   implement `Copy`, `Sync`, `Send`, `Freeze`, etc.
30 //! * Since we just have a bit pattern, `DepNode` can be mapped from disk into
31 //!   memory without any post-processing (e.g. "abomination-style" pointer
32 //!   reconstruction).
33 //! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that
34 //!   refer to things that do not exist anymore. In previous implementations
35 //!   `DepNode` contained a `DefId`. A `DepNode` referring to something that
36 //!   had been removed between the previous and the current compilation session
37 //!   could not be instantiated because the current compilation session
38 //!   contained no `DefId` for thing that had been removed.
39 //!
40 //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro
41 //! defines the `DepKind` enum and a corresponding `DepConstructor` enum. The
42 //! `DepConstructor` enum links a `DepKind` to the parameters that are needed at
43 //! runtime in order to construct a valid `DepNode` fingerprint.
44 //!
45 //! Because the macro sees what parameters a given `DepKind` requires, it can
46 //! "infer" some properties for each kind of `DepNode`:
47 //!
48 //! * Whether a `DepNode` of a given kind has any parameters at all. Some
49 //!   `DepNode`s, like `Krate`, represent global concepts with only one value.
50 //! * Whether it is possible, in principle, to reconstruct a query key from a
51 //!   given `DepNode`. Many `DepKind`s only require a single `DefId` parameter,
52 //!   in which case it is possible to map the node's fingerprint back to the
53 //!   `DefId` it was computed from. In other cases, too much information gets
54 //!   lost during fingerprint computation.
55 //!
56 //! The `DepConstructor` enum, together with `DepNode::new()` ensures that only
57 //! valid `DepNode` instances can be constructed. For example, the API does not
58 //! allow for constructing parameterless `DepNode`s with anything other
59 //! than a zeroed out fingerprint. More generally speaking, it relieves the
60 //! user of the `DepNode` API of having to know how to compute the expected
61 //! fingerprint for a given set of node parameters.
62
63 use hir::def_id::{CrateNum, DefId, DefIndex};
64 use hir::map::DefPathHash;
65 use hir::{HirId, ItemLocalId};
66
67 use ich::Fingerprint;
68 use ty::{TyCtxt, Instance, InstanceDef};
69 use ty::fast_reject::SimplifiedType;
70 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
71 use ich::StableHashingContext;
72 use std::fmt;
73 use std::hash::Hash;
74
75 // erase!() just makes tokens go away. It's used to specify which macro argument
76 // is repeated (i.e. which sub-expression of the macro we are in) but don't need
77 // to actually use any of the arguments.
78 macro_rules! erase {
79     ($x:tt) => ({})
80 }
81
82 macro_rules! anon_attr_to_bool {
83     (anon) => (true)
84 }
85
86 macro_rules! define_dep_nodes {
87     (<$tcx:tt>
88     $(
89         [$($anon:ident)*]
90         $variant:ident $(( $($tuple_arg:tt),* ))*
91                        $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })*
92       ,)*
93     ) => (
94         #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
95                  RustcEncodable, RustcDecodable)]
96         pub enum DepKind {
97             $($variant),*
98         }
99
100         impl DepKind {
101             #[allow(unreachable_code)]
102             #[inline]
103             pub fn can_reconstruct_query_key<$tcx>(&self) -> bool {
104                 match *self {
105                     $(
106                         DepKind :: $variant => {
107                             $(return !anon_attr_to_bool!($anon);)*
108
109                             // tuple args
110                             $({
111                                 return <( $($tuple_arg,)* ) as DepNodeParams>
112                                     ::CAN_RECONSTRUCT_QUERY_KEY;
113                             })*
114
115                             // struct args
116                             $({
117
118                                 return <( $($struct_arg_ty,)* ) as DepNodeParams>
119                                     ::CAN_RECONSTRUCT_QUERY_KEY;
120                             })*
121
122                             true
123                         }
124                     )*
125                 }
126             }
127
128             #[allow(unreachable_code)]
129             #[inline]
130             pub fn is_anon<$tcx>(&self) -> bool {
131                 match *self {
132                     $(
133                         DepKind :: $variant => {
134                             $(return anon_attr_to_bool!($anon);)*
135                             false
136                         }
137                     )*
138                 }
139             }
140
141             #[allow(unreachable_code)]
142             #[inline]
143             pub fn has_params(&self) -> bool {
144                 match *self {
145                     $(
146                         DepKind :: $variant => {
147                             // tuple args
148                             $({
149                                 $(erase!($tuple_arg);)*
150                                 return true;
151                             })*
152
153                             // struct args
154                             $({
155                                 $(erase!($struct_arg_name);)*
156                                 return true;
157                             })*
158
159                             false
160                         }
161                     )*
162                 }
163             }
164         }
165
166         pub enum DepConstructor<$tcx> {
167             $(
168                 $variant $(( $($tuple_arg),* ))*
169                          $({ $($struct_arg_name : $struct_arg_ty),* })*
170             ),*
171         }
172
173         #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
174                  RustcEncodable, RustcDecodable)]
175         pub struct DepNode {
176             pub kind: DepKind,
177             pub hash: Fingerprint,
178         }
179
180         impl DepNode {
181             #[allow(unreachable_code, non_snake_case)]
182             pub fn new<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
183                                        dep: DepConstructor<'gcx>)
184                                        -> DepNode
185                 where 'gcx: 'a + 'tcx,
186                       'tcx: 'a
187             {
188                 match dep {
189                     $(
190                         DepConstructor :: $variant $(( $($tuple_arg),* ))*
191                                                    $({ $($struct_arg_name),* })*
192                             =>
193                         {
194                             // tuple args
195                             $({
196                                 let tupled_args = ( $($tuple_arg,)* );
197                                 let hash = DepNodeParams::to_fingerprint(&tupled_args,
198                                                                          tcx);
199                                 let dep_node = DepNode {
200                                     kind: DepKind::$variant,
201                                     hash
202                                 };
203
204                                 if cfg!(debug_assertions) &&
205                                    !dep_node.kind.can_reconstruct_query_key() &&
206                                    (tcx.sess.opts.debugging_opts.incremental_info ||
207                                     tcx.sess.opts.debugging_opts.query_dep_graph)
208                                 {
209                                     tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
210                                         tupled_args.to_debug_str(tcx)
211                                     });
212                                 }
213
214                                 return dep_node;
215                             })*
216
217                             // struct args
218                             $({
219                                 let tupled_args = ( $($struct_arg_name,)* );
220                                 let hash = DepNodeParams::to_fingerprint(&tupled_args,
221                                                                          tcx);
222                                 let dep_node = DepNode {
223                                     kind: DepKind::$variant,
224                                     hash
225                                 };
226
227                                 if cfg!(debug_assertions) &&
228                                    !dep_node.kind.can_reconstruct_query_key() &&
229                                    (tcx.sess.opts.debugging_opts.incremental_info ||
230                                     tcx.sess.opts.debugging_opts.query_dep_graph)
231                                 {
232                                     tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
233                                         tupled_args.to_debug_str(tcx)
234                                     });
235                                 }
236
237                                 return dep_node;
238                             })*
239
240                             DepNode {
241                                 kind: DepKind::$variant,
242                                 hash: Fingerprint::zero(),
243                             }
244                         }
245                     )*
246                 }
247             }
248
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.
252             #[inline]
253             pub fn from_def_path_hash(kind: DepKind,
254                                       def_path_hash: DefPathHash)
255                                       -> DepNode {
256                 assert!(kind.can_reconstruct_query_key() && kind.has_params());
257                 DepNode {
258                     kind,
259                     hash: def_path_hash.0,
260                 }
261             }
262
263             /// Create a new, parameterless DepNode. This method will assert
264             /// that the DepNode corresponding to the given DepKind actually
265             /// does not require any parameters.
266             #[inline]
267             pub fn new_no_params(kind: DepKind) -> DepNode {
268                 assert!(!kind.has_params());
269                 DepNode {
270                     kind,
271                     hash: Fingerprint::zero(),
272                 }
273             }
274
275             /// Extract the DefId corresponding to this DepNode. This will work
276             /// if two conditions are met:
277             ///
278             /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
279             /// 2. the item that the DefPath refers to exists in the current tcx.
280             ///
281             /// Condition (1) is determined by the DepKind variant of the
282             /// DepNode. Condition (2) might not be fulfilled if a DepNode
283             /// refers to something from the previous compilation session that
284             /// has been removed.
285             #[inline]
286             pub fn extract_def_id(&self, tcx: TyCtxt) -> Option<DefId> {
287                 if self.kind.can_reconstruct_query_key() {
288                     let def_path_hash = DefPathHash(self.hash);
289                     if let Some(ref def_path_map) = tcx.def_path_hash_to_def_id.as_ref() {
290                         def_path_map.get(&def_path_hash).cloned()
291                     } else {
292                        None
293                     }
294                 } else {
295                     None
296                 }
297             }
298
299             /// Used in testing
300             pub fn from_label_string(label: &str,
301                                      def_path_hash: DefPathHash)
302                                      -> Result<DepNode, ()> {
303                 let kind = match label {
304                     $(
305                         stringify!($variant) => DepKind::$variant,
306                     )*
307                     _ => return Err(()),
308                 };
309
310                 if !kind.can_reconstruct_query_key() {
311                     return Err(());
312                 }
313
314                 if kind.has_params() {
315                     Ok(def_path_hash.to_dep_node(kind))
316                 } else {
317                     Ok(DepNode::new_no_params(kind))
318                 }
319             }
320         }
321     );
322 }
323
324 impl fmt::Debug for DepNode {
325     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
326         write!(f, "{:?}", self.kind)?;
327
328         if !self.kind.has_params() {
329             return Ok(());
330         }
331
332         write!(f, "(")?;
333
334         ::ty::tls::with_opt(|opt_tcx| {
335             if let Some(tcx) = opt_tcx {
336                 if let Some(def_id) = self.extract_def_id(tcx) {
337                     write!(f, "{}", tcx.item_path_str(def_id))?;
338                 } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) {
339                     write!(f, "{}", s)?;
340                 } else {
341                     write!(f, "{:?}", self.hash)?;
342                 }
343             } else {
344                 write!(f, "{:?}", self.hash)?;
345             }
346             Ok(())
347         })?;
348
349         write!(f, ")")
350     }
351 }
352
353
354 impl DefPathHash {
355     #[inline]
356     pub fn to_dep_node(self, kind: DepKind) -> DepNode {
357         DepNode::from_def_path_hash(kind, self)
358     }
359 }
360
361 impl DefId {
362     #[inline]
363     pub fn to_dep_node(self, tcx: TyCtxt, kind: DepKind) -> DepNode {
364         DepNode::from_def_path_hash(kind, tcx.def_path_hash(self))
365     }
366 }
367
368 define_dep_nodes!( <'tcx>
369     // Represents the `Krate` as a whole (the `hir::Krate` value) (as
370     // distinct from the krate module). This is basically a hash of
371     // the entire krate, so if you read from `Krate` (e.g., by calling
372     // `tcx.hir.krate()`), we will have to assume that any change
373     // means that you need to be recompiled. This is because the
374     // `Krate` value gives you access to all other items. To avoid
375     // this fate, do not call `tcx.hir.krate()`; instead, prefer
376     // wrappers like `tcx.visit_all_items_in_krate()`.  If there is no
377     // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain
378     // access to the krate, but you must remember to add suitable
379     // edges yourself for the individual items that you read.
380     [] Krate,
381
382     // Represents the HIR node with the given node-id
383     [] Hir(DefId),
384
385     // Represents the body of a function or method. The def-id is that of the
386     // function/method.
387     [] HirBody(DefId),
388
389     // Represents the metadata for a given HIR node, typically found
390     // in an extern crate.
391     [] MetaData(DefId),
392
393     // Represents some artifact that we save to disk. Note that these
394     // do not have a def-id as part of their identifier.
395     [] WorkProduct(WorkProductId),
396
397     // Represents different phases in the compiler.
398     [] RegionScopeTree(DefId),
399     [] Coherence,
400     [] CoherenceInherentImplOverlapCheck,
401     [] Resolve,
402     [] CoherenceCheckTrait(DefId),
403     [] PrivacyAccessLevels(CrateNum),
404
405     // Represents the MIR for a fn; also used as the task node for
406     // things read/modify that MIR.
407     [] MirConstQualif(DefId),
408     [] MirConst(DefId),
409     [] MirValidated(DefId),
410     [] MirOptimized(DefId),
411     [] MirShim { instance_def: InstanceDef<'tcx> },
412
413     [] BorrowCheckKrate,
414     [] BorrowCheck(DefId),
415     [] MirBorrowCheck(DefId),
416
417     [] RvalueCheck(DefId),
418     [] Reachability,
419     [] MirKeys,
420     [] TransWriteMetadata,
421     [] CrateVariances,
422
423     // Nodes representing bits of computed IR in the tcx. Each shared
424     // table in the tcx (or elsewhere) maps to one of these
425     // nodes.
426     [] AssociatedItems(DefId),
427     [] TypeOfItem(DefId),
428     [] GenericsOfItem(DefId),
429     [] PredicatesOfItem(DefId),
430     [] SuperPredicatesOfItem(DefId),
431     [] TraitDefOfItem(DefId),
432     [] AdtDefOfItem(DefId),
433     [] IsDefaultImpl(DefId),
434     [] ImplTraitRef(DefId),
435     [] ImplPolarity(DefId),
436     [] ClosureKind(DefId),
437     [] FnSignature(DefId),
438     [] GenSignature(DefId),
439     [] CoerceUnsizedInfo(DefId),
440
441     [] ItemVarianceConstraints(DefId),
442     [] ItemVariances(DefId),
443     [] IsConstFn(DefId),
444     [] IsForeignItem(DefId),
445     [] TypeParamPredicates { item_id: DefId, param_id: DefId },
446     [] SizedConstraint(DefId),
447     [] DtorckConstraint(DefId),
448     [] AdtDestructor(DefId),
449     [] AssociatedItemDefIds(DefId),
450     [] InherentImpls(DefId),
451     [] TypeckBodiesKrate,
452     [] TypeckTables(DefId),
453     [] HasTypeckTables(DefId),
454     [anon] ConstEval,
455     [] SymbolName(DefId),
456     [] InstanceSymbolName { instance: Instance<'tcx> },
457     [] SpecializationGraph(DefId),
458     [] ObjectSafety(DefId),
459
460     [anon] IsCopy,
461     [anon] IsSized,
462     [anon] IsFreeze,
463     [anon] NeedsDrop,
464     [anon] Layout,
465
466     // The set of impls for a given trait.
467     [] TraitImpls(DefId),
468     [] RelevantTraitImpls(DefId, SimplifiedType),
469
470     [] AllLocalTraitImpls,
471
472     // Nodes representing caches. To properly handle a true cache, we
473     // don't use a DepTrackingMap, but rather we push a task node.
474     // Otherwise the write into the map would be incorrectly
475     // attributed to the first task that happened to fill the cache,
476     // which would yield an overly conservative dep-graph.
477     [] TraitItems(DefId),
478     [] ReprHints(DefId),
479
480     // Trait selection cache is a little funny. Given a trait
481     // reference like `Foo: SomeTrait<Bar>`, there could be
482     // arbitrarily many def-ids to map on in there (e.g., `Foo`,
483     // `SomeTrait`, `Bar`). We could have a vector of them, but it
484     // requires heap-allocation, and trait sel in general can be a
485     // surprisingly hot path. So instead we pick two def-ids: the
486     // trait def-id, and the first def-id in the input types. If there
487     // is no def-id in the input types, then we use the trait def-id
488     // again. So for example:
489     //
490     // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
491     // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
492     // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
493     // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
494     // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
495     // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
496     // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
497     // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
498     // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
499     //
500     // You can see that we map many trait refs to the same
501     // trait-select node.  This is not a problem, it just means
502     // imprecision in our dep-graph tracking.  The important thing is
503     // that for any given trait-ref, we always map to the **same**
504     // trait-select node.
505     [anon] TraitSelect,
506
507     // For proj. cache, we just keep a list of all def-ids, since it is
508     // not a hotspot.
509     [] ProjectionCache { def_ids: DefIdList },
510
511     [] ParamEnv(DefId),
512     [] DescribeDef(DefId),
513     [] DefSpan(DefId),
514     [] LookupStability(DefId),
515     [] LookupDeprecationEntry(DefId),
516     [] ItemBodyNestedBodies(DefId),
517     [] ConstIsRvaluePromotableToStatic(DefId),
518     [] ImplParent(DefId),
519     [] TraitOfItem(DefId),
520     [] IsExportedSymbol(DefId),
521     [] IsMirAvailable(DefId),
522     [] ItemAttrs(DefId),
523     [] FnArgNames(DefId),
524     [] DylibDepFormats(CrateNum),
525     [] IsPanicRuntime(CrateNum),
526     [] IsCompilerBuiltins(CrateNum),
527     [] HasGlobalAllocator(CrateNum),
528     [] ExternCrate(DefId),
529     [] LintLevels,
530     [] Specializes { impl1: DefId, impl2: DefId },
531     [] InScopeTraits(DefIndex),
532     [] ModuleExports(DefId),
533     [] IsSanitizerRuntime(CrateNum),
534     [] IsProfilerRuntime(CrateNum),
535     [] GetPanicStrategy(CrateNum),
536     [] IsNoBuiltins(CrateNum),
537     [] ImplDefaultness(DefId),
538     [] ExportedSymbols(CrateNum),
539     [] NativeLibraries(CrateNum),
540     [] PluginRegistrarFn(CrateNum),
541     [] DeriveRegistrarFn(CrateNum),
542     [] CrateDisambiguator(CrateNum),
543     [] CrateHash(CrateNum),
544     [] OriginalCrateName(CrateNum),
545
546     [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
547     [] AllTraitImplementations(CrateNum),
548
549     [] IsDllimportForeignItem(DefId),
550     [] IsStaticallyIncludedForeignItem(DefId),
551     [] NativeLibraryKind(DefId),
552     [] LinkArgs,
553
554     [] NamedRegion(DefIndex),
555     [] IsLateBound(DefIndex),
556     [] ObjectLifetimeDefaults(DefIndex),
557
558     [] Visibility(DefId),
559     [] DepKind(CrateNum),
560     [] CrateName(CrateNum),
561     [] ItemChildren(DefId),
562     [] ExternModStmtCnum(DefId),
563     [] GetLangItems,
564     [] DefinedLangItems(CrateNum),
565     [] MissingLangItems(CrateNum),
566     [] ExternConstBody(DefId),
567     [] VisibleParentMap,
568     [] IsDirectExternCrate(CrateNum),
569     [] MissingExternCrateItem(CrateNum),
570     [] UsedCrateSource(CrateNum),
571     [] PostorderCnums,
572
573     [] Freevars(DefId),
574     [] MaybeUnusedTraitImport(DefId),
575     [] MaybeUnusedExternCrates,
576     [] StabilityIndex,
577     [] AllCrateNums,
578 );
579
580 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
581     const CAN_RECONSTRUCT_QUERY_KEY: bool;
582
583     /// This method turns the parameters of a DepNodeConstructor into an opaque
584     /// Fingerprint to be used in DepNode.
585     /// Not all DepNodeParams support being turned into a Fingerprint (they
586     /// don't need to if the corresponding DepNode is anonymous).
587     fn to_fingerprint(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint {
588         panic!("Not implemented. Accidentally called on anonymous node?")
589     }
590
591     fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String {
592         format!("{:?}", self)
593     }
594 }
595
596 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
597     where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + fmt::Debug
598 {
599     default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
600
601     default fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint {
602         let mut hcx = StableHashingContext::new(tcx);
603         let mut hasher = StableHasher::new();
604
605         self.hash_stable(&mut hcx, &mut hasher);
606
607         hasher.finish()
608     }
609
610     default fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String {
611         format!("{:?}", *self)
612     }
613 }
614
615 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
616     const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
617
618     fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
619         tcx.def_path_hash(self.0).0
620     }
621
622     fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
623         tcx.item_path_str(self.0)
624     }
625 }
626
627 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) {
628     const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
629
630     // We actually would not need to specialize the implementation of this
631     // method but it's faster to combine the hashes than to instantiate a full
632     // hashing context and stable-hashing state.
633     fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
634         let (def_id_0, def_id_1) = *self;
635
636         let def_path_hash_0 = tcx.def_path_hash(def_id_0);
637         let def_path_hash_1 = tcx.def_path_hash(def_id_1);
638
639         def_path_hash_0.0.combine(def_path_hash_1.0)
640     }
641
642     fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
643         let (def_id_0, def_id_1) = *self;
644
645         format!("({}, {})",
646                 tcx.def_path(def_id_0).to_string(tcx),
647                 tcx.def_path(def_id_1).to_string(tcx))
648     }
649 }
650
651
652 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIdList,) {
653     const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
654
655     // We actually would not need to specialize the implementation of this
656     // method but it's faster to combine the hashes than to instantiate a full
657     // hashing context and stable-hashing state.
658     fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
659         let mut fingerprint = Fingerprint::zero();
660
661         for &def_id in self.0.iter() {
662             let def_path_hash = tcx.def_path_hash(def_id);
663             fingerprint = fingerprint.combine(def_path_hash.0);
664         }
665
666         fingerprint
667     }
668
669     fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
670         use std::fmt::Write;
671
672         let mut s = String::new();
673         write!(&mut s, "[").unwrap();
674
675         for &def_id in self.0.iter() {
676             write!(&mut s, "{}", tcx.def_path(def_id).to_string(tcx)).unwrap();
677         }
678
679         write!(&mut s, "]").unwrap();
680
681         s
682     }
683 }
684
685 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (HirId,) {
686     const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
687
688     // We actually would not need to specialize the implementation of this
689     // method but it's faster to combine the hashes than to instantiate a full
690     // hashing context and stable-hashing state.
691     fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
692         let (HirId {
693             owner,
694             local_id: ItemLocalId(local_id),
695         },) = *self;
696
697         let def_path_hash = tcx.def_path_hash(DefId::local(owner));
698         let local_id = Fingerprint::from_smaller_hash(local_id as u64);
699
700         def_path_hash.0.combine(local_id)
701     }
702 }
703
704 /// A "work product" corresponds to a `.o` (or other) file that we
705 /// save in between runs. These ids do not have a DefId but rather
706 /// some independent path or string that persists between runs without
707 /// the need to be mapped or unmapped. (This ensures we can serialize
708 /// them even in the absence of a tcx.)
709 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
710          RustcEncodable, RustcDecodable)]
711 pub struct WorkProductId {
712     hash: Fingerprint
713 }
714
715 impl WorkProductId {
716     pub fn from_cgu_name(cgu_name: &str) -> WorkProductId {
717         let mut hasher = StableHasher::new();
718         cgu_name.len().hash(&mut hasher);
719         cgu_name.hash(&mut hasher);
720         WorkProductId {
721             hash: hasher.finish()
722         }
723     }
724
725     pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId {
726         WorkProductId {
727             hash: fingerprint
728         }
729     }
730
731     pub fn to_dep_node(self) -> DepNode {
732         DepNode {
733             kind: DepKind::WorkProduct,
734             hash: self.hash,
735         }
736     }
737 }
738
739 impl_stable_hash_for!(struct ::dep_graph::WorkProductId {
740     hash
741 });
742
743 type DefIdList = Vec<DefId>;