Skip to content

Commit 134d9d0

Browse files
authored
Rollup merge of rust-lang#121135 - Zalathar:no-whole-body-span, r=wesleywiser
coverage: Discard spans that fill the entire function body While debugging some other coverage changes, I discovered a frustrating inconsistency that occurs in functions containing closures, if they end with an implicit `()` return instead of an explicit trailing-expression. This turns out to have been caused by the corresponding node in MIR having a span that covers the entire function body. When preparing coverage spans, any span that fills the whole body tends to cause more harm than good, so this PR detects and discards those spans. (This isn't the first time whole-body spans have caused problems; we also eliminated some of them in rust-lang#118525.)
2 parents 7fedf99 + cd9021e commit 134d9d0

11 files changed

+117
-28
lines changed

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,23 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
132132
bcb_data.basic_blocks.iter().flat_map(move |&bb| {
133133
let data = &mir_body[bb];
134134

135+
let unexpand = move |expn_span| {
136+
unexpand_into_body_span_with_visible_macro(expn_span, body_span)
137+
// Discard any spans that fill the entire body, because they tend
138+
// to represent compiler-inserted code, e.g. implicitly returning `()`.
139+
.filter(|(span, _)| !span.source_equal(body_span))
140+
};
141+
135142
let statement_spans = data.statements.iter().filter_map(move |statement| {
136143
let expn_span = filtered_statement_span(statement)?;
137-
let (span, visible_macro) =
138-
unexpand_into_body_span_with_visible_macro(expn_span, body_span)?;
144+
let (span, visible_macro) = unexpand(expn_span)?;
139145

140146
Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement)))
141147
});
142148

143149
let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| {
144150
let expn_span = filtered_terminator_span(terminator)?;
145-
let (span, visible_macro) =
146-
unexpand_into_body_span_with_visible_macro(expn_span, body_span)?;
151+
let (span, visible_macro) = unexpand(expn_span)?;
147152

148153
Some(SpanFromMir::new(span, visible_macro, bcb, false))
149154
});
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Function name: closure_unit_return::explicit_unit
2+
Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 01, 01, 10, 01, 05, 05, 02, 02]
3+
Number of files: 1
4+
- file 0 => global file 1
5+
Number of expressions: 0
6+
Number of file 0 mappings: 2
7+
- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 16)
8+
- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2)
9+
10+
Function name: closure_unit_return::explicit_unit::{closure#0} (unused)
11+
Raw bytes (9): 0x[01, 01, 00, 01, 00, 08, 16, 02, 06]
12+
Number of files: 1
13+
- file 0 => global file 1
14+
Number of expressions: 0
15+
Number of file 0 mappings: 1
16+
- Code(Zero) at (prev + 8, 22) to (start + 2, 6)
17+
18+
Function name: closure_unit_return::implicit_unit
19+
Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 10, 01, 05, 05, 02, 02]
20+
Number of files: 1
21+
- file 0 => global file 1
22+
Number of expressions: 0
23+
Number of file 0 mappings: 2
24+
- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 16)
25+
- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2)
26+
27+
Function name: closure_unit_return::implicit_unit::{closure#0} (unused)
28+
Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06]
29+
Number of files: 1
30+
- file 0 => global file 1
31+
Number of expressions: 0
32+
Number of file 0 mappings: 1
33+
- Code(Zero) at (prev + 17, 22) to (start + 2, 6)
34+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
LL| |#![feature(coverage_attribute)]
2+
LL| |// edition: 2021
3+
LL| |
4+
LL| |// Regression test for an inconsistency between functions that return the value
5+
LL| |// of their trailing expression, and functions that implicitly return `()`.
6+
LL| |
7+
LL| 1|fn explicit_unit() {
8+
LL| 1| let closure = || {
9+
LL| 0| ();
10+
LL| 0| };
11+
LL| |
12+
LL| 1| drop(closure);
13+
LL| 1| () // explicit return of trailing value
14+
LL| 1|}
15+
LL| |
16+
LL| 1|fn implicit_unit() {
17+
LL| 1| let closure = || {
18+
LL| 0| ();
19+
LL| 0| };
20+
LL| |
21+
LL| 1| drop(closure);
22+
LL| 1| // implicit return of `()`
23+
LL| 1|}
24+
LL| |
25+
LL| |#[coverage(off)]
26+
LL| |fn main() {
27+
LL| | explicit_unit();
28+
LL| | implicit_unit();
29+
LL| |}
30+

