Skip to content

Commit 4b471df

Browse files
committed
coverage: Disconnect span extraction from CoverageSpansGenerator
By performal initial span extraction in a separate free function, we can remove some accidental complexity from the main generator code.
1 parent 972ab88 commit 4b471df

File tree

2 files changed

+85
-87
lines changed

2 files changed

+85
-87
lines changed

compiler/rustc_mir_transform/src/coverage/spans.rs

+12-17
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,7 @@ impl CoverageSpan {
203203
/// * Merge spans that represent continuous (both in source code and control flow), non-branching
204204
/// execution
205205
/// * Carve out (leave uncovered) any span that will be counted by another MIR (notably, closures)
206-
struct CoverageSpansGenerator<'a, 'tcx> {
207-
/// The MIR, used to look up `BasicBlockData`.
208-
mir_body: &'a mir::Body<'tcx>,
209-
210-
/// A `Span` covering the signature of function for the MIR.
211-
fn_sig_span: Span,
212-
206+
struct CoverageSpansGenerator<'a> {
213207
/// A `Span` covering the function body of the MIR (typically from left curly brace to right
214208
/// curly brace).
215209
body_span: Span,
@@ -219,7 +213,7 @@ struct CoverageSpansGenerator<'a, 'tcx> {
219213

220214
/// The initial set of `CoverageSpan`s, sorted by `Span` (`lo` and `hi`) and by relative
221215
/// dominance between the `BasicCoverageBlock`s of equal `Span`s.
222-
sorted_spans_iter: Option<std::vec::IntoIter<CoverageSpan>>,
216+
sorted_spans_iter: std::vec::IntoIter<CoverageSpan>,
223217

224218
/// The current `CoverageSpan` to compare to its `prev`, to possibly merge, discard, force the
225219
/// discard of the `prev` (and or `pending_dups`), or keep both (with `prev` moved to
@@ -259,7 +253,7 @@ struct CoverageSpansGenerator<'a, 'tcx> {
259253
refined_spans: Vec<CoverageSpan>,
260254
}
261255

262-
impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
256+
impl<'a> CoverageSpansGenerator<'a> {
263257
/// Generate a minimal set of `CoverageSpan`s, each representing a contiguous code region to be
264258
/// counted.
265259
///
@@ -282,17 +276,22 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
282276
/// Note the resulting vector of `CoverageSpan`s may not be fully sorted (and does not need
283277
/// to be).
284278
pub(super) fn generate_coverage_spans(
285-
mir_body: &'a mir::Body<'tcx>,
279+
mir_body: &mir::Body<'_>,
286280
fn_sig_span: Span, // Ensured to be same SourceFile and SyntaxContext as `body_span`
287281
body_span: Span,
288282
basic_coverage_blocks: &'a CoverageGraph,
289283
) -> Vec<CoverageSpan> {
290-
let mut coverage_spans = Self {
284+
let sorted_spans = from_mir::mir_to_initial_sorted_coverage_spans(
291285
mir_body,
292286
fn_sig_span,
293287
body_span,
294288
basic_coverage_blocks,
295-
sorted_spans_iter: None,
289+
);
290+
291+
let coverage_spans = Self {
292+
body_span,
293+
basic_coverage_blocks,
294+
sorted_spans_iter: sorted_spans.into_iter(),
296295
refined_spans: Vec::with_capacity(basic_coverage_blocks.num_nodes() * 2),
297296
some_curr: None,
298297
curr_original_span: Span::with_root_ctxt(BytePos(0), BytePos(0)),
@@ -302,10 +301,6 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
302301
pending_dups: Vec::new(),
303302
};
304303

305-
let sorted_spans = coverage_spans.mir_to_initial_sorted_coverage_spans();
306-
307-
coverage_spans.sorted_spans_iter = Some(sorted_spans.into_iter());
308-
309304
coverage_spans.to_refined_spans()
310305
}
311306

@@ -510,7 +505,7 @@ impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
510505
self.some_prev = Some(curr);
511506
self.prev_original_span = self.curr_original_span;
512507
}
513-
while let Some(curr) = self.sorted_spans_iter.as_mut().unwrap().next() {
508+
while let Some(curr) = self.sorted_spans_iter.next() {
514509
debug!("FOR curr={:?}", curr);
515510
if self.some_prev.is_some() && self.prev_starts_after_next(&curr) {
516511
debug!(

compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs

+73-70
Original file line numberDiff line numberDiff line change
@@ -3,86 +3,89 @@ use rustc_middle::mir::{
33
};
44
use rustc_span::Span;
55

6-
use crate::coverage::graph::{BasicCoverageBlock, BasicCoverageBlockData};
7-
use crate::coverage::spans::{CoverageSpan, CoverageSpansGenerator};
6+
use crate::coverage::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
7+
use crate::coverage::spans::CoverageSpan;
88

9-
impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
10-
pub(super) fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> {
11-
let mut initial_spans =
12-
Vec::<CoverageSpan>::with_capacity(self.mir_body.basic_blocks.len() * 2);
13-
for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() {
14-
initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data));
15-
}
9+
pub(super) fn mir_to_initial_sorted_coverage_spans(
10+
mir_body: &mir::Body<'_>,
11+
fn_sig_span: Span,
12+
body_span: Span,
13+
basic_coverage_blocks: &CoverageGraph,
14+
) -> Vec<CoverageSpan> {
15+
let mut initial_spans = Vec::<CoverageSpan>::with_capacity(mir_body.basic_blocks.len() * 2);
16+
for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() {
17+
initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data));
18+
}
1619

17-
if initial_spans.is_empty() {
18-
// This can happen if, for example, the function is unreachable (contains only a
19-
// `BasicBlock`(s) with an `Unreachable` terminator).
20-
return initial_spans;
21-
}
20+
if initial_spans.is_empty() {
21+
// This can happen if, for example, the function is unreachable (contains only a
22+
// `BasicBlock`(s) with an `Unreachable` terminator).
23+
return initial_spans;
24+
}
2225

23-
initial_spans.push(CoverageSpan::for_fn_sig(self.fn_sig_span));
26+
initial_spans.push(CoverageSpan::for_fn_sig(fn_sig_span));
2427

25-
initial_spans.sort_by(|a, b| {
26-
// First sort by span start.
27-
Ord::cmp(&a.span.lo(), &b.span.lo())
28-
// If span starts are the same, sort by span end in reverse order.
29-
// This ensures that if spans A and B are adjacent in the list,
30-
// and they overlap but are not equal, then either:
31-
// - Span A extends further left, or
32-
// - Both have the same start and span A extends further right
33-
.then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse())
34-
// If both spans are equal, sort the BCBs in dominator order,
35-
// so that dominating BCBs come before other BCBs they dominate.
36-
.then_with(|| self.basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb))
37-
// If two spans are otherwise identical, put closure spans first,
38-
// as this seems to be what the refinement step expects.
39-
.then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse())
40-
});
28+
initial_spans.sort_by(|a, b| {
29+
// First sort by span start.
30+
Ord::cmp(&a.span.lo(), &b.span.lo())
31+
// If span starts are the same, sort by span end in reverse order.
32+
// This ensures that if spans A and B are adjacent in the list,
33+
// and they overlap but are not equal, then either:
34+
// - Span A extends further left, or
35+
// - Both have the same start and span A extends further right
36+
.then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse())
37+
// If both spans are equal, sort the BCBs in dominator order,
38+
// so that dominating BCBs come before other BCBs they dominate.
39+
.then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb))
40+
// If two spans are otherwise identical, put closure spans first,
41+
// as this seems to be what the refinement step expects.
42+
.then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse())
43+
});
4144

