Skip to content

Commit 3258a74

Browse files
committed
coverage: Instead of splitting, just discard any span that overlaps a hole
1 parent f8d98dc commit 3258a74

File tree

10 files changed

+63
-88
lines changed

10 files changed

+63
-88
lines changed

Diff for: compiler/rustc_mir_transform/src/coverage/spans.rs

+16-46
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::VecDeque;
2+
use std::iter;
23

34
use rustc_data_structures::fx::FxHashSet;
45
use rustc_middle::mir;
@@ -83,9 +84,7 @@ pub(super) fn extract_refined_covspans(
8384
// Split the covspans into separate buckets that don't overlap any holes.
8485
let buckets = divide_spans_into_buckets(covspans, &holes);
8586

86-
for mut covspans in buckets {
87-
// Make sure each individual bucket is internally sorted.
88-
covspans.sort_by(compare_covspans);
87+
for covspans in buckets {
8988
let _span = debug_span!("processing bucket", ?covspans).entered();
9089

9190
let mut covspans = remove_unwanted_overlapping_spans(covspans);
@@ -161,50 +160,37 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
161160
}
162161

163162
/// Uses the holes to divide the given covspans into buckets, such that:
164-
/// - No span in any hole overlaps a bucket (truncating the spans if necessary).
163+
/// - No span in any hole overlaps a bucket (discarding spans if necessary).
165164
/// - The spans in each bucket are strictly after all spans in previous buckets,
166165
/// and strictly before all spans in subsequent buckets.
167166
///
168-
/// The resulting buckets are sorted relative to each other, but might not be
169-
/// internally sorted.
167+
/// The lists of covspans and holes must be sorted.
168+
/// The resulting buckets are sorted relative to each other, and each bucket's
169+
/// contents are sorted.
170170
#[instrument(level = "debug")]
171171
fn divide_spans_into_buckets(input_covspans: Vec<Covspan>, holes: &[Hole]) -> Vec<Vec<Covspan>> {
172172
debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
173173
debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
174174

175-
// Now we're ready to start carving holes out of the initial coverage spans,
176-
// and grouping them in buckets separated by the holes.
175+
// Now we're ready to start grouping spans into buckets separated by holes.
177176

178177
let mut input_covspans = VecDeque::from(input_covspans);
179-
let mut fragments = vec![];
180178

181179
// For each hole:
182180
// - Identify the spans that are entirely or partly before the hole.
183-
// - Put those spans in a corresponding bucket, truncated to the start of the hole.
184-
// - If one of those spans also extends after the hole, put the rest of it
185-
// in a "fragments" vector that is processed by the next hole.
181+
// - Discard any that overlap with the hole.
182+
// - Add the remaining identified spans to the corresponding bucket.
186183
let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
187184
for (hole, bucket) in holes.iter().zip(&mut buckets) {
188-
let fragments_from_prev = std::mem::take(&mut fragments);
189-
190-
// Only inspect spans that precede or overlap this hole,
191-
// leaving the rest to be inspected by later holes.
192-
// (This relies on the spans and holes both being sorted.)
193-
let relevant_input_covspans =
194-
drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi());
195-
196-
for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) {
197-
let (before, after) = covspan.split_around_hole_span(hole.span);
198-
bucket.extend(before);
199-
fragments.extend(after);
200-
}
185+
bucket.extend(
186+
drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi())
187+
.filter(|c| !c.span.overlaps(hole.span)),
188+
);
201189
}
202190

203-
// After finding the spans before each hole, any remaining fragments/spans
204-
// form their own final bucket, after the final hole.
191+
// Any remaining spans form their own final bucket, after the final hole.
205192
// (If there were no holes, this will just be all of the initial spans.)
206-
fragments.extend(input_covspans);
207-
buckets.push(fragments);
193+
buckets.push(Vec::from(input_covspans));
208194

209195
buckets
210196
}
@@ -215,7 +201,7 @@ fn drain_front_while<'a, T>(
215201
queue: &'a mut VecDeque<T>,
216202
mut pred_fn: impl FnMut(&T) -> bool,
217203
) -> impl Iterator<Item = T> {
218-
std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
204+
iter::from_fn(move || queue.pop_front_if(|x| pred_fn(x)))
219205
}
220206

