Skip to content

Commit cd3a8c1

Browse files
committed
Removes unneeded check of #[no_coverage] in mapgen
And adds tests to validate it still works. There is an anticipated feature request to support a compiler flag that only adds coverage for specific files (or perhaps mods). As I thought about where that change would need to be supported, I realized that checking the attribute in mapgen (for unused functions) was unnecessary. The unused functions are only synthesized if they have MIR coverage, and functions with the `no_coverage` attribute will not have been instrumented with MIR coverage statements in the first place. New tests confirm this. Also, while adding tests, I updated resolved comments and FIXMEs in other tests.
1 parent 716394d commit cd3a8c1

File tree

9 files changed

+56
-95
lines changed

9 files changed

+56
-95
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods};
88
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
99
use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
1010
use rustc_llvm::RustString;
11-
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1211
use rustc_middle::mir::coverage::CodeRegion;
1312
use rustc_span::Symbol;
1413

@@ -281,11 +280,8 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
281280

282281
let mut unused_def_ids_by_file: FxHashMap<Symbol, Vec<DefId>> = FxHashMap::default();
283282
for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) {
284-
let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id);
285-
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) {
286-
continue;
287-
}
288-
// Make sure the non-codegenned (unused) function has a file_name
283+
// Make sure the non-codegenned (unused) function has at least one MIR
284+
// `Coverage` statement with a code region, and return its file name.
289285
if let Some(non_codegenned_file_name) = tcx.covered_file_name(non_codegenned_def_id) {
290286
let def_ids =
291287
unused_def_ids_by_file.entry(*non_codegenned_file_name).or_insert_with(Vec::new);

src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
14| 1| }
1515
15| 1|}
1616
16| |
17-
17| |// FIXME(#83985): The auto-generated closure in an async function is failing to include
18-
18| |// the println!() and `let` assignment lines in the coverage code region(s), as it does in the
19-
19| |// non-async function above, unless the `println!()` is inside a covered block.
17+
17| |
18+
18| |
19+
19| |
2020
20| 1|async fn async_func() {
2121
21| 1| println!("async_func was covered");
2222
22| 1| let b = true;
@@ -26,9 +26,9 @@
2626
^0
2727
26| 1|}
2828
27| |
29-
28| |// FIXME(#83985): As above, this async function only has the `println!()` macro call, which is not
30-
29| |// showing coverage, so the entire async closure _appears_ uncovered; but this is not exactly true.
31-
30| |// It's only certain kinds of lines and/or their context that results in missing coverage.
29+
28| |
30+
29| |
31+
30| |
3232
31| 1|async fn async_func_just_println() {
3333
32| 1| println!("async_func_just_println was covered");
3434
33| 1|}

src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.no_cov_crate.txt

+23-4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,27 @@
1111
11| | println!("called but not covered");
1212
12| |}
1313
13| |
14-
14| 1|fn main() {
15-
15| 1| do_not_add_coverage_1();
16-
16| 1| do_not_add_coverage_2();
17-
17| 1|}
14+
14| |#[no_coverage]
15+
15| |fn do_not_add_coverage_not_called() {
16+
16| | println!("not called and not covered");
17+
17| |}
18+
18| |
19+
19| 1|fn add_coverage_1() {
20+
20| 1| println!("called and covered");
21+
21| 1|}
22+
22| |
23+
23| 1|fn add_coverage_2() {
24+
24| 1| println!("called and covered");
25+
25| 1|}
26+
26| |
27+
27| 0|fn add_coverage_not_called() {
28+
28| 0| println!("not called but covered");
29+
29| 0|}
30+
30| |
31+
31| 1|fn main() {
32+
32| 1| do_not_add_coverage_1();
33+
33| 1| do_not_add_coverage_2();
34+
34| 1| add_coverage_1();
35+
35| 1| add_coverage_2();
36+
36| 1|}
1837

src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.no_cov_func.txt

-19
This file was deleted.

src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.panic_unwind.txt

