coverage: Extract a common iterator over a function's coverage statements

Both of the coverage queries can now use this one helper function to iterate
over all of the `mir::Coverage` payloads in the statements of a `mir::Body`.
This commit is contained in:
Zalathar 2023-08-30 23:29:37 +10:00
parent d5573d708d
commit 3f549466a8

View File

@ -1,5 +1,6 @@
use super::*; use super::*;
use rustc_data_structures::captures::Captures;
use rustc_middle::mir::coverage::*; use rustc_middle::mir::coverage::*;
use rustc_middle::mir::{self, Body, Coverage, CoverageInfo}; use rustc_middle::mir::{self, Body, Coverage, CoverageInfo};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
@ -66,17 +67,10 @@ impl CoverageVisitor {
} }
fn visit_body(&mut self, body: &Body<'_>) { fn visit_body(&mut self, body: &Body<'_>) {
for bb_data in body.basic_blocks.iter() { for coverage in all_coverage_in_mir_body(body) {
for statement in bb_data.statements.iter() {
if let StatementKind::Coverage(box ref coverage) = statement.kind {
if is_inlined(body, statement) {
continue;
}
self.visit_coverage(coverage); self.visit_coverage(coverage);
} }
} }
}
}
fn visit_coverage(&mut self, coverage: &Coverage) { fn visit_coverage(&mut self, coverage: &Coverage) {
if self.add_missing_operands { if self.add_missing_operands {
@ -115,21 +109,23 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> {
let body = mir_body(tcx, def_id); let body = mir_body(tcx, def_id);
body.basic_blocks all_coverage_in_mir_body(body)
.iter() // Not all coverage statements have an attached code region.
.flat_map(|data| { .filter_map(|coverage| coverage.code_region.as_ref())
data.statements.iter().filter_map(|statement| match statement.kind { .collect()
StatementKind::Coverage(box ref coverage) => { }
if is_inlined(body, statement) {
None fn all_coverage_in_mir_body<'a, 'tcx>(
} else { body: &'a Body<'tcx>,
coverage.code_region.as_ref() // may be None ) -> impl Iterator<Item = &'a Coverage> + Captures<'tcx> {
} body.basic_blocks.iter().flat_map(|bb_data| &bb_data.statements).filter_map(|statement| {
match statement.kind {
StatementKind::Coverage(box ref coverage) if !is_inlined(body, statement) => {
Some(coverage)
} }
_ => None, _ => None,
}
}) })
})
.collect()
} }
fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {