mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 13:04:42 +00:00 
			
		
		
		
	 c9d46eb224
			
		
	
	
		c9d46eb224
		
	
	
	
	
		
			
			This expands the API to be more flexible, allowing for more visitation patterns on graphs. This will be useful to avoid extra datasets (and allocations) in cases where the expanded DFS API is sufficient. This also fixes a bug with the previous DFS constructor, which left the start node not marked as visited (even though it was immediately returned).
		
			
				
	
	
		
			82 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use rustc_index::vec::Idx;
 | |
| 
 | |
| pub mod dominators;
 | |
| pub mod implementation;
 | |
| pub mod iterate;
 | |
| mod reference;
 | |
| pub mod scc;
 | |
| pub mod vec_graph;
 | |
| 
 | |
| #[cfg(test)]
 | |
| mod tests;
 | |
| 
 | |
| pub trait DirectedGraph {
 | |
|     type Node: Idx;
 | |
| }
 | |
| 
 | |
| pub trait WithNumNodes: DirectedGraph {
 | |
|     fn num_nodes(&self) -> usize;
 | |
| }
 | |
| 
 | |
| pub trait WithNumEdges: DirectedGraph {
 | |
|     fn num_edges(&self) -> usize;
 | |
| }
 | |
| 
 | |
| pub trait WithSuccessors: DirectedGraph
 | |
| where
 | |
|     Self: for<'graph> GraphSuccessors<'graph, Item = <Self as DirectedGraph>::Node>,
 | |
| {
 | |
|     fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter;
 | |
| 
 | |
|     fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
 | |
|     where
 | |
|         Self: WithNumNodes,
 | |
|     {
 | |
|         iterate::DepthFirstSearch::new(self).with_start_node(from)
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[allow(unused_lifetimes)]
 | |
| pub trait GraphSuccessors<'graph> {
 | |
|     type Item;
 | |
|     type Iter: Iterator<Item = Self::Item>;
 | |
| }
 | |
| 
 | |
| pub trait WithPredecessors: DirectedGraph
 | |
| where
 | |
|     Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
 | |
| {
 | |
|     fn predecessors(&self, node: Self::Node) -> <Self as GraphPredecessors<'_>>::Iter;
 | |
| }
 | |
| 
 | |
| #[allow(unused_lifetimes)]
 | |
| pub trait GraphPredecessors<'graph> {
 | |
|     type Item;
 | |
|     type Iter: Iterator<Item = Self::Item>;
 | |
| }
 | |
| 
 | |
| pub trait WithStartNode: DirectedGraph {
 | |
|     fn start_node(&self) -> Self::Node;
 | |
| }
 | |
| 
 | |
| pub trait ControlFlowGraph:
 | |
|     DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes
 | |
| {
 | |
|     // convenient trait
 | |
| }
 | |
| 
 | |
| impl<T> ControlFlowGraph for T where
 | |
|     T: DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes
 | |
| {
 | |
| }
 | |
| 
 | |
| /// Returns `true` if the graph has a cycle that is reachable from the start node.
 | |
| pub fn is_cyclic<G>(graph: &G) -> bool
 | |
| where
 | |
|     G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
 | |
| {
 | |
|     iterate::TriColorDepthFirstSearch::new(graph)
 | |
|         .run_from_start(&mut iterate::CycleDetector)
 | |
|         .is_some()
 | |
| }
 |