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.
48#[derive(#[automatically_derived]
impl<N: ::core::clone::Clone, E: ::core::clone::Clone> ::core::clone::Clone
    for LinkedGraph<N, E> {
    #[inline]
    fn clone(&self) -> LinkedGraph<N, E> {
        LinkedGraph {
            nodes: ::core::clone::Clone::clone(&self.nodes),
            edges: ::core::clone::Clone::clone(&self.edges),
        }
    }
}Clone)]
49pub struct LinkedGraph<N, E> {
50    nodes: IndexVec<NodeIndex, Node<N>>,
51    edges: Vec<Edge<E>>,
52}
53
54#[derive(#[automatically_derived]
impl<N: ::core::clone::Clone> ::core::clone::Clone for Node<N> {
    #[inline]
    fn clone(&self) -> Node<N> {
        Node {
            first_edge: ::core::clone::Clone::clone(&self.first_edge),
            data: ::core::clone::Clone::clone(&self.data),
        }
    }
}Clone)]
55pub struct Node<N> {
56    first_edge: [EdgeIndex; 2], // see module comment
57    pub data: Option<N>,
58}
59
60#[derive(#[automatically_derived]
impl<E: ::core::clone::Clone> ::core::clone::Clone for Edge<E> {
    #[inline]
    fn clone(&self) -> Edge<E> {
        Edge {
            next_edge: ::core::clone::Clone::clone(&self.next_edge),
            source: ::core::clone::Clone::clone(&self.source),
            target: ::core::clone::Clone::clone(&self.target),
            data: ::core::clone::Clone::clone(&self.data),
        }
    }
}Clone, #[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)]
61pub struct Edge<E> {
62    next_edge: [EdgeIndex; 2], // see module comment
63    source: NodeIndex,
64    target: NodeIndex,
65    pub data: E,
66}
67
68#[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)]
69pub struct NodeIndex(pub usize);
70
71#[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)]
72pub struct EdgeIndex(pub usize);
73
74pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);
75
76// Use a private field here to guarantee no more instances are created:
77#[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)]
78pub struct Direction {
79    repr: usize,
80}
81
82pub const OUTGOING: Direction = Direction { repr: 0 };
83
84pub const INCOMING: Direction = Direction { repr: 1 };
85
86impl NodeIndex {
87    /// Returns unique ID (unique with respect to the graph holding associated node).
88    pub fn node_id(self) -> usize {
89        self.0
90    }
91}
92
93impl Idx for NodeIndex {
94    fn new(idx: usize) -> NodeIndex {
95        NodeIndex(idx)
96    }
97
98    fn index(self) -> usize {
99        self.0
100    }
101}
102
103impl<N: Debug, E: Debug> LinkedGraph<N, E> {
104    pub fn new() -> Self {
105        Self { nodes: IndexVec::new(), edges: Vec::new() }
106    }
107
108    pub fn with_capacity(nodes: usize, edges: usize) -> Self {
109        Self { nodes: IndexVec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
110    }
111
112    // # Simple accessors
113
114    #[inline]
115    pub fn all_nodes(&self) -> &IndexSlice<NodeIndex, Node<N>> {
116        &self.nodes
117    }
118
119    #[inline]
120    pub fn len_nodes(&self) -> usize {
121        self.nodes.len()
122    }
123
124    #[inline]
125    pub fn all_edges(&self) -> &[Edge<E>] {
126        &self.edges
127    }
128
129    #[inline]
130    pub fn len_edges(&self) -> usize {
131        self.edges.len()
132    }
133
134    // # Node construction
135
136    pub fn next_node_index(&self) -> NodeIndex {
137        NodeIndex(self.nodes.len())
138    }
139
140    fn ensure_node(&mut self, idx: NodeIndex) -> &mut Node<N> {
141        self.nodes.ensure_contains_elem(idx, || Node {
142            first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
143            data: None,
144        })
145    }
146
147    pub fn add_node_with_idx(&mut self, idx: NodeIndex, data: N) {
148        let old_data = self.ensure_node(idx).data.replace(data);
149        if true {
    if !old_data.is_none() {
        ::core::panicking::panic("assertion failed: old_data.is_none()")
    };
};debug_assert!(old_data.is_none());
150    }
151
152    pub fn add_node(&mut self, data: N) -> NodeIndex {
153        let idx = self.next_node_index();
154        self.add_node_with_idx(idx, data);
155        idx
156    }
157
158    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
159        self.nodes[idx].data.as_mut().unwrap()
160    }
161
162    pub fn node_data(&self, idx: NodeIndex) -> &N {
163        self.nodes[idx].data.as_ref().unwrap()
164    }
165
166    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
167        &self.nodes[idx]
168    }
169
170    // # Edge construction and queries
171
172    pub fn next_edge_index(&self) -> EdgeIndex {
173        EdgeIndex(self.edges.len())
174    }
175
176    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
177        {
    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:177",
                        "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(177u32),
                        ::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);
