]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_query_system/src/dep_graph/prev.rs
9298b652da2d04c142105701271106c24a7ab93b
[rust.git] / compiler / rustc_query_system / src / dep_graph / prev.rs
1 use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
2 use super::{DepKind, DepNode};
3 use crate::dep_graph::DepContext;
4 use rustc_data_structures::fingerprint::Fingerprint;
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_span::def_id::DefPathHash;
7
8 #[derive(Debug, Encodable, Decodable)]
9 pub struct PreviousDepGraph<K: DepKind> {
10     data: SerializedDepGraph<K>,
11     index: FxHashMap<DepNode<K>, SerializedDepNodeIndex>,
12 }
13
14 impl<K: DepKind> Default for PreviousDepGraph<K> {
15     fn default() -> Self {
16         PreviousDepGraph { data: Default::default(), index: Default::default() }
17     }
18 }
19
20 impl<K: DepKind> PreviousDepGraph<K> {
21     pub fn new(data: SerializedDepGraph<K>) -> PreviousDepGraph<K> {
22         let index: FxHashMap<_, _> =
23             data.nodes.iter_enumerated().map(|(idx, &dep_node)| (dep_node, idx)).collect();
24         PreviousDepGraph { data, index }
25     }
26
27     #[inline]
28     pub fn edge_targets_from(
29         &self,
30         dep_node_index: SerializedDepNodeIndex,
31     ) -> &[SerializedDepNodeIndex] {
32         self.data.edge_targets_from(dep_node_index)
33     }
34
35     #[inline]
36     pub fn index_to_node<CTX: DepContext<DepKind = K>>(
37         &self,
38         dep_node_index: SerializedDepNodeIndex,
39         tcx: CTX,
40     ) -> DepNode<K> {
41         let dep_node = self.data.nodes[dep_node_index];
42         // We have just loaded a deserialized `DepNode` from the previous
43         // compilation session into the current one. If this was a foreign `DefId`,
44         // then we stored additional information in the incr comp cache when we
45         // initially created its fingerprint (see `DepNodeParams::to_fingerprint`)
46         // We won't be calling `to_fingerprint` again for this `DepNode` (we no longer
47         // have the original value), so we need to copy over this additional information
48         // from the old incremental cache into the new cache that we serialize
49         // and the end of this compilation session.
50         if dep_node.kind.can_reconstruct_query_key() {
51             tcx.register_reused_dep_path_hash(DefPathHash(dep_node.hash.into()));
52         }
53         dep_node
54     }
55
56     /// When debug assertions are enabled, asserts that the dep node at `dep_node_index` is equal to `dep_node`.
57     /// This method should be preferred over manually calling `index_to_node`.
58     /// Calls to `index_to_node` may affect global state, so gating a call
59     /// to `index_to_node` on debug assertions could cause behavior changes when debug assertions
60     /// are enabled.
61     #[inline]
62     pub fn debug_assert_eq(&self, dep_node_index: SerializedDepNodeIndex, dep_node: DepNode<K>) {
63         debug_assert_eq!(self.data.nodes[dep_node_index], dep_node);
64     }
65
66     /// Obtains a debug-printable version of the `DepNode`.
67     /// See `debug_assert_eq` for why this should be preferred over manually
68     /// calling `dep_node_index`
69     pub fn debug_dep_node(&self, dep_node_index: SerializedDepNodeIndex) -> impl std::fmt::Debug {
70         // We're returning the `DepNode` without calling `register_reused_dep_path_hash`,
71         // but `impl Debug` return type means that it can only be used for debug printing.
72         // So, there's no risk of calls trying to create new dep nodes that have this
73         // node as a dependency
74         self.data.nodes[dep_node_index]
75     }
76
77     #[inline]
78     pub fn node_to_index(&self, dep_node: &DepNode<K>) -> SerializedDepNodeIndex {
79         self.index[dep_node]
80     }
81
82     #[inline]
83     pub fn node_to_index_opt(&self, dep_node: &DepNode<K>) -> Option<SerializedDepNodeIndex> {
84         self.index.get(dep_node).cloned()
85     }
86
87     #[inline]
88     pub fn fingerprint_of(&self, dep_node: &DepNode<K>) -> Option<Fingerprint> {
89         self.index.get(dep_node).map(|&node_index| self.data.fingerprints[node_index])
90     }
91
92     #[inline]
93     pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fingerprint {
94         self.data.fingerprints[dep_node_index]
95     }
96
97     pub fn node_count(&self) -> usize {
98         self.index.len()
99     }
100 }