@@ -145,18 +145,17 @@ impl CoverageGraph {
145
145
bcbs. push ( bcb_data) ;
146
146
} ;
147
147
148
- // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows
149
- // each block terminator's `successors()`. Coverage spans must map to actual source code,
150
- // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal
151
- // intentionally omits unwind paths.
152
- // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
153
- // `catch_unwind()` handlers.
148
+ // Traverse the MIR control-flow graph, accumulating chains of blocks
149
+ // that can be combined into a single node in the coverage graph.
150
+ // A depth-first search ensures that if two nodes can be chained
151
+ // together, they will be adjacent in the traversal order.
154
152
155
153
// Accumulates a chain of blocks that will be combined into one BCB.
156
154
let mut basic_blocks = Vec :: new ( ) ;
157
155
158
156
let filtered_successors = |bb| bcb_filtered_successors ( mir_body[ bb] . terminator ( ) ) ;
159
- for bb in short_circuit_preorder ( mir_body, filtered_successors)
157
+ let subgraph = CoverageRelevantSubgraph :: new ( & mir_body. basic_blocks ) ;
158
+ for bb in graph:: depth_first_search ( subgraph, mir:: START_BLOCK )
160
159
. filter ( |& bb| mir_body[ bb] . terminator ( ) . kind != TerminatorKind :: Unreachable )
161
160
{
162
161
// If the previous block can't be chained into `bb`, flush the accumulated
@@ -599,28 +598,31 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
599
598
}
600
599
}
601
600
602
- fn short_circuit_preorder < ' a , ' tcx , F , Iter > (
603
- body : & ' a mir:: Body < ' tcx > ,
604
- filtered_successors : F ,
605
- ) -> impl Iterator < Item = BasicBlock > + Captures < ' a > + Captures < ' tcx >
606
- where
607
- F : Fn ( BasicBlock ) -> Iter ,
608
- Iter : IntoIterator < Item = BasicBlock > ,
609
- {
610
- let mut visited = BitSet :: new_empty ( body. basic_blocks . len ( ) ) ;
611
- let mut worklist = vec ! [ mir:: START_BLOCK ] ;
612
-
613
- std:: iter:: from_fn ( move || {
614
- while let Some ( bb) = worklist. pop ( ) {
615
- if !visited. insert ( bb) {
616
- continue ;
617
- }
618
-
619
- worklist. extend ( filtered_successors ( bb) ) ;
601
+ /// Wrapper around a [`mir::BasicBlocks`] graph that restricts each node's
602
+ /// successors to only the ones considered "relevant" when building a coverage
603
+ /// graph.
604
+ #[ derive( Clone , Copy ) ]
605
+ struct CoverageRelevantSubgraph < ' a , ' tcx > {
606
+ basic_blocks : & ' a mir:: BasicBlocks < ' tcx > ,
607
+ }
608
+ impl < ' a , ' tcx > CoverageRelevantSubgraph < ' a , ' tcx > {
609
+ fn new ( basic_blocks : & ' a mir:: BasicBlocks < ' tcx > ) -> Self {
610
+ Self { basic_blocks }
611
+ }
620
612
621
- return Some ( bb) ;
622
- }
613
+ fn coverage_successors ( & self , bb : BasicBlock ) -> CoverageSuccessors < ' _ > {
614
+ bcb_filtered_successors ( self . basic_blocks [ bb] . terminator ( ) )
615
+ }
616
+ }
617
+ impl < ' a , ' tcx > graph:: DirectedGraph for CoverageRelevantSubgraph < ' a , ' tcx > {
618
+ type Node = BasicBlock ;
623
619
624
- None
625
- } )
620
+ fn num_nodes ( & self ) -> usize {
621
+ self . basic_blocks . num_nodes ( )
622
+ }
623
+ }
624
+ impl < ' a , ' tcx > graph:: Successors for CoverageRelevantSubgraph < ' a , ' tcx > {
625
+ fn successors ( & self , bb : Self :: Node ) -> impl Iterator < Item = Self :: Node > {
626
+ self . coverage_successors ( bb) . into_iter ( )
627
+ }
626
628
}
0 commit comments