Skip to content

Commit 96697d4

Browse files
committed
LinkedGraph: support adding nodes and edges in arbitrary order
If an edge uses some not-yet-known node, we just leave the node's data empty, that data can be added later. Use this support to avoid skipping edges in DepGraphQuery
1 parent 71d656e commit 96697d4

File tree

3 files changed

+24
-19
lines changed

3 files changed

+24
-19
lines changed

compiler/rustc_data_structures/src/graph/linked_graph/mod.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub struct LinkedGraph<N, E> {
5252

5353
pub struct Node<N> {
5454
first_edge: [EdgeIndex; 2], // see module comment
55-
pub data: N,
55+
pub data: Option<N>,
5656
}
5757

5858
#[derive(Debug)]
@@ -135,18 +135,30 @@ impl<N: Debug, E: Debug> LinkedGraph<N, E> {
135135
NodeIndex(self.nodes.len())
136136
}
137137

138+
fn ensure_node(&mut self, idx: NodeIndex) -> &mut Node<N> {
139+
self.nodes.ensure_contains_elem(idx, || Node {
140+
first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
141+
data: None,
142+
})
143+
}
144+
145+
pub fn add_node_with_idx(&mut self, idx: NodeIndex, data: N) {
146+
let old_data = self.ensure_node(idx).data.replace(data);
147+
debug_assert!(old_data.is_none());
148+
}
149+
138150
pub fn add_node(&mut self, data: N) -> NodeIndex {
139151
let idx = self.next_node_index();
140-
self.nodes.push(Node { first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX], data });
152+
self.add_node_with_idx(idx, data);
141153
idx
142154
}
143155

144156
pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
145-
&mut self.nodes[idx].data
157+
self.nodes[idx].data.as_mut().unwrap()
146158
}
147159

148160
pub fn node_data(&self, idx: NodeIndex) -> &N {
149-
&self.nodes[idx].data
161+
self.nodes[idx].data.as_ref().unwrap()
150162
}
151163

152164
pub fn node(&self, idx: NodeIndex) -> &Node<N> {
@@ -165,8 +177,8 @@ impl<N: Debug, E: Debug> LinkedGraph<N, E> {
165177
let idx = self.next_edge_index();
166178

167179
// read current first of the list of edges from each node
168-
let source_first = self.nodes[source].first_edge[OUTGOING.repr];
169-
let target_first = self.nodes[target].first_edge[INCOMING.repr];
180+
let source_first = self.ensure_node(source).first_edge[OUTGOING.repr];
181+
let target_first = self.ensure_node(target).first_edge[INCOMING.repr];
170182

171183
// create the new edge, with the previous firsts from each node
172184
// as the next pointers

compiler/rustc_data_structures/src/graph/linked_graph/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fn each_node() {
4040
let expected = ["A", "B", "C", "D", "E", "F"];
4141
graph.each_node(|idx, node| {
4242
assert_eq!(&expected[idx.0], graph.node_data(idx));
43-
assert_eq!(expected[idx.0], node.data);
43+
assert_eq!(expected[idx.0], node.data.unwrap());
4444
true
4545
});
4646
}

compiler/rustc_middle/src/dep_graph/retained.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, LinkedGraph, NodeIndex};
3-
use rustc_index::IndexVec;
43

54
use super::{DepNode, DepNodeIndex};
65

@@ -13,7 +12,6 @@ use super::{DepNode, DepNodeIndex};
1312
pub struct RetainedDepGraph {
1413
pub inner: LinkedGraph<DepNode, ()>,
1514
pub indices: FxHashMap<DepNode, NodeIndex>,
16-
pub dep_index_to_index: IndexVec<DepNodeIndex, Option<NodeIndex>>,
1715
}
1816

1917
impl RetainedDepGraph {
@@ -23,27 +21,22 @@ impl RetainedDepGraph {
2321

2422
let inner = LinkedGraph::with_capacity(node_count, edge_count);
2523
let indices = FxHashMap::default();
26-
let dep_index_to_index = IndexVec::new();
2724

28-
Self { inner, indices, dep_index_to_index }
25+
Self { inner, indices }
2926
}
3027

3128
pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) {
32-
let source = self.inner.add_node(node);
33-
self.dep_index_to_index.insert(index, source);
29+
let source = NodeIndex(index.as_usize());
30+
self.inner.add_node_with_idx(source, node);
3431
self.indices.insert(node, source);
3532

3633
for &target in edges.iter() {
37-
// We may miss the edges that are pushed while the `DepGraphQuery` is being accessed.
38-
// Skip them to issues.
39-
if let Some(&Some(target)) = self.dep_index_to_index.get(target) {
40-
self.inner.add_edge(source, target, ());
41-
}
34+
self.inner.add_edge(source, NodeIndex(target.as_usize()), ());
4235
}
4336
}
4437

4538
pub fn nodes(&self) -> Vec<&DepNode> {
46-
self.inner.all_nodes().iter().map(|n| &n.data).collect()
39+
self.inner.all_nodes().iter().map(|n| n.data.as_ref().unwrap()).collect()
4740
}
4841

4942
pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> {

0 commit comments

Comments
 (0)