Skip to content

Commit

Permalink
Fixes reported bugs in Rust Coverage
Browse files Browse the repository at this point in the history
Fixes: #79569

Fixes: #79566
Fixes: #79565

For the first issue (#79569), I got hit a `debug_assert!()` before
encountering the reported error message (because I have `debug = true`
enabled in my config.toml).

The assertion showed me that some `SwitchInt`s can have more than one
target pointing to the same `BasicBlock`.

I had thought that was invalid, but since it seems to be possible, I'm
allowing this now.

I added a new test for this.

----

In the last two cases above, both tests (intentionally) fail to compile,
but the `InstrumentCoverage` pass is invoked anyway.

The MIR starts with an `Unreachable` `BasicBlock`, which I hadn't
encountered before. (I had assumed the `InstrumentCoverage` pass
would only be invoked with MIRs from successful compilations.)

I don't have test infrastructure set up to test coverage on files that
fail to compile, so I didn't add a new test.
  • Loading branch information
richkadel committed Dec 12, 2020
1 parent 9eb3a7c commit eb963ff
Show file tree
Hide file tree
Showing 8 changed files with 553 additions and 18 deletions.
28 changes: 16 additions & 12 deletions compiler/rustc_mir/src/transform/coverage/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,28 @@ impl CoverageGraph {

// Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock
// equivalents. Note that since the BasicCoverageBlock graph has been fully simplified, the
// each predecessor of a BCB leader_bb should be in a unique BCB, and each successor of a
// BCB last_bb should be in its own unique BCB. Therefore, collecting the BCBs using
// `bb_to_bcb` should work without requiring a deduplication step.
// each predecessor of a BCB leader_bb should be in a unique BCB. It is possible for a
// `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so
// de-duplication is required. This is done without reordering the successors.

let bcbs_len = bcbs.len();
let mut seen = IndexVec::from_elem_n(false, bcbs_len);
let successors = IndexVec::from_fn_n(
|bcb| {
for b in seen.iter_mut() {
*b = false;
}
let bcb_data = &bcbs[bcb];
let bcb_successors =
let mut bcb_successors = Vec::new();
for successor in
bcb_filtered_successors(&mir_body, &bcb_data.terminator(mir_body).kind)
.filter_map(|&successor_bb| bb_to_bcb[successor_bb])
.collect::<Vec<_>>();
debug_assert!({
let mut sorted = bcb_successors.clone();
sorted.sort_unstable();
let initial_len = sorted.len();
sorted.dedup();
sorted.len() == initial_len
});
{
if !seen[successor] {
seen[successor] = true;
bcb_successors.push(successor);
}
}
bcb_successors
},
bcbs.len(),
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_mir/src/transform/coverage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
return;
}

match mir_body.basic_blocks()[mir::START_BLOCK].terminator().kind {
TerminatorKind::Unreachable => {
trace!("InstrumentCoverage skipped for unreachable `START_BLOCK`");
return;
}
_ => {}
}

trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());
Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"data": [
{
"files": [
{
"filename": "../coverage/match_or_pattern.rs",
"summary": {
"functions": {
"count": 1,
"covered": 1,
"percent": 100
},
"instantiations": {
"count": 1,
"covered": 1,
"percent": 100
},
"lines": {
"count": 37,
"covered": 33,
"percent": 89.1891891891892
},
"regions": {
"count": 25,
"covered": 17,
"notcovered": 8,
"percent": 68
}
}
}
],
"totals": {
"functions": {
"count": 1,
"covered": 1,
"percent": 100
},
"instantiations": {
"count": 1,
"covered": 1,
"percent": 100
},
"lines": {
"count": 37,
"covered": 33,
"percent": 89.1891891891892
},
"regions": {
"count": 25,
"covered": 17,
"notcovered": 8,
"percent": 68
}
}
}
],
"type": "llvm.coverage.json.export",
"version": "2.0.1"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
1| |#![feature(or_patterns)]
2| |
3| 1|fn main() {
4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
6| 1| // dependent conditions.
7| 1| let is_true = std::env::args().len() == 1;
8| 1|
9| 1| let mut a: u8 = 0;
10| 1| let mut b: u8 = 0;
11| 1| if is_true {
12| 1| a = 2;
13| 1| b = 0;
14| 1| }
^0
15| 1| match (a, b) {
16| | // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
17| | // This test confirms a fix for Issue #79569.
18| 0| (0 | 1, 2 | 3) => {}
19| 1| _ => {}
20| | }
21| 1| if is_true {
22| 1| a = 0;
23| 1| b = 0;
24| 1| }
^0
25| 1| match (a, b) {
26| 0| (0 | 1, 2 | 3) => {}
27| 1| _ => {}
28| | }
29| 1| if is_true {
30| 1| a = 2;
31| 1| b = 2;
32| 1| }
^0
33| 1| match (a, b) {
34| 0| (0 | 1, 2 | 3) => {}
35| 1| _ => {}
36| | }
37| 1| if is_true {
38| 1| a = 0;
39| 1| b = 2;
40| 1| }
^0
41| 1| match (a, b) {
42| 1| (0 | 1, 2 | 3) => {}
43| 0| _ => {}
44| | }
45| 1|}

Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,8 @@ Counter in file 0 79:14 -> 79:16, 0
Counter in file 0 81:1 -> 81:2, 0
Counter in file 0 91:25 -> 91:34, 0
Counter in file 0 5:1 -> 5:25, #1
Counter in file 0 5:25 -> 6:14, #1
Counter in file 0 7:9 -> 7:10, #2
Counter in file 0 9:9 -> 9:10, (#1 - #2)
Counter in file 0 11:1 -> 11:2, (#2 + (#1 - #2))
Counter in file 0 21:1 -> 21:23, #1
Counter in file 0 17:20 -> 17:21, #1
Counter in file 0 67:5 -> 67:23, #1
Counter in file 0 38:1 -> 38:19, #1
Counter in file 0 38:19 -> 42:12, #1
Expand All @@ -46,14 +43,18 @@ Counter in file 0 44:27 -> 44:32, #8
Counter in file 0 44:36 -> 44:38, (#6 + 0)
Counter in file 0 45:14 -> 45:16, #7
Counter in file 0 47:1 -> 47:2, (#5 + (#6 + #7))
Counter in file 0 13:20 -> 13:21, #1
Counter in file 0 29:1 -> 29:22, #1
Counter in file 0 93:1 -> 101:2, #1
Counter in file 0 91:1 -> 91:25, #1
Counter in file 0 5:25 -> 6:14, #1
Counter in file 0 7:9 -> 7:10, #2
Counter in file 0 9:9 -> 9:10, (#1 - #2)
Counter in file 0 11:1 -> 11:2, (#2 + (#1 - #2))
Counter in file 0 51:5 -> 52:18, #1
Counter in file 0 53:13 -> 53:14, #2
Counter in file 0 63:13 -> 63:14, (#1 - #2)
Counter in file 0 65:5 -> 65:6, (#2 + (#1 - #2))
Counter in file 0 17:20 -> 17:21, #1
Counter in file 0 49:1 -> 68:12, #1
Counter in file 0 69:9 -> 69:10, #2
Counter in file 0 69:14 -> 69:27, (#1 + 0)
Expand All @@ -70,7 +71,6 @@ Counter in file 0 87:14 -> 87:16, #3
Counter in file 0 89:1 -> 89:2, (#3 + (#2 + (#1 - (#3 + #2))))
Counter in file 0 17:1 -> 17:20, #1
Counter in file 0 66:5 -> 66:23, #1
Counter in file 0 13:20 -> 13:21, #1
Counter in file 0 17:9 -> 17:10, #1
Counter in file 0 17:9 -> 17:10, #1
Counter in file 0 117:17 -> 117:19, #1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
Counter in file 0 3:1 -> 11:15, #1
Counter in file 0 11:16 -> 14:6, #2
Counter in file 0 14:6 -> 14:7, (#1 - #2)
Counter in file 0 15:11 -> 15:17, (#2 + (#1 - #2))
Counter in file 0 18:27 -> 18:29, #5
Counter in file 0 19:14 -> 19:16, (#3 + #4)
Counter in file 0 21:8 -> 21:15, ((#3 + #4) + #5)
Counter in file 0 21:16 -> 24:6, #6
Counter in file 0 24:6 -> 24:7, (((#3 + #4) + #5) - #6)
Counter in file 0 25:11 -> 25:17, (#6 + (((#3 + #4) + #5) - #6))
Counter in file 0 26:27 -> 26:29, #9
Counter in file 0 27:14 -> 27:16, (#7 + #8)
Counter in file 0 29:8 -> 29:15, ((#7 + #8) + #9)
Counter in file 0 29:16 -> 32:6, #10
Counter in file 0 32:6 -> 32:7, (((#7 + #8) + #9) - #10)
Counter in file 0 33:11 -> 33:17, (#10 + (((#7 + #8) + #9) - #10))
Counter in file 0 34:27 -> 34:29, #13
Counter in file 0 35:14 -> 35:16, (#11 + #12)
Counter in file 0 37:8 -> 37:15, ((#11 + #12) + #13)
Counter in file 0 37:16 -> 40:6, #14
Counter in file 0 40:6 -> 40:7, (((#11 + #12) + #13) - #14)
Counter in file 0 41:11 -> 41:17, (#14 + (((#11 + #12) + #13) - #14))
Counter in file 0 42:27 -> 42:29, #17
Counter in file 0 43:14 -> 43:16, (#15 + #16)
Counter in file 0 45:1 -> 45:2, ((#15 + #16) + #17)
Emitting segments for file: ../coverage/match_or_pattern.rs
Combined regions:
3:1 -> 11:15 (count=1)
11:16 -> 14:6 (count=1)
14:6 -> 14:7 (count=0)
15:11 -> 15:17 (count=1)
18:27 -> 18:29 (count=0)
19:14 -> 19:16 (count=1)
21:8 -> 21:15 (count=1)
21:16 -> 24:6 (count=1)
24:6 -> 24:7 (count=0)
25:11 -> 25:17 (count=1)
26:27 -> 26:29 (count=0)
27:14 -> 27:16 (count=1)
29:8 -> 29:15 (count=1)
29:16 -> 32:6 (count=1)
32:6 -> 32:7 (count=0)
33:11 -> 33:17 (count=1)
34:27 -> 34:29 (count=0)
35:14 -> 35:16 (count=1)
37:8 -> 37:15 (count=1)
37:16 -> 40:6 (count=1)
40:6 -> 40:7 (count=0)
41:11 -> 41:17 (count=1)
42:27 -> 42:29 (count=1)
43:14 -> 43:16 (count=0)
45:1 -> 45:2 (count=1)
Segment at 3:1 (count = 1), RegionEntry
Segment at 11:15 (count = 0), Skipped
Segment at 11:16 (count = 1), RegionEntry
Segment at 14:6 (count = 0), RegionEntry
Segment at 14:7 (count = 0), Skipped
Segment at 15:11 (count = 1), RegionEntry
Segment at 15:17 (count = 0), Skipped
Segment at 18:27 (count = 0), RegionEntry
Segment at 18:29 (count = 0), Skipped
Segment at 19:14 (count = 1), RegionEntry
Segment at 19:16 (count = 0), Skipped
Segment at 21:8 (count = 1), RegionEntry
Segment at 21:15 (count = 0), Skipped
Segment at 21:16 (count = 1), RegionEntry
Segment at 24:6 (count = 0), RegionEntry
Segment at 24:7 (count = 0), Skipped
Segment at 25:11 (count = 1), RegionEntry
Segment at 25:17 (count = 0), Skipped
Segment at 26:27 (count = 0), RegionEntry
Segment at 26:29 (count = 0), Skipped
Segment at 27:14 (count = 1), RegionEntry
Segment at 27:16 (count = 0), Skipped
Segment at 29:8 (count = 1), RegionEntry
Segment at 29:15 (count = 0), Skipped
Segment at 29:16 (count = 1), RegionEntry
Segment at 32:6 (count = 0), RegionEntry
Segment at 32:7 (count = 0), Skipped
Segment at 33:11 (count = 1), RegionEntry
Segment at 33:17 (count = 0), Skipped
Segment at 34:27 (count = 0), RegionEntry
Segment at 34:29 (count = 0), Skipped
Segment at 35:14 (count = 1), RegionEntry
Segment at 35:16 (count = 0), Skipped
Segment at 37:8 (count = 1), RegionEntry
Segment at 37:15 (count = 0), Skipped
Segment at 37:16 (count = 1), RegionEntry
Segment at 40:6 (count = 0), RegionEntry
Segment at 40:7 (count = 0), Skipped
Segment at 41:11 (count = 1), RegionEntry
Segment at 41:17 (count = 0), Skipped
Segment at 42:27 (count = 1), RegionEntry
Segment at 42:29 (count = 0), Skipped
Segment at 43:14 (count = 0), RegionEntry
Segment at 43:16 (count = 0), Skipped
Segment at 45:1 (count = 1), RegionEntry
Segment at 45:2 (count = 0), Skipped
Loading

0 comments on commit eb963ff

Please sign in to comment.