Skip to content

Commit 84c4b16

Browse files
committed
coverage: Hoist the splitting of visible macro invocations
1 parent 4b96161 commit 84c4b16

File tree

3 files changed

+54
-58
lines changed

3 files changed

+54
-58
lines changed

compiler/rustc_mir_transform/src/coverage/spans.rs

-34
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ impl<'a> CoverageSpansGenerator<'a> {
215215
// span-processing steps don't make sense yet.
216216
if self.some_prev.is_none() {
217217
debug!(" initial span");
218-
self.maybe_push_macro_name_span();
219218
continue;
220219
}
221220

@@ -227,15 +226,13 @@ impl<'a> CoverageSpansGenerator<'a> {
227226
debug!(" same bcb (and neither is a closure), merge with prev={prev:?}");
228227
let prev = self.take_prev();
229228
self.curr_mut().merge_from(&prev);
230-
self.maybe_push_macro_name_span();
231229
// Note that curr.span may now differ from curr_original_span
232230
} else if prev.span.hi() <= curr.span.lo() {
233231
debug!(
234232
" different bcbs and disjoint spans, so keep curr for next iter, and add prev={prev:?}",
235233
);
236234
let prev = self.take_prev();
237235
self.refined_spans.push(prev);
238-
self.maybe_push_macro_name_span();
239236
} else if prev.is_closure {
240237
// drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
241238
// next iter
@@ -251,7 +248,6 @@ impl<'a> CoverageSpansGenerator<'a> {
251248
self.update_pending_dups();
252249
} else {
253250
self.cutoff_prev_at_overlapping_curr();
254-
self.maybe_push_macro_name_span();
255251
}
256252
}
257253

@@ -286,36 +282,6 @@ impl<'a> CoverageSpansGenerator<'a> {
286282
self.refined_spans
287283
}
288284

289-
/// If `curr` is part of a new macro expansion, carve out and push a separate
290-
/// span that ends just after the macro name and its subsequent `!`.
291-
fn maybe_push_macro_name_span(&mut self) {
292-
let curr = self.curr();
293-
294-
let Some(visible_macro) = curr.visible_macro else { return };
295-
296-
// The split point is relative to `curr_original_span`,
297-
// because `curr.span` may have been merged with preceding spans.
298-
let split_point_after_macro_bang = self.curr_original_span.lo()
299-
+ BytePos(visible_macro.as_str().len() as u32)
300-
+ BytePos(1); // add 1 for the `!`
301-
debug_assert!(split_point_after_macro_bang <= curr.span.hi());
302-
if split_point_after_macro_bang > curr.span.hi() {
303-
// Something is wrong with the macro name span;
304-
// return now to avoid emitting malformed mappings (e.g. #117788).
305-
return;
306-
}
307-
308-
let mut macro_name_cov = curr.clone();
309-
macro_name_cov.span = macro_name_cov.span.with_hi(split_point_after_macro_bang);
310-
self.curr_mut().span = curr.span.with_lo(split_point_after_macro_bang);
311-
312-
debug!(
313-
" and curr starts a new macro expansion, so add a new span just for \
314-
the macro `{visible_macro}!`, new span={macro_name_cov:?}",
315-
);
316-
self.refined_spans.push(macro_name_cov);
317-
}
318-
319285
#[track_caller]
320286
fn curr(&self) -> &CoverageSpan {
321287
self.some_curr.as_ref().unwrap_or_else(|| bug!("some_curr is None (curr)"))

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

+36
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
3838

3939
initial_spans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb));
4040
remove_unwanted_macro_spans(&mut initial_spans);
41+
split_visible_macro_spans(&mut initial_spans);
4142

4243
initial_spans.sort_by(|a, b| {
4344
// First sort by span start.
@@ -79,6 +80,41 @@ fn remove_unwanted_macro_spans(initial_spans: &mut Vec<CoverageSpan>) {
7980
});
8081
}
8182

