Skip to content

Commit 858a53c

Browse files
committed
coverage: Remove hole-carving code from the main span refiner
Now that hole spans are handled by a separate earlier pass, this code never sees hole spans, and therefore doesn't need to deal with them.
1 parent c9ea5f1 commit 858a53c

File tree

1 file changed

+19
-80
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+19
-80
lines changed

compiler/rustc_mir_transform/src/coverage/spans.rs

+19-80
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ pub(super) fn extract_refined_covspans(
2424
from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks);
2525
for bucket in sorted_span_buckets {
2626
let refined_spans = SpansRefiner::refine_sorted_spans(bucket);
27-
code_mappings.extend(refined_spans.into_iter().map(|covspan| {
28-
let RefinedCovspan { span, bcb, is_hole: _ } = covspan;
27+
code_mappings.extend(refined_spans.into_iter().map(|RefinedCovspan { span, bcb }| {
2928
// Each span produced by the refiner represents an ordinary code region.
3029
mappings::CodeMapping { span, bcb }
3130
}));
@@ -36,24 +35,16 @@ pub(super) fn extract_refined_covspans(
3635
struct CurrCovspan {
3736
span: Span,
3837
bcb: BasicCoverageBlock,
39-
is_hole: bool,
4038
}
4139

4240
impl CurrCovspan {
43-
fn new(span: Span, bcb: BasicCoverageBlock, is_hole: bool) -> Self {
44-
Self { span, bcb, is_hole }
41+
fn new(span: Span, bcb: BasicCoverageBlock) -> Self {
42+
Self { span, bcb }
4543
}
4644

4745
fn into_prev(self) -> PrevCovspan {
48-
let Self { span, bcb, is_hole } = self;
49-
PrevCovspan { span, bcb, merged_spans: vec![span], is_hole }
50-
}
51-
52-
fn into_refined(self) -> RefinedCovspan {
53-
// This is only called in cases where `curr` is a hole span that has
54-
// been carved out of `prev`.
55-
debug_assert!(self.is_hole);
56-
self.into_prev().into_refined()
46+
let Self { span, bcb } = self;
47+
PrevCovspan { span, bcb, merged_spans: vec![span] }
5748
}
5849
}
5950

@@ -64,12 +55,11 @@ struct PrevCovspan {
6455
/// List of all the original spans from MIR that have been merged into this
6556
/// span. Mainly used to precisely skip over gaps when truncating a span.
6657
merged_spans: Vec<Span>,
67-
is_hole: bool,
6858
}
6959

7060
impl PrevCovspan {
7161
fn is_mergeable(&self, other: &CurrCovspan) -> bool {
72-
self.bcb == other.bcb && !self.is_hole && !other.is_hole
62+
self.bcb == other.bcb
7363
}
7464

7565
fn merge_from(&mut self, other: &CurrCovspan) {
@@ -87,27 +77,21 @@ impl PrevCovspan {
8777
if self.merged_spans.is_empty() { None } else { Some(self.into_refined()) }
8878
}
8979

90-
fn refined_copy(&self) -> RefinedCovspan {
91-
let &Self { span, bcb, merged_spans: _, is_hole } = self;
92-
RefinedCovspan { span, bcb, is_hole }
93-
}
94-
9580
fn into_refined(self) -> RefinedCovspan {
96-
// Even though we consume self, we can just reuse the copying impl.
97-
self.refined_copy()
81+
let Self { span, bcb, merged_spans: _ } = self;
82+
RefinedCovspan { span, bcb }
9883
}
9984
}
10085

10186
#[derive(Debug)]
10287
struct RefinedCovspan {
10388
span: Span,
10489
bcb: BasicCoverageBlock,
105-
is_hole: bool,
10690
}
10791

10892
impl RefinedCovspan {
10993
fn is_mergeable(&self, other: &Self) -> bool {
110-
self.bcb == other.bcb && !self.is_hole && !other.is_hole
94+
self.bcb == other.bcb
11195
}
11296

11397
fn merge_from(&mut self, other: &Self) {
@@ -122,8 +106,6 @@ impl RefinedCovspan {
122106
/// * Remove duplicate source code coverage regions
123107
/// * Merge spans that represent continuous (both in source code and control flow), non-branching
124108
/// execution
125-
/// * Carve out (leave uncovered) any "hole" spans that need to be left blank
126-
/// (e.g. closures that will be counted by their own MIR body)
127109
struct SpansRefiner {
128110
/// The initial set of coverage spans, sorted by `Span` (`lo` and `hi`) and by relative
129111
/// dominance between the `BasicCoverageBlock`s of equal `Span`s.
@@ -184,13 +166,6 @@ impl SpansRefiner {
184166
);
185167
let prev = self.take_prev().into_refined();
186168
self.refined_spans.push(prev);
187-
} else if prev.is_hole {
188-
// drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
189-
// next iter
190-
debug!(?prev, "prev (a hole) overlaps curr, so discarding curr");
191-
self.take_curr(); // Discards curr.
192-
} else if curr.is_hole {
193-
self.carve_out_span_for_hole();
194169
} else {
195170
self.cutoff_prev_at_overlapping_curr();
196171
}
@@ -214,9 +189,6 @@ impl SpansRefiner {
214189
}
215190
});
216191

217-
// Discard hole spans, since their purpose was to carve out chunks from
218-
// other spans, but we don't want the holes themselves in the final mappings.
219-
self.refined_spans.retain(|covspan| !covspan.is_hole);
220192
self.refined_spans
221193
}
222194

@@ -252,50 +224,17 @@ impl SpansRefiner {
252224
if let Some(curr) = self.some_curr.take() {
253225
self.some_prev = Some(curr.into_prev());
254226
}
255-
while let Some(curr) = self.sorted_spans_iter.next() {
256-
debug!("FOR curr={:?}", curr);
257-
if let Some(prev) = &self.some_prev
258-
&& prev.span.lo() > curr.span.lo()
259-
{
260-
// Skip curr because prev has already advanced beyond the end of curr.
261-
// This can only happen if a prior iteration updated `prev` to skip past
262-
// a region of code, such as skipping past a hole.
263-
debug!(?prev, "prev.span starts after curr.span, so curr will be dropped");
264-
} else {
265-
self.some_curr = Some(CurrCovspan::new(curr.span, curr.bcb, false));
266-
return true;
227+
if let Some(SpanFromMir { span, bcb, .. }) = self.sorted_spans_iter.next() {
228+
// This code only sees sorted spans after hole-carving, so there should
229+
// be no way for `curr` to start before `prev`.
230+
if let Some(prev) = &self.some_prev {
231+
debug_assert!(prev.span.lo() <= span.lo());
267232
}
268-
}
269-
false
270-
}
271-
272-
/// If `prev`s span extends left of the hole (`curr`), carve out the hole's span from
273-
/// `prev`'s span. Add the portion of the span to the left of the hole; and if the span
274-
/// extends to the right of the hole, update `prev` to that portion of the span.
275-
fn carve_out_span_for_hole(&mut self) {
276-
let prev = self.prev();
277-
let curr = self.curr();
278-
279-
let left_cutoff = curr.span.lo();
280-
let right_cutoff = curr.span.hi();
281-
let has_pre_hole_span = prev.span.lo() < right_cutoff;
282-
let has_post_hole_span = prev.span.hi() > right_cutoff;
283-
284-
if has_pre_hole_span {
285-
let mut pre_hole = prev.refined_copy();
286-
pre_hole.span = pre_hole.span.with_hi(left_cutoff);
287-
debug!(?pre_hole, "prev overlaps a hole; adding pre-hole span");
288-
self.refined_spans.push(pre_hole);
289-
}
290-
291-
if has_post_hole_span {
292-
// Mutate `prev.span` to start after the hole (and discard curr).
293-
self.prev_mut().span = self.prev().span.with_lo(right_cutoff);
294-
debug!(prev=?self.prev(), "mutated prev to start after the hole");
295-
296-
// Prevent this curr from becoming prev.
297-
let hole_covspan = self.take_curr().into_refined();
298-
self.refined_spans.push(hole_covspan); // since self.prev() was already updated
233+
self.some_curr = Some(CurrCovspan::new(span, bcb));
234+
debug!(?self.some_prev, ?self.some_curr, "next_coverage_span");
235+
true
236+
} else {
237+
false
299238
}
300239
}
301240

0 commit comments

Comments
 (0)