221207
/// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines"
@@ -258,22 +244,6 @@ struct Covspan {
258244
}
259245

260246
impl Covspan {
261-
/// Splits this covspan into 0-2 parts:
262-
/// - The part that is strictly before the hole span, if any.
263-
/// - The part that is strictly after the hole span, if any.
264-
fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
265-
let before = try {
266-
let span = self.span.trim_end(hole_span)?;
267-
Self { span, ..*self }
268-
};
269-
let after = try {
270-
let span = self.span.trim_start(hole_span)?;
271-
Self { span, ..*self }
272-
};
273-
274-
(before, after)
275-
}
276-
277247
/// If `self` and `other` can be merged (i.e. they have the same BCB),
278248
/// mutates `self.span` to also include `other.span` and returns true.
279249
///

Diff for: compiler/rustc_mir_transform/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#![feature(map_try_insert)]
1313
#![feature(never_type)]
1414
#![feature(try_blocks)]
15+
#![feature(vec_deque_pop_if)]
1516
#![feature(yeet_expr)]
1617
// tidy-alphabetical-end
1718

Diff for: tests/coverage/async_block.cov-map

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Function name: async_block::main
2-
Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 00, 14, 01, 16, 02, 07, 0a, 02, 06, 01, 03, 01, 00, 02]
2+
Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 01, 0d, 00, 13, 02, 07, 09, 00, 22, 01, 02, 01, 00, 02]
33
Number of files: 1
44
- file 0 => global file 1
55
Number of expressions: 1
@@ -9,11 +9,11 @@ Number of file 0 mappings: 6
99
- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
1010
= (c1 - c0)
1111
- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19)
12-
- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 1, 22)
12+
- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19)
1313
= (c1 - c0)
14-
- Code(Expression(0, Sub)) at (prev + 7, 10) to (start + 2, 6)
14+
- Code(Expression(0, Sub)) at (prev + 7, 9) to (start + 0, 34)
1515
= (c1 - c0)
16-
- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
16+
- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2)
1717
Highest counter ID seen: c1
1818

1919
Function name: async_block::main::{closure#0}

Diff for: tests/coverage/async_block.coverage

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
LL| 12| }
1616
LL| 16| };
1717
LL| 16| executor::block_on(future);
18-
LL| 16| }
18+
LL| | }
1919
LL| 1|}
2020

Diff for: tests/coverage/async_closure.cov-map

+8-6
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ Number of file 0 mappings: 2
3030
Highest counter ID seen: c0
3131

3232
Function name: async_closure::main::{closure#0}
33-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
33+
Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
3434
Number of files: 1
3535
- file 0 => global file 1
3636
Number of expressions: 0
37-
Number of file 0 mappings: 1
38-
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
37+
Number of file 0 mappings: 2
38+
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
39+
- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
3940
Highest counter ID seen: c0
4041

4142
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
@@ -48,11 +49,12 @@ Number of file 0 mappings: 1
4849
Highest counter ID seen: c0
4950

5051
Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
51-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
52+
Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
5253
Number of files: 1
5354
- file 0 => global file 1
5455
Number of expressions: 0
55-
Number of file 0 mappings: 1
56-
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
56+
Number of file 0 mappings: 2
57+
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
58+
- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
5759
Highest counter ID seen: c0
5860

Diff for: tests/coverage/async_closure.coverage

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
LL| |
1010
LL| 1|pub fn main() {
1111
LL| 2| let async_closure = async || {};
12-
^1
1312
------------------
1413
| async_closure::main::{closure#0}:
1514
| LL| 1| let async_closure = async || {};
1615
------------------
16+
| async_closure::main::{closure#0}::{closure#0}::<i16>:
17+
| LL| 1| let async_closure = async || {};
18+
------------------
1719
| async_closure::main::{closure#0}::{closure#1}::<i32>:
1820
| LL| 1| let async_closure = async || {};
1921
------------------

Diff for: tests/coverage/closure.cov-map

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
Function name: closure::main
2-
Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02]
2+
Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0d, 1b, 01, 1a, 05, 02, 0a, 01, 0c, 05, 11, 1b, 01, 1e, 05, 02, 0a, 01, 0c, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02]
33
Number of files: 1
44
- file 0 => global file 1
55
Number of expressions: 1
66
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
77
Number of file 0 mappings: 24
8-
- Code(Counter(0)) at (prev + 9, 1) to (start + 15, 13)
9-
- Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10)
10-
- Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13)
11-
- Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10)
12-
- Code(Counter(0)) at (prev + 16, 5) to (start + 12, 22)
8+
- Code(Counter(0)) at (prev + 9, 1) to (start + 13, 27)
9+
- Code(Counter(0)) at (prev + 26, 5) to (start + 2, 10)
10+
- Code(Counter(0)) at (prev + 12, 5) to (start + 17, 27)
11+
- Code(Counter(0)) at (prev + 30, 5) to (start + 2, 10)
12+
- Code(Counter(0)) at (prev + 12, 5) to (start + 12, 22)
1313
- Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24)
1414
- Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30)
1515
- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41)