42-
initial_spans
43-
}
45+
initial_spans
46+
}
4447

45-
// Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of
46-
// the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One `CoverageSpan` is generated
47-
// for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will
48-
// merge some `CoverageSpan`s, at which point a `CoverageSpan` may represent multiple
49-
// `Statement`s and/or `Terminator`s.)
50-
fn bcb_to_initial_coverage_spans(
51-
&self,
52-
bcb: BasicCoverageBlock,
53-
bcb_data: &'a BasicCoverageBlockData,
54-
) -> Vec<CoverageSpan> {
55-
bcb_data
56-
.basic_blocks
57-
.iter()
58-
.flat_map(|&bb| {
59-
let data = &self.mir_body[bb];
60-
data.statements
61-
.iter()
62-
.enumerate()
63-
.filter_map(move |(index, statement)| {
64-
filtered_statement_span(statement).map(|span| {
65-
CoverageSpan::for_statement(
66-
statement,
67-
function_source_span(span, self.body_span),
68-
span,
69-
bcb,
70-
bb,
71-
index,
72-
)
73-
})
74-
})
75-
.chain(filtered_terminator_span(data.terminator()).map(|span| {
76-
CoverageSpan::for_terminator(
77-
function_source_span(span, self.body_span),
48+
// Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of
49+
// the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One `CoverageSpan` is generated
50+
// for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will
51+
// merge some `CoverageSpan`s, at which point a `CoverageSpan` may represent multiple
52+
// `Statement`s and/or `Terminator`s.)
53+
fn bcb_to_initial_coverage_spans(
54+
mir_body: &mir::Body<'_>,
55+
body_span: Span,
56+
bcb: BasicCoverageBlock,
57+
bcb_data: &BasicCoverageBlockData,
58+
) -> Vec<CoverageSpan> {
59+
bcb_data
60+
.basic_blocks
61+
.iter()
62+
.flat_map(|&bb| {
63+
let data = &mir_body[bb];
64+
data.statements
65+
.iter()
66+
.enumerate()
67+
.filter_map(move |(index, statement)| {
68+
filtered_statement_span(statement).map(|span| {
69+
CoverageSpan::for_statement(
70+
statement,
71+
function_source_span(span, body_span),
7872
span,
7973
bcb,
8074
bb,
75+
index,
8176
)
82-
}))
83-
})
84-
.collect()
85-
}
77+
})
78+
})
79+
.chain(filtered_terminator_span(data.terminator()).map(|span| {
80+
CoverageSpan::for_terminator(
81+
function_source_span(span, body_span),
82+
span,
83+
bcb,
84+
bb,
85+
)
86+
}))
87+
})
88+
.collect()
8689
}
8790

8891
/// If the MIR `Statement` has a span contributive to computing coverage spans,

0 commit comments

Comments
 (0)