178
179        let idx = self.next_edge_index();
180
181        // read current first of the list of edges from each node
182        let source_first = self.ensure_node(source).first_edge[OUTGOING.repr];
183        let target_first = self.ensure_node(target).first_edge[INCOMING.repr];
184
185        // create the new edge, with the previous firsts from each node
186        // as the next pointers
187        self.edges.push(Edge { next_edge: [source_first, target_first], source, target, data });
188
189        // adjust the firsts for each node target be the next object.
190        self.nodes[source].first_edge[OUTGOING.repr] = idx;
191        self.nodes[target].first_edge[INCOMING.repr] = idx;
192
193        idx
194    }
195
196    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
197        &self.edges[idx.0]
198    }
199
200    // # Iterating over nodes, edges
201
202    pub fn enumerated_nodes(&self) -> impl Iterator<Item = (NodeIndex, &Node<N>)> {
203        self.nodes.iter().enumerate().map(|(idx, n)| (NodeIndex(idx), n))
204    }
205
206    pub fn enumerated_edges(&self) -> impl Iterator<Item = (EdgeIndex, &Edge<E>)> {
207        self.edges.iter().enumerate().map(|(idx, e)| (EdgeIndex(idx), e))
208    }
209
210    pub fn each_node<'a>(&'a self, mut f: impl FnMut(NodeIndex, &'a Node<N>) -> bool) -> bool {
211        //! Iterates over all edges defined in the graph.
212        self.enumerated_nodes().all(|(node_idx, node)| f(node_idx, node))
213    }
214
215    pub fn each_edge<'a>(&'a self, mut f: impl FnMut(EdgeIndex, &'a Edge<E>) -> bool) -> bool {
216        //! Iterates over all edges defined in the graph
217        self.enumerated_edges().all(|(edge_idx, edge)| f(edge_idx, edge))
218    }
219
220    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<'_, N, E> {
221        self.adjacent_edges(source, OUTGOING)
222    }
223
224    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<'_, N, E> {
225        self.adjacent_edges(source, INCOMING)
226    }
227
228    pub fn adjacent_edges(
229        &self,
230        source: NodeIndex,
231        direction: Direction,
232    ) -> AdjacentEdges<'_, N, E> {
233        let first_edge = self.node(source).first_edge[direction.repr];
234        AdjacentEdges { graph: self, direction, next: first_edge }
235    }
236
237    pub fn successor_nodes(&self, source: NodeIndex) -> impl Iterator<Item = NodeIndex> {
238        self.outgoing_edges(source).targets()
239    }
240
241    pub fn predecessor_nodes(&self, target: NodeIndex) -> impl Iterator<Item = NodeIndex> {
242        self.incoming_edges(target).sources()
243    }
244
245    pub fn depth_traverse(
246        &self,
247        start: NodeIndex,
248        direction: Direction,
249    ) -> DepthFirstTraversal<'_, N, E> {
250        DepthFirstTraversal::with_start_node(self, start, direction)
251    }
252
253    pub fn nodes_in_postorder(
254        &self,
255        direction: Direction,
256        entry_node: NodeIndex,
257    ) -> Vec<NodeIndex> {
258        let mut visited = DenseBitSet::new_empty(self.len_nodes());
259        let mut stack = ::alloc::vec::Vec::new()vec![];
260        let mut result = Vec::with_capacity(self.len_nodes());
261        let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
262            if visited.insert(node.0) {
263                stack.push((node, self.adjacent_edges(node, direction)));
264            }
265        };
266
267        for node in
268            Some(entry_node).into_iter().chain(self.enumerated_nodes().map(|(node, _)| node))
269        {
270            push_node(&mut stack, node);
271            while let Some((node, mut iter)) = stack.pop() {
272                if let Some((_, child)) = iter.next() {
273                    let target = child.source_or_target(direction);
274                    // the current node needs more processing, so
275                    // add it back to the stack
276                    stack.push((node, iter));
277                    // and then push the new node
278                    push_node(&mut stack, target);
279                } else {
280                    result.push(node);
281                }
282            }
283        }
284
285        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());
286        result
287    }
288}
289
290// # Iterators
291
292pub struct AdjacentEdges<'g, N, E> {
293    graph: &'g LinkedGraph<N, E>,
294    direction: Direction,
295    next: EdgeIndex,
296}
297
298impl<'g, N: Debug, E: Debug> AdjacentEdges<'g, N, E> {
299    fn targets(self) -> impl Iterator<Item = NodeIndex> {
300        self.map(|(_, edge)| edge.target)
301    }
302
303    fn sources(self) -> impl Iterator<Item = NodeIndex> {
304        self.map(|(_, edge)| edge.source)
305    }
306}
307
308impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
309    type Item = (EdgeIndex, &'g Edge<E>);
310
311    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
312        let edge_index = self.next;
313        if edge_index == INVALID_EDGE_INDEX {
314            return None;
315        }
316
317        let edge = self.graph.edge(edge_index);
318        self.next = edge.next_edge[self.direction.repr];
319        Some((edge_index, edge))
320    }
321
322    fn size_hint(&self) -> (usize, Option<usize>) {
323        // At most, all the edges in the graph.
324        (0, Some(self.graph.len_edges()))
325    }
326}
327
328pub struct DepthFirstTraversal<'g, N, E> {
329    graph: &'g LinkedGraph<N, E>,
330    stack: Vec<NodeIndex>,
331    visited: DenseBitSet<usize>,
332    direction: Direction,
333}
334
335impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
336    pub fn with_start_node(
337        graph: &'g LinkedGraph<N, E>,
338        start_node: NodeIndex,
339        direction: Direction,
340    ) -> Self {
341        let mut visited = DenseBitSet::new_empty(graph.len_nodes());
342        visited.insert(start_node.node_id());
343        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 }
344    }
345
346    fn visit(&mut self, node: NodeIndex) {
347        if self.visited.insert(node.node_id()) {
348            self.stack.push(node);
349        }
350    }
351}
352
353impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
354    type Item = NodeIndex;
355
356    fn next(&mut self) -> Option<NodeIndex> {
357        let next = self.stack.pop();
358        if let Some(idx) = next {
359            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
360                let target = edge.source_or_target(self.direction);
361                self.visit(target);
362            }
363        }
364        next
365    }
366
367    fn size_hint(&self) -> (usize, Option<usize>) {
368        // We will visit every node in the graph exactly once.
369        let remaining = self.graph.len_nodes() - self.visited.count();
370        (remaining, Some(remaining))
371    }
372}
373
374impl<'g, N: Debug, E: Debug> ExactSizeIterator for DepthFirstTraversal<'g, N, E> {}
375
376impl<E> Edge<E> {
377    pub fn source(&self) -> NodeIndex {
378        self.source
379    }
380
381    pub fn target(&self) -> NodeIndex {
382        self.target
383    }
384
385    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
386        if direction == OUTGOING { self.target } else { self.source }
387    }
388}