-18
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,4 @@
2929
29| |// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
3030
30| |// normal program exit cleanup, including writing out the current values of the coverage
3131
31| |// counters.
32-
32| |// 3. The coverage results show (interestingly) that the `panic!()` call did execute, but it does
33-
33| |// not show coverage of the `if countdown == 1` branch in `main()` that calls
34-
34| |// `might_panic(true)` (causing the call to `panic!()`).
35-
35| |// 4. The reason `main()`s `if countdown == 1` branch, calling `might_panic(true)`, appears
36-
36| |// "uncovered" is, InstrumentCoverage (intentionally) treats `TerminatorKind::Call` terminators
37-
37| |// as non-branching, because when a program executes normally, they always are. Errors handled
38-
38| |// via the try `?` operator produce error handling branches that *are* treated as branches in
39-
39| |// coverage results. By treating calls without try `?` operators as non-branching (assumed to
40-
40| |// return normally and continue) the coverage graph can be simplified, producing smaller,
41-
41| |// faster binaries, and cleaner coverage results.
42-
42| |// 5. The reason the coverage results actually show `panic!()` was called is most likely because
43-
43| |// `panic!()` is a macro, not a simple function call, and there are other `Statement`s and/or
44-
44| |// `Terminator`s that execute with a coverage counter before the panic and unwind occur.
45-
45| |// 6. Since the common practice is not to use `panic!()` for error handling, the coverage
46-
46| |// implementation avoids incurring an additional cost (in program size and execution time) to
47-
47| |// improve coverage results for an event that is generally not "supposed" to happen.
48-
48| |// 7. FIXME(#78544): This issue describes a feature request for a proposed option to enable
49-
49| |// more accurate coverage results for tests that intentionally panic.
5032

src/test/run-make-fulldeps/coverage/async2.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ fn non_async_func() {
1414
}
1515
}
1616

17-
// FIXME(#83985): The auto-generated closure in an async function is failing to include
18-
// the println!() and `let` assignment lines in the coverage code region(s), as it does in the
19-
// non-async function above, unless the `println!()` is inside a covered block.
17+
18+
19+
2020
async fn async_func() {
2121
println!("async_func was covered");
2222
let b = true;
@@ -25,9 +25,9 @@ async fn async_func() {
2525
}
2626
}
2727

28-
// FIXME(#83985): As above, this async function only has the `println!()` macro call, which is not
29-
// showing coverage, so the entire async closure _appears_ uncovered; but this is not exactly true.
30-
// It's only certain kinds of lines and/or their context that results in missing coverage.
28+
29+
30+
3131
async fn async_func_just_println() {
3232
println!("async_func_just_println was covered");
3333
}

src/test/run-make-fulldeps/coverage/no_cov_crate.rs

+19
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,26 @@ fn do_not_add_coverage_2() {
1111
println!("called but not covered");
1212
}
1313

14+
#[no_coverage]
15+
fn do_not_add_coverage_not_called() {
16+
println!("not called and not covered");
17+
}
18+
19+
fn add_coverage_1() {
20+
println!("called and covered");
21+
}
22+
23+
fn add_coverage_2() {
24+
println!("called and covered");
25+
}
26+
27+
fn add_coverage_not_called() {
28+
println!("not called but covered");
29+
}
30+
1431
fn main() {
1532
do_not_add_coverage_1();
1633
do_not_add_coverage_2();
34+
add_coverage_1();
35+
add_coverage_2();
1736
}

src/test/run-make-fulldeps/coverage/no_cov_func.rs

-18
This file was deleted.

src/test/run-make-fulldeps/coverage/panic_unwind.rs

-18
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,3 @@ fn main() -> Result<(), u8> {
2929
// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
3030
// normal program exit cleanup, including writing out the current values of the coverage
3131
// counters.
32-
// 3. The coverage results show (interestingly) that the `panic!()` call did execute, but it does
33-
// not show coverage of the `if countdown == 1` branch in `main()` that calls
34-
// `might_panic(true)` (causing the call to `panic!()`).
35-
// 4. The reason `main()`s `if countdown == 1` branch, calling `might_panic(true)`, appears
36-
// "uncovered" is, InstrumentCoverage (intentionally) treats `TerminatorKind::Call` terminators
37-
// as non-branching, because when a program executes normally, they always are. Errors handled
38-
// via the try `?` operator produce error handling branches that *are* treated as branches in
39-
// coverage results. By treating calls without try `?` operators as non-branching (assumed to
40-
// return normally and continue) the coverage graph can be simplified, producing smaller,
41-
// faster binaries, and cleaner coverage results.
42-
// 5. The reason the coverage results actually show `panic!()` was called is most likely because
43-
// `panic!()` is a macro, not a simple function call, and there are other `Statement`s and/or
44-
// `Terminator`s that execute with a coverage counter before the panic and unwind occur.
45-
// 6. Since the common practice is not to use `panic!()` for error handling, the coverage
46-
// implementation avoids incurring an additional cost (in program size and execution time) to
47-
// improve coverage results for an event that is generally not "supposed" to happen.
48-
// 7. FIXME(#78544): This issue describes a feature request for a proposed option to enable
49-
// more accurate coverage results for tests that intentionally panic.

0 commit comments

Comments
 (0)