@@ -145,18 +145,17 @@ impl CoverageGraph {
145145 bcbs. push ( bcb_data) ;
146146 } ;
147147
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.
154152
155153 // Accumulates a chain of blocks that will be combined into one BCB.
156154 let mut basic_blocks = Vec :: new ( ) ;
157155
158156 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 )
160159 . filter ( |& bb| mir_body[ bb] . terminator ( ) . kind != TerminatorKind :: Unreachable )
161160 {
162161 // If the previous block can't be chained into `bb`, flush the accumulated
@@ -599,28 +598,31 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
599598 }
600599}
601600
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+ }
620612
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 ;
623619
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+ }
626628}
0 commit comments