Skip to main content

rustc_middle/dep_graph/
retained.rs

1use rustc_data_structures::fx::FxHashMap;
2use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, LinkedGraph, NodeIndex};
3
4use super::{DepNode, DepNodeIndex};
5
6/// An in-memory copy of the current session's query dependency graph, which
7/// is only enabled when `-Zquery-dep-graph` is set (for debugging/testing).
8///
9/// Normally, dependencies recorded during the current session are written to
10/// disk and then forgotten, to avoid wasting memory on information that is
11/// not needed when the compiler is working correctly.
12#[derive(#[automatically_derived]
impl ::core::clone::Clone for RetainedDepGraph {
    #[inline]
    fn clone(&self) -> RetainedDepGraph {
        RetainedDepGraph {
            inner: ::core::clone::Clone::clone(&self.inner),
            indices: ::core::clone::Clone::clone(&self.indices),
        }
    }
}Clone)]
13pub struct RetainedDepGraph {
14    pub inner: LinkedGraph<DepNode, ()>,
15    pub indices: FxHashMap<DepNode, NodeIndex>,
16}
17
18impl RetainedDepGraph {
19    pub fn new(prev_node_count: usize) -> Self {
20        let node_count = prev_node_count + prev_node_count / 4;
21        let edge_count = 6 * node_count;
22
23        let inner = LinkedGraph::with_capacity(node_count, edge_count);
24        let indices = FxHashMap::default();
25
26        Self { inner, indices }
27    }
28
29    /// Adds `node` at its dep-graph index. Indices are allocated to threads in batches, so the
30    /// index space is sparse and the slots skipped over hold no node.
31    pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) {
32        let source = NodeIndex(index.as_usize());
33        self.inner.add_node_with_idx(source, node);
34        self.indices.insert(node, source);
35
36        for &target in edges.iter() {
37            self.inner.add_edge(source, NodeIndex(target.as_usize()), ());
38        }
39    }
40
41    pub fn nodes(&self) -> Vec<&DepNode> {
42        self.inner.all_nodes().iter().filter_map(|n| n.data.as_ref()).collect()
43    }
44
45    pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> {
46        self.inner
47            .all_edges()
48            .iter()
49            .map(|edge| (edge.source(), edge.target()))
50            .map(|(s, t)| (self.inner.node_data(s), self.inner.node_data(t)))
51            .collect()
52    }
53
54    fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> {
55        if let Some(&index) = self.indices.get(node) {
56            self.inner.depth_traverse(index, direction).map(|s| self.inner.node_data(s)).collect()
57        } else {
58            ::alloc::vec::Vec::new()vec![]
59        }
60    }
61
62    /// All nodes that can reach `node`.
63    pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> {
64        self.reachable_nodes(node, INCOMING)
65    }
66}