Skip to content

Commit 76b769c

Browse files
authored
Rollup merge of #152621 - petrochenkov:graph2, r=Zalathar
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 RetainedDepGraph. This is continuation of #152590, that PR just fixes the ICE, this PR also preserves all the edges in debug dumps. This is also a minimized version of #151821 with a smaller amount of data structure hacks.
2 parents a0e206b + 96697d4 commit 76b769c

3 files changed

Lines changed: 43 additions & 27 deletions

File tree

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

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use std::fmt::Debug;
2424

2525
use rustc_index::bit_set::DenseBitSet;
26+
use rustc_index::{Idx, IndexSlice, IndexVec};
2627
use tracing::debug;
2728

2829
#[cfg(test)]
@@ -45,13 +46,13 @@ mod tests;
4546
/// and does not implement those traits, so it has its own implementations of a
4647
/// few basic graph algorithms.
4748
pub struct LinkedGraph<N, E> {
48-
nodes: Vec<Node<N>>,
49+
nodes: IndexVec<NodeIndex, Node<N>>,
4950
edges: Vec<Edge<E>>,
5051
}
5152

5253
pub struct Node<N> {
5354
first_edge: [EdgeIndex; 2], // see module comment
54-
pub data: N,
55+
pub data: Option<N>,
5556
}
5657

5758
#[derive(Debug)]
@@ -62,7 +63,7 @@ pub struct Edge<E> {
6263
pub data: E,
6364
}
6465

65-
#[derive(Copy, Clone, PartialEq, Debug)]
66+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
6667
pub struct NodeIndex(pub usize);
6768

6869
#[derive(Copy, Clone, PartialEq, Debug)]
@@ -87,19 +88,29 @@ impl NodeIndex {
8788
}
8889
}
8990

91+
impl Idx for NodeIndex {
92+
fn new(idx: usize) -> NodeIndex {
93+
NodeIndex(idx)
94+
}
95+
96+
fn index(self) -> usize {
97+
self.0
98+
}
99+
}
100+
90101
impl<N: Debug, E: Debug> LinkedGraph<N, E> {
91102
pub fn new() -> Self {
92-
Self { nodes: Vec::new(), edges: Vec::new() }
103+
Self { nodes: IndexVec::new(), edges: Vec::new() }
93104
}
94105

95106
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
96-
Self { nodes: Vec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
107+
Self { nodes: IndexVec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
97108
}
98109

99110
// # Simple accessors
100111

101112
#[inline]
102-
pub fn all_nodes(&self) -> &[Node<N>] {
113+
pub fn all_nodes(&self) -> &IndexSlice<NodeIndex, Node<N>> {
103114
&self.nodes
104115
}
105116

@@ -124,22 +135,34 @@ impl<N: Debug, E: Debug> LinkedGraph<N, E> {
124135
NodeIndex(self.nodes.len())
125136
}
126137

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+
127150
pub fn add_node(&mut self, data: N) -> NodeIndex {
128151
let idx = self.next_node_index();
129-
self.nodes.push(Node { first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX], data });
152+
self.add_node_with_idx(idx, data);
130153
idx
131154
}
132155

133156
pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
134-
&mut self.nodes[idx.0].data
157+
self.nodes[idx].data.as_mut().unwrap()
135158
}
136159

137160
pub fn node_data(&self, idx: NodeIndex) -> &N {
138-
&self.nodes[idx.0].data
161+
self.nodes[idx].data.as_ref().unwrap()
139162
}
140163

141164
pub fn node(&self, idx: NodeIndex) -> &Node<N> {
142-
&self.nodes[idx.0]
165+
&self.nodes[idx]
143166
}
144167

145168
// # Edge construction and queries
@@ -154,16 +177,16 @@ impl<N: Debug, E: Debug> LinkedGraph<N, E> {
154177
let idx = self.next_edge_index();
155178

156179
// read current first of the list of edges from each node
157-
let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
158-
let target_first = self.nodes[target.0].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];
159182

160183
// create the new edge, with the previous firsts from each node
161184
// as the next pointers
162185
self.edges.push(Edge { next_edge: [source_first, target_first], source, target, data });
163186

164187
// adjust the firsts for each node target be the next object.
165-
self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
166-
self.nodes[target.0].first_edge[INCOMING.repr] = idx;
188+
self.nodes[source].first_edge[OUTGOING.repr] = idx;
189+
self.nodes[target].first_edge[INCOMING.repr] = idx;
167190

168191
idx
169192
}

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)