Diff for: tests/coverage/closure.coverage

+11-11
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,18 @@
2020
LL| 1| some_string
2121
LL| 1| .
2222
LL| 1| unwrap_or_else
23-
LL| 1| (
24-
LL| 1| ||
23+
LL| | (
24+
LL| | ||
2525
LL| 0| {
2626
LL| 0| let mut countdown = 0;
2727
LL| 0| if is_false {
2828
LL| 0| countdown = 10;
2929
LL| 0| }
3030
LL| 0| "alt string 1".to_owned()
31-
LL| 1| }
32-
LL| 1| )
33-
LL| 1| );
34-
LL| 1|
31+
LL| 0| }
32+
LL| | )
33+
LL| | );
34+
LL| |
3535
LL| 1| some_string = Some(String::from("the string content"));
3636
LL| 1| let
3737
LL| 1| a
@@ -62,18 +62,18 @@
6262
LL| 1| some_string
6363
LL| 1| .
6464
LL| 1| unwrap_or_else
65-
LL| 1| (
66-
LL| 1| ||
65+
LL| | (
66+
LL| | ||
6767
LL| 1| {
6868
LL| 1| let mut countdown = 0;
6969
LL| 1| if is_false {
7070
LL| 0| countdown = 10;
7171
LL| 1| }
7272
LL| 1| "alt string 3".to_owned()
7373
LL| 1| }
74-
LL| 1| )
75-
LL| 1| );
76-
LL| 1|
74+
LL| | )
75+
LL| | );
76+
LL| |
7777
LL| 1| some_string = None;
7878
LL| 1| let
7979
LL| 1| a

Diff for: tests/coverage/holes.cov-map

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Number of file 0 mappings: 1
88
Highest counter ID seen: (none)
99

1010
Function name: holes::main
11-
Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02]
11+
Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 06, 27, 01, 13, 05, 01, 02]
1212
Number of files: 1
1313
- file 0 => global file 1
1414
Number of expressions: 0
@@ -24,8 +24,8 @@ Number of file 0 mappings: 13
2424
- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17)
2525
- Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15)
2626
- Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15)
27-
- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13)
28-
- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2)
27+
- Code(Counter(0)) at (prev + 10, 5) to (start + 6, 39)
28+
- Code(Counter(0)) at (prev + 19, 5) to (start + 1, 2)
2929
Highest counter ID seen: c0
3030

3131
Function name: holes::main::_unused_fn (unused)

Diff for: tests/coverage/holes.coverage

+10-10
Original file line numberDiff line numberDiff line change
@@ -84,18 +84,18 @@
8484
LL| 1| // `nested_filter::OnlyBodies` or equivalent.
8585
LL| 1| #[rustfmt::skip]
8686
LL| 1| let _const_block_inside_anon_const =
87-
LL| 1| [
88-
LL| 1| 0
89-
LL| 1| ;
90-
LL| 1| 7
91-
LL| 1| +
92-
LL| 1| const
87+
LL| | [
88+
LL| | 0
89+
LL| | ;
90+
LL| | 7
91+
LL| | +
92+
LL| | const
9393
LL| | {
9494
LL| | 3
95-
LL| 1| }
96-
LL| 1| ]
97-
LL| 1| ;
98-
LL| 1|
95+
LL| | }
96+
LL| | ]
97+
LL| | ;
98+
LL| |
9999
LL| 1| black_box(());
100100
LL| 1|}
101101

0 commit comments

Comments
 (0)