83+
/// When a span corresponds to a macro invocation that is visible from the
84+
/// function body, split it into two parts. The first part covers just the
85+
/// macro name plus `!`, and the second part covers the rest of the macro
86+
/// invocation. This seems to give better results for code that uses macros.
87+
fn split_visible_macro_spans(initial_spans: &mut Vec<CoverageSpan>) {
88+
let mut extra_spans = vec![];
89+
90+
initial_spans.retain(|covspan| {
91+
if covspan.is_closure {
92+
return true;
93+
}
94+
95+
let Some(visible_macro) = covspan.visible_macro else { return true };
96+
97+
let split_len = visible_macro.as_str().len() as u32 + 1;
98+
let (before, after) = covspan.span.split_at(split_len);
99+
if !covspan.span.contains(before) || !covspan.span.contains(after) {
100+
// Something is unexpectedly wrong with the split point.
101+
// The debug assertion in `split_at` will have already caught this,
102+
// but in release builds it's safer to do nothing and maybe get a
103+
// bug report for unexpected coverage, rather than risk an ICE.
104+
return true;
105+
}
106+
107+
assert!(!covspan.is_closure);
108+
extra_spans.push(CoverageSpan::new(before, covspan.visible_macro, covspan.bcb, false));
109+
extra_spans.push(CoverageSpan::new(after, covspan.visible_macro, covspan.bcb, false));
110+
false // Discard the original covspan that we just split.
111+
});
112+
113+
// The newly-split spans are added at the end, so any previous sorting
114+
// is not preserved.
115+
initial_spans.extend(extra_spans);
116+
}
117+
82118
// Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of
83119
// the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One `CoverageSpan` is generated
84120
// for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will

tests/coverage/closure.cov-map

+18-24
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,18 @@ Number of file 0 mappings: 1
8181
- Code(Zero) at (prev + 171, 13) to (start + 2, 14)
8282

8383
Function name: closure::main::{closure#14}
84-
Raw bytes (36): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 05, 03, b2, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 01, 0d, 00, 0e]
84+
Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, b2, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e]
8585
Number of files: 1
8686
- file 0 => global file 1
87-
Number of expressions: 3
88-
- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub)
89-
- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
90-
- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
91-
Number of file 0 mappings: 5
92-
- Code(Expression(0, Add)) at (prev + 178, 13) to (start + 0, 21)
93-
= (c1 + (c0 - c1))
94-
- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27)
95-
- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37)
96-
- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51)
87+
Number of expressions: 2
88+
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
89+
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
90+
Number of file 0 mappings: 4
91+
- Code(Counter(0)) at (prev + 178, 13) to (start + 2, 27)
92+
- Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37)
93+
- Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51)
9794
= (c0 - c1)
98-
- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 14)
95+
- Code(Expression(1, Add)) at (prev + 1, 13) to (start + 0, 14)
9996
= (c1 + (c0 - c1))
10097

10198
Function name: closure::main::{closure#15}
@@ -118,21 +115,18 @@ Number of file 0 mappings: 6
118115
= (c1 + (c0 - c1))
119116

120117
Function name: closure::main::{closure#16}
121-
Raw bytes (36): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 05, 03, c4, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 01, 0d, 00, 0e]
118+
Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, c4, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e]
122119
Number of files: 1
123120
- file 0 => global file 1
124-
Number of expressions: 3
125-
- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub)
126-
- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
127-
- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
128-
Number of file 0 mappings: 5
129-
- Code(Expression(0, Add)) at (prev + 196, 13) to (start + 0, 21)
130-
= (c1 + (c0 - c1))
131-
- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27)
132-
- Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37)
133-
- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51)
121+
Number of expressions: 2
122+
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
123+
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
124+
Number of file 0 mappings: 4
125+
- Code(Counter(0)) at (prev + 196, 13) to (start + 2, 27)
126+
- Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37)
127+
- Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51)
134128
= (c0 - c1)
135-
- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 14)
129+
- Code(Expression(1, Add)) at (prev + 1, 13) to (start + 0, 14)
136130
= (c1 + (c0 - c1))
137131

138132
Function name: closure::main::{closure#17}

0 commit comments

Comments
 (0)