Skip to main content

rustc_data_structures/graph/linked_graph/
mod.rs

1//! See [`LinkedGraph`].
2//!
3//! # Interface details
4//!
5//! You customize the graph by specifying a "node data" type `N` and an
6//! "edge data" type `E`. You can then later gain access (mutable or
7//! immutable) to these "user-data" bits. Currently, you can only add
8//! nodes or edges to the graph. You cannot remove or modify them once
9//! added. This could be changed if we have a need.
10//!
11//! # Implementation details
12//!
13//! The main tricky thing about this code is the way that edges are
14//! stored. The edges are stored in a central array, but they are also
15//! threaded onto two linked lists for each node, one for incoming edges
16//! and one for outgoing edges. Note that every edge is a member of some
17//! incoming list and some outgoing list. Basically you can load the
18//! first index of the linked list from the node data structures (the
19//! field `first_edge`) and then, for each edge, load the next index from
20//! the field `next_edge`). Each of those fields is an array that should
21//! be indexed by the direction (see the type `Direction`).
22
23use std::fmt::Debug;
24
25use rustc_index::bit_set::DenseBitSet;
26use rustc_index::{Idx, IndexSlice, IndexVec};
27use tracing::debug;
28
29#[cfg(test)]
30mod tests;
31
32/// A concrete graph implementation that supports:
33/// - Nodes and/or edges labelled with custom data types (`N` and `E` respectively).
34/// - Incremental addition of new nodes/edges (but not removal).
35/// - Flat storage of node/edge data in a pair of vectors.
36/// - Iteration over any node's out-edges or in-edges, via linked lists
37///   threaded through the node/edge data.
38///
39/// # Caution
40/// This is an older graph implementation that is still used by some pieces
41/// of diagnostic/debugging code. New code that needs a graph data structure
42/// should consider using `VecGraph` instead, or implementing its own
43/// special-purpose graph with the specific features needed.
44///
45/// This graph implementation predates the later [graph traits](crate::graph),
46/// and does not implement those traits, so it has its own implementations of a
47/// few basic graph algorithms.
48pub struct LinkedGraph<N, E> {
49    nodes: IndexVec<NodeIndex, Node<N>>,
50    edges: Vec<Edge<E>>,
51}
52
53pub struct Node<N> {
54    first_edge: [EdgeIndex; 2], // see module comment
55    pub data: Option<N>,
56}
57
58#[derive(#[automatically_derived]
impl<E: ::core::fmt::Debug> ::core::fmt::Debug for Edge<E> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "Edge",
            "next_edge", &self.next_edge, "source", &self.source, "target",
            &self.target, "data", &&self.data)
    }
}Debug)]
59pub struct Edge<E> {
60    next_edge: [EdgeIndex; 2], // see module comment
61    source: NodeIndex,
62    target: NodeIndex,
63    pub data: E,
64}
65
66#[derive(#[automatically_derived]
impl ::core::marker::Copy for NodeIndex { }Copy, #[automatically_derived]
impl ::core::clone::Clone for NodeIndex {
    #[inline]
    fn clone(&self) -> NodeIndex {
        let _: ::core::clone::AssertParamIsClone<usize>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for NodeIndex {
    #[inline]
    fn eq(&self, other: &NodeIndex) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for NodeIndex {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<usize>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for NodeIndex {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for NodeIndex {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "NodeIndex",
            &&self.0)
    }
}Debug)]
67pub struct NodeIndex(pub usize);
68
69#[derive(#[automatically_derived]
impl ::core::marker::Copy for EdgeIndex { }Copy, #[automatically_derived]
impl ::core::clone::Clone for EdgeIndex {
    #[inline]
    fn clone(&self) -> EdgeIndex {
        let _: ::core::clone::AssertParamIsClone<usize>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for EdgeIndex {
    #[inline]
    fn eq(&self, other: &EdgeIndex) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for EdgeIndex {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "EdgeIndex",
            &&self.0)
    }
}Debug)]
70pub struct EdgeIndex(pub usize);
71
72pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);
73
74// Use a private field here to guarantee no more instances are created:
75#[derive(#[automatically_derived]
impl ::core::marker::Copy for Direction { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Direction {
    #[inline]
    fn clone(&self) -> Direction {
        let _: ::core::clone::AssertParamIsClone<usize>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Direction {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "Direction",
            "repr", &&self.repr)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Direction {
    #[inline]
    fn eq(&self, other: &Direction) -> bool { self.repr == other.repr }
}PartialEq)]
76pub struct Direction {
77    repr: usize,
78}
79
80pub const OUTGOING: Direction = Direction { repr: 0 };
81
82pub const INCOMING: Direction = Direction { repr: 1 };
83
84impl NodeIndex {
85    /// Returns unique ID (unique with respect to the graph holding associated node).
86    pub fn node_id(self) -> usize {
87        self.0
88    }
89}
90
91impl 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
101impl<N: Debug, E: Debug> LinkedGraph<N, E> {
102    pub fn new() -> Self {
103        Self { nodes: IndexVec::new(), edges: Vec::new() }
104    }
105
106    pub fn with_capacity(nodes: usize, edges: usize) -> Self {
107        Self { nodes: IndexVec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
108    }
109
110    // # Simple accessors
111
112    #[inline]
113    pub fn all_nodes(&self) -> &IndexSlice<NodeIndex, Node<N>> {
114        &self.nodes
115    }
116
117    #[inline]
118    pub fn len_nodes(&self) -> usize {
119        self.nodes.len()
120    }
121
122    #[inline]
123    pub fn all_edges(&self) -> &[Edge<E>] {
124        &self.edges
125    }
126
127    #[inline]
128    pub fn len_edges(&self) -> usize {
129        self.edges.len()
130    }
131
132    // # Node construction
133
134    pub fn next_node_index(&self) -> NodeIndex {
135        NodeIndex(self.nodes.len())
136    }
137
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        if true {
    if !old_data.is_none() {
        ::core::panicking::panic("assertion failed: old_data.is_none()")
    };
};debug_assert!(old_data.is_none());
148    }
149
150    pub fn add_node(&mut self, data: N) -> NodeIndex {
151        let idx = self.next_node_index();
152        self.add_node_with_idx(idx, data);
153        idx
154    }
155
156    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
157        self.nodes[idx].data.as_mut().unwrap()
158    }
159
160    pub fn node_data(&self, idx: NodeIndex) -> &N {
161        self.nodes[idx].data.as_ref().unwrap()
162    }
163
164    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
165        &self.nodes[idx]
166    }
167
168    // # Edge construction and queries
169
170    pub fn next_edge_index(&self) -> EdgeIndex {
171        EdgeIndex(self.edges.len())
172    }
173
174    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
175        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_data_structures/src/graph/linked_graph/mod.rs:175",
                        "rustc_data_structures::graph::linked_graph",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_data_structures/src/graph/linked_graph/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(175u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_data_structures::graph::linked_graph"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("graph: add_edge({0:?}, {1:?}, {2:?})",
                                                    source, target, data) as &dyn Value))])
            });
    } else { ; }
};debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);
176
177        let idx = self.next_edge_index();
178
179        // read current first of the list of edges from each node
180        let source_first = self.ensure_node(source).first_edge[OUTGOING.repr];
181        let target_first = self.ensure_node(target).first_edge[INCOMING.repr];
182
183        // create the new edge, with the previous firsts from each node
184        // as the next pointers
185        self.edges.push(Edge { next_edge: [source_first, target_first], source, target, data });
186
187        // adjust the firsts for each node target be the next object.
188        self.nodes[source].first_edge[OUTGOING.repr] = idx;
189        self.nodes[target].first_edge[INCOMING.repr] = idx;
190
191        idx
192    }
193
194    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
195        &self.edges[idx.0]
196    }
197
198    // # Iterating over nodes, edges
199
200    pub fn enumerated_nodes(&self) -> impl Iterator<Item = (NodeIndex, &Node<N>)> {
201        self.nodes.iter().enumerate().map(|(idx, n)| (NodeIndex(idx), n))
202    }
203
204    pub fn enumerated_edges(&self) -> impl Iterator<Item = (EdgeIndex, &Edge<E>)> {
205        self.edges.iter().enumerate().map(|(idx, e)| (EdgeIndex(idx), e))
206    }
207
208    pub fn each_node<'a>(&'a self, mut f: impl FnMut(NodeIndex, &'a Node<N>) -> bool) -> bool {
209        //! Iterates over all edges defined in the graph.
210        self.enumerated_nodes().all(|(node_idx, node)| f(node_idx, node))
211    }
212
213    pub fn each_edge<'a>(&'a self, mut f: impl FnMut(EdgeIndex, &'a Edge<E>) -> bool) -> bool {
214        //! Iterates over all edges defined in the graph
215        self.enumerated_edges().all(|(edge_idx, edge)| f(edge_idx, edge))
216    }
217
218    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<'_, N, E> {
219        self.adjacent_edges(source, OUTGOING)
220    }
221
222    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<'_, N, E> {
223        self.adjacent_edges(source, INCOMING)
224    }
225
226    pub fn adjacent_edges(
227        &self,
228        source: NodeIndex,
229        direction: Direction,
230    ) -> AdjacentEdges<'_, N, E> {
231        let first_edge = self.node(source).first_edge[direction.repr];
232        AdjacentEdges { graph: self, direction, next: first_edge }
233    }
234
235    pub fn successor_nodes(&self, source: NodeIndex) -> impl Iterator<Item = NodeIndex> {
236        self.outgoing_edges(source).targets()
237    }
238
239    pub fn predecessor_nodes(&self, target: NodeIndex) -> impl Iterator<Item = NodeIndex> {
240        self.incoming_edges(target).sources()
241    }
242
243    pub fn depth_traverse(
244        &self,
245        start: NodeIndex,
246        direction: Direction,
247    ) -> DepthFirstTraversal<'_, N, E> {
248        DepthFirstTraversal::with_start_node(self, start, direction)
249    }
250
251    pub fn nodes_in_postorder(
252        &self,
253        direction: Direction,
254        entry_node: NodeIndex,
255    ) -> Vec<NodeIndex> {
256        let mut visited = DenseBitSet::new_empty(self.len_nodes());
257        let mut stack = ::alloc::vec::Vec::new()vec![];
258        let mut result = Vec::with_capacity(self.len_nodes());
259        let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
260            if visited.insert(node.0) {
261                stack.push((node, self.adjacent_edges(node, direction)));
262            }
263        };
264
265        for node in
266            Some(entry_node).into_iter().chain(self.enumerated_nodes().map(|(node, _)| node))
267        {
268            push_node(&mut stack, node);
269            while let Some((node, mut iter)) = stack.pop() {
270                if let Some((_, child)) = iter.next() {
271                    let target = child.source_or_target(direction);
272                    // the current node needs more processing, so
273                    // add it back to the stack
274                    stack.push((node, iter));
275                    // and then push the new node
276                    push_node(&mut stack, target);
277                } else {
278                    result.push(node);
279                }
280            }
281        }
282
283        match (&result.len(), &self.len_nodes()) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(result.len(), self.len_nodes());
284        result
285    }
286}
287
288// # Iterators
289
290pub struct AdjacentEdges<'g, N, E> {
291    graph: &'g LinkedGraph<N, E>,
292    direction: Direction,
293    next: EdgeIndex,
294}
295
296impl<'g, N: Debug, E: Debug> AdjacentEdges<'g, N, E> {
297    fn targets(self) -> impl Iterator<Item = NodeIndex> {
298        self.map(|(_, edge)| edge.target)
299    }
300
301    fn sources(self) -> impl Iterator<Item = NodeIndex> {
302        self.map(|(_, edge)| edge.source)
303    }
304}
305
306impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
307    type Item = (EdgeIndex, &'g Edge<E>);
308
309    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
310        let edge_index = self.next;
311        if edge_index == INVALID_EDGE_INDEX {
312            return None;
313        }
314
315        let edge = self.graph.edge(edge_index);
316        self.next = edge.next_edge[self.direction.repr];
317        Some((edge_index, edge))
318    }
319
320    fn size_hint(&self) -> (usize, Option<usize>) {
321        // At most, all the edges in the graph.
322        (0, Some(self.graph.len_edges()))
323    }
324}
325
326pub struct DepthFirstTraversal<'g, N, E> {
327    graph: &'g LinkedGraph<N, E>,
328    stack: Vec<NodeIndex>,
329    visited: DenseBitSet<usize>,
330    direction: Direction,
331}
332
333impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
334    pub fn with_start_node(
335        graph: &'g LinkedGraph<N, E>,
336        start_node: NodeIndex,
337        direction: Direction,
338    ) -> Self {
339        let mut visited = DenseBitSet::new_empty(graph.len_nodes());
340        visited.insert(start_node.node_id());
341        DepthFirstTraversal { graph, stack: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [start_node]))vec![start_node], visited, direction }
342    }
343
344    fn visit(&mut self, node: NodeIndex) {
345        if self.visited.insert(node.node_id()) {
346            self.stack.push(node);
347        }
348    }
349}
350
351impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
352    type Item = NodeIndex;
353
354    fn next(&mut self) -> Option<NodeIndex> {
355        let next = self.stack.pop();
356        if let Some(idx) = next {
357            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
358                let target = edge.source_or_target(self.direction);
359                self.visit(target);
360            }
361        }
362        next
363    }
364
365    fn size_hint(&self) -> (usize, Option<usize>) {
366        // We will visit every node in the graph exactly once.
367        let remaining = self.graph.len_nodes() - self.visited.count();
368        (remaining, Some(remaining))
369    }
370}
371
372impl<'g, N: Debug, E: Debug> ExactSizeIterator for DepthFirstTraversal<'g, N, E> {}
373
374impl<E> Edge<E> {
375    pub fn source(&self) -> NodeIndex {
376        self.source
377    }
378
379    pub fn target(&self) -> NodeIndex {
380        self.target
381    }
382
383    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
384        if direction == OUTGOING { self.target } else { self.source }
385    }
386}