tests/coverage/closure_unit_return.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![feature(coverage_attribute)]
2+
// edition: 2021
3+
4+
// Regression test for an inconsistency between functions that return the value
5+
// of their trailing expression, and functions that implicitly return `()`.
6+
7+
fn explicit_unit() {
8+
let closure = || {
9+
();
10+
};
11+
12+
drop(closure);
13+
() // explicit return of trailing value
14+
}
15+
16+
fn implicit_unit() {
17+
let closure = || {
18+
();
19+
};
20+
21+
drop(closure);
22+
// implicit return of `()`
23+
}
24+
25+
#[coverage(off)]
26+
fn main() {
27+
explicit_unit();
28+
implicit_unit();
29+
}

tests/coverage/coverage_attr_closure.cov-map

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ Number of file 0 mappings: 1
1515
- Code(Zero) at (prev + 29, 19) to (start + 2, 6)
1616

1717
Function name: coverage_attr_closure::contains_closures_on
18-
Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 02, 05, 01, 04, 06, 02, 05, 01, 04, 06, 01, 02]
18+
Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 01, 1a, 01, 05, 09, 00, 1b, 01, 04, 01, 00, 02]
1919
Number of files: 1
2020
- file 0 => global file 1
2121
Number of expressions: 0
2222
Number of file 0 mappings: 3
23-
- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 5)
24-
- Code(Counter(0)) at (prev + 4, 6) to (start + 2, 5)
25-
- Code(Counter(0)) at (prev + 4, 6) to (start + 1, 2)
23+
- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 26)
24+
- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 27)
25+
- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2)
2626

2727
Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused)
2828
Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06]

tests/coverage/coverage_attr_closure.coverage

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
LL| |#[coverage(on)]
1515
LL| 1|fn contains_closures_on() {
1616
LL| 1| let _local_closure_on = #[coverage(on)]
17-
LL| 1| |input: &str| {
17+
LL| 0| |input: &str| {
1818
LL| 0| println!("{input}");
19-
LL| 1| };
19+
LL| 0| };
2020
LL| 1| let _local_closure_off = #[coverage(off)]
21-
LL| 1| |input: &str| {
21+
LL| | |input: &str| {
2222
LL| | println!("{input}");
23-
LL| 1| };
23+
LL| | };
2424
LL| 1|}
2525
LL| |
2626
LL| |#[coverage(off)]

tests/coverage/inline-dead.cov-map

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ Number of file 0 mappings: 4
2222
= (Zero + (c0 - Zero))
2323

2424
Function name: inline_dead::main
25-
Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 05, 06, 02, 02]
25+
Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02]
2626
Number of files: 1
2727
- file 0 => global file 1
2828
Number of expressions: 0
2929
Number of file 0 mappings: 2
30-
- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13)
31-
- Code(Counter(0)) at (prev + 5, 6) to (start + 2, 2)
30+
- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 10)
31+
- Code(Counter(0)) at (prev + 6, 5) to (start + 1, 2)
3232

3333
Function name: inline_dead::main::{closure#0}
3434
Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06]

tests/coverage/macro_name_span.cov-map

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Function name: macro_name_span::affected_function
2-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 02, 06]
2+
Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40]
33
Number of files: 1
44
- file 0 => global file 1
55
Number of expressions: 0
66
Number of file 0 mappings: 1
7-
- Code(Counter(0)) at (prev + 22, 28) to (start + 2, 6)
7+
- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64)
88

99
Function name: macro_name_span::main
1010
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02]

tests/coverage/macro_name_span.coverage

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
LL| |macro_name_span_helper::macro_that_defines_a_function! {
2222
LL| 1| fn affected_function() {
2323
LL| 1| macro_with_an_unreasonably_and_egregiously_long_name!();
24-
LL| 1| }
24+
LL| | }
2525
LL| |}
2626

tests/coverage/unicode.cov-map

-8
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,6 @@ Number of file 0 mappings: 9
2727
- Code(Expression(5, Add)) at (prev + 2, 5) to (start + 1, 2)
2828
= (c4 + ((((c0 + c1) - c1) - c2) + c3))
2929

30-
Function name: unicode::サビ
31-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 14, 00, 18]
32-
Number of files: 1
33-
- file 0 => global file 1
34-
Number of expressions: 0
35-
Number of file 0 mappings: 1
36-
- Code(Counter(0)) at (prev + 30, 20) to (start + 0, 24)
37-
3830
Function name: unicode::他 (unused)
3931
Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25]
4032
Number of files: 1

tests/coverage/unicode.coverage

+1-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
LL| |
3030
LL| |macro_rules! macro_that_defines_a_function {
3131
LL| | (fn $名:ident () $体:tt) => {
32-
LL| 1| fn $名 () $体 fn 他 () {}
33-
^0
32+
LL| 0| fn $名 () $体 fn 他 () {}
3433
LL| | }
3534
LL| |}
3635
LL| |

0 commit comments

Comments
 (0)