Skip to content

Commit f088d62

Browse files
committed
coverage: Use a standard depth-first search on a custom subgraph
1 parent 662a0fb commit f088d62

File tree

1 file changed

+28
-30
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+28
-30
lines changed

compiler/rustc_mir_transform/src/coverage/graph.rs

+28-30
Original file line numberDiff line numberDiff line change
@@ -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 current_chain = 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 let Some(&prev) = current_chain.last() {
@@ -596,28 +595,27 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
596595
}
597596
}
598597

599-
fn short_circuit_preorder<'a, 'tcx, F, Iter>(
600-
body: &'a mir::Body<'tcx>,
601-
filtered_successors: F,
602-
) -> impl Iterator<Item = BasicBlock> + Captures<'a> + Captures<'tcx>
603-
where
604-
F: Fn(BasicBlock) -> Iter,
605-
Iter: IntoIterator<Item = BasicBlock>,
606-
{
607-
let mut visited = BitSet::new_empty(body.basic_blocks.len());
608-
let mut worklist = vec![mir::START_BLOCK];
609-
610-
std::iter::from_fn(move || {
611-
while let Some(bb) = worklist.pop() {
612-
if !visited.insert(bb) {
613-
continue;
614-
}
615-
616-
worklist.extend(filtered_successors(bb));
617-
618-
return Some(bb);
619-
}
598+
/// Wrapper around a [`mir::BasicBlocks`] graph that restricts each node's
599+
/// successors to only the ones considered "relevant" when building a coverage
600+
/// graph.
601+
#[derive(Clone, Copy)]
602+
struct CoverageRelevantSubgraph<'a, 'tcx> {
603+
basic_blocks: &'a mir::BasicBlocks<'tcx>,
604+
}
605+
impl<'a, 'tcx> CoverageRelevantSubgraph<'a, 'tcx> {
606+
fn new(basic_blocks: &'a mir::BasicBlocks<'tcx>) -> Self {
607+
Self { basic_blocks }
608+
}
609+
}
610+
impl<'a, 'tcx> graph::DirectedGraph for CoverageRelevantSubgraph<'a, 'tcx> {
611+
type Node = BasicBlock;
620612

621-
None
622-
})
613+
fn num_nodes(&self) -> usize {
614+
self.basic_blocks.num_nodes()
615+
}
616+
}
617+
impl<'a, 'tcx> graph::Successors for CoverageRelevantSubgraph<'a, 'tcx> {
618+
fn successors(&self, node: Self::Node) -> impl Iterator<Item = Self::Node> {
619+
bcb_filtered_successors(self.basic_blocks[node].terminator()).into_iter()
620+
}
623621
}

0 commit comments

Comments
 (0)