diff options
| author | Rich Kadel <richkadel@google.com> | 2020-12-11 18:28:37 -0800 |
|---|---|---|
| committer | Rich Kadel <richkadel@google.com> | 2020-12-11 21:40:22 -0800 |
| commit | eb963ffe451bfbc001ea86712a94619903bfbaf8 (patch) | |
| tree | 6cd2fb6ebdb047cbaef18e7358995ed9410a8db8 | |
| parent | 9eb3a7ceafd1e2c1924177caa18c7cc0c25b413e (diff) | |
| download | rust-eb963ffe451bfbc001ea86712a94619903bfbaf8.tar.gz rust-eb963ffe451bfbc001ea86712a94619903bfbaf8.zip | |
Fixes reported bugs in Rust Coverage
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.
8 files changed, 553 insertions, 18 deletions
diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs index 2408a999c05..b1a1bb957e7 100644 --- a/compiler/rustc_mir/src/transform/coverage/graph.rs +++ b/compiler/rustc_mir/src/transform/coverage/graph.rs @@ -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(), diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index f69748db238..53f7c28ee35 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -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()); diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_export_coverage.match_or_pattern.json b/src/test/run-make-fulldeps/coverage-reports/expected_export_coverage.match_or_pattern.json new file mode 100644 index 00000000000..8559fc84aa9 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_export_coverage.match_or_pattern.json @@ -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" +} diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.match_or_pattern.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.match_or_pattern.txt new file mode 100644 index 00000000000..a0fccb24f99 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.match_or_pattern.txt @@ -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|} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt index ed91e8898ee..4df0bac8c86 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt @@ -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 @@ -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) @@ -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 diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.match_or_pattern.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.match_or_pattern.txt new file mode 100644 index 00000000000..fc12612ce7d --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.match_or_pattern.txt @@ -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 diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html new file mode 100644 index 00000000000..133a85c8394 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html @@ -0,0 +1,271 @@ +<!DOCTYPE html> +<!-- + +Preview this file as rendered HTML from the github source at: +https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html + +For revisions in Pull Requests (PR): + * Replace "rust-lang" with the github PR author + * Replace "master" with the PR branch name + +--> +<html> +<head> +<title>match_or_pattern.main - Coverage Spans</title> +<style> + .line { + counter-increment: line; + } + .line:before { + content: counter(line) ": "; + font-family: Menlo, Monaco, monospace; + font-style: italic; + width: 3.8em; + display: inline-block; + text-align: right; + filter: opacity(50%); + -webkit-user-select: none; + } + .code { + color: #dddddd; + background-color: #222222; + font-family: Menlo, Monaco, monospace; + line-height: 1.4em; + border-bottom: 2px solid #222222; + white-space: pre; + display: inline-block; + } + .odd { + background-color: #55bbff; + color: #223311; + } + .even { + background-color: #ee7756; + color: #551133; + } + .code { + --index: calc(var(--layer) - 1); + padding-top: calc(var(--index) * 0.15em); + filter: + hue-rotate(calc(var(--index) * 25deg)) + saturate(calc(100% - (var(--index) * 2%))) + brightness(calc(100% - (var(--index) * 1.5%))); + } + .annotation { + color: #4444ff; + font-family: monospace; + font-style: italic; + display: none; + -webkit-user-select: none; + } + body:active .annotation { + /* requires holding mouse down anywhere on the page */ + display: inline-block; + } + span:hover .annotation { + /* requires hover over a span ONLY on its first line */ + display: inline-block; + } +</style> +</head> +<body> +<div class="code" style="counter-reset: line 2"><span class="line"><span><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"><span class="annotation">@0,1,2,3⦊</span>fn main() {</span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> // Initialize test constants in a way that cannot be determined at compile time, to ensure</span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from</span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> // dependent conditions.</span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> let is_true = std::env::args().len() == 1;</span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"></span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> let mut a: u8 = 0;</span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> let mut b: u8 = 0;</span></span> +<span class="line"><span class="code even" style="--layer: 1" title="7:19-7:35: @0.Call: _4 = args() -> [return: bb1, unwind: bb41] +7:19-7:35: @1[0]: _3 = &_4 +7:19-7:41: @1.Call: _2 = <Args as ExactSizeIterator>::len(move _3) -> [return: bb2, unwind: bb40] +7:19-7:46: @2[1]: _1 = Eq(move _2, const 1_usize) +7:9-7:16: @2[3]: FakeRead(ForLet, _1) +9:21-9:22: @3[2]: _5 = const 0_u8 +9:9-9:14: @3[3]: FakeRead(ForLet, _5) +9:16-9:18: @3[4]: AscribeUserType(_5, o, UserTypeProjection { base: UserType(1), projs: [] }) +10:21-10:22: @3[6]: _6 = const 0_u8 +10:9-10:14: @3[7]: FakeRead(ForLet, _6) +10:16-10:18: @3[8]: AscribeUserType(_6, o, UserTypeProjection { base: UserType(3), projs: [] }) +11:8-11:15: @3[11]: _8 = _1 +11:8-11:15: @3[12]: FakeRead(ForMatchedPlace, _8)"> if is_true<span class="annotation">⦉@0,1,2,3</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8 +13:9-13:14: @6[1]: _6 = const 0_u8 +11:16-14:6: @6[2]: _7 = const ()"><span class="annotation">@4,6⦊</span>{</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8 +13:9-13:14: @6[1]: _6 = const 0_u8 +11:16-14:6: @6[2]: _7 = const ()"> a = 2;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8 +13:9-13:14: @6[1]: _6 = const 0_u8 +11:16-14:6: @6[2]: _7 = const ()"> b = 0;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="12:9-12:14: @6[0]: _5 = const 2_u8 +13:9-13:14: @6[1]: _6 = const 0_u8 +11:16-14:6: @6[2]: _7 = const ()"> }<span class="annotation">⦉@4,6</span></span></span><span><span class="code even" style="--layer: 1" title="14:6-14:6: @5[0]: _7 = const ()"><span class="annotation">@5⦊</span>‸<span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="15:12-15:13: @7[5]: _11 = _5 +15:15-15:16: @7[7]: _12 = _6 +15:11-15:17: @7[8]: _10 = (move _11, move _12) +15:11-15:17: @7[11]: FakeRead(ForMatchedPlace, _10)"><span class="annotation">@7⦊</span>(a, b)<span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0"> {</span></span> +<span class="line"><span class="code" style="--layer: 0"> // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.</span></span> +<span class="line"><span class="code" style="--layer: 0"> // This test confirms a fix for Issue #79569.</span></span> +<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) => </span><span><span class="code even" style="--layer: 1" title="18:27-18:29: @11[0]: _9 = const ()"><span class="annotation">@10,11⦊</span>{}<span class="annotation">⦉@10,11</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> _ => </span><span><span class="code odd" style="--layer: 1" title="19:14-19:16: @8[0]: _9 = const ()"><span class="annotation">@8⦊</span>{}<span class="annotation">⦉@8</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> }</span></span> +<span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="21:8-21:15: @12[4]: _14 = _1 +21:8-21:15: @12[5]: FakeRead(ForMatchedPlace, _14)"><span class="annotation">@12⦊</span>is_true<span class="annotation">⦉@12</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8 +23:9-23:14: @15[1]: _6 = const 0_u8 +21:16-24:6: @15[2]: _13 = const ()"><span class="annotation">@13,15⦊</span>{</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8 +23:9-23:14: @15[1]: _6 = const 0_u8 +21:16-24:6: @15[2]: _13 = const ()"> a = 0;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8 +23:9-23:14: @15[1]: _6 = const 0_u8 +21:16-24:6: @15[2]: _13 = const ()"> b = 0;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="22:9-22:14: @15[0]: _5 = const 0_u8 +23:9-23:14: @15[1]: _6 = const 0_u8 +21:16-24:6: @15[2]: _13 = const ()"> }<span class="annotation">⦉@13,15</span></span></span><span><span class="code even" style="--layer: 1" title="24:6-24:6: @14[0]: _13 = const ()"><span class="annotation">@14⦊</span>‸<span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="25:12-25:13: @16[5]: _17 = _5 +25:15-25:16: @16[7]: _18 = _6 +25:11-25:17: @16[8]: _16 = (move _17, move _18) +25:11-25:17: @16[11]: FakeRead(ForMatchedPlace, _16)"><span class="annotation">@16⦊</span>(a, b)<span class="annotation">⦉@16</span></span></span><span class="code" style="--layer: 0"> {</span></span> +<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) => </span><span><span class="code even" style="--layer: 1" title="26:27-26:29: @20[0]: _15 = const ()"><span class="annotation">@19,20⦊</span>{}<span class="annotation">⦉@19,20</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> _ => </span><span><span class="code odd" style="--layer: 1" title="27:14-27:16: @17[0]: _15 = const ()"><span class="annotation">@17⦊</span>{}<span class="annotation">⦉@17</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> }</span></span> +<span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="29:8-29:15: @21[4]: _20 = _1 +29:8-29:15: @21[5]: FakeRead(ForMatchedPlace, _20)"><span class="annotation">@21⦊</span>is_true<span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8 +31:9-31:14: @24[1]: _6 = const 2_u8 +29:16-32:6: @24[2]: _19 = const ()"><span class="annotation">@22,24⦊</span>{</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8 +31:9-31:14: @24[1]: _6 = const 2_u8 +29:16-32:6: @24[2]: _19 = const ()"> a = 2;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8 +31:9-31:14: @24[1]: _6 = const 2_u8 +29:16-32:6: @24[2]: _19 = const ()"> b = 2;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="30:9-30:14: @24[0]: _5 = const 2_u8 +31:9-31:14: @24[1]: _6 = const 2_u8 +29:16-32:6: @24[2]: _19 = const ()"> }<span class="annotation">⦉@22,24</span></span></span><span><span class="code even" style="--layer: 1" title="32:6-32:6: @23[0]: _19 = const ()"><span class="annotation">@23⦊</span>‸<span class="annotation">⦉@23</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="33:12-33:13: @25[5]: _23 = _5 +33:15-33:16: @25[7]: _24 = _6 +33:11-33:17: @25[8]: _22 = (move _23, move _24) +33:11-33:17: @25[11]: FakeRead(ForMatchedPlace, _22)"><span class="annotation">@25⦊</span>(a, b)<span class="annotation">⦉@25</span></span></span><span class="code" style="--layer: 0"> {</span></span> +<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) => </span><span><span class="code even" style="--layer: 1" title="34:27-34:29: @29[0]: _21 = const ()"><span class="annotation">@28,29⦊</span>{}<span class="annotation">⦉@28,29</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> _ => </span><span><span class="code odd" style="--layer: 1" title="35:14-35:16: @26[0]: _21 = const ()"><span class="annotation">@26⦊</span>{}<span class="annotation">⦉@26</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> }</span></span> +<span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="37:8-37:15: @30[4]: _26 = _1 +37:8-37:15: @30[5]: FakeRead(ForMatchedPlace, _26)"><span class="annotation">@30⦊</span>is_true<span class="annotation">⦉@30</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8 +39:9-39:14: @33[1]: _6 = const 2_u8 +37:16-40:6: @33[2]: _25 = const ()"><span class="annotation">@31,33⦊</span>{</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8 +39:9-39:14: @33[1]: _6 = const 2_u8 +37:16-40:6: @33[2]: _25 = const ()"> a = 0;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8 +39:9-39:14: @33[1]: _6 = const 2_u8 +37:16-40:6: @33[2]: _25 = const ()"> b = 2;</span></span> +<span class="line"><span class="code odd" style="--layer: 1" title="38:9-38:14: @33[0]: _5 = const 0_u8 +39:9-39:14: @33[1]: _6 = const 2_u8 +37:16-40:6: @33[2]: _25 = const ()"> }<span class="annotation">⦉@31,33</span></span></span><span><span class="code even" style="--layer: 1" title="40:6-40:6: @32[0]: _25 = const ()"><span class="annotation">@32⦊</span>‸<span class="annotation">⦉@32</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> match </span><span><span class="code odd" style="--layer: 1" title="41:12-41:13: @34[4]: _28 = _5 +41:15-41:16: @34[6]: _29 = _6 +41:11-41:17: @34[7]: _27 = (move _28, move _29) +41:11-41:17: @34[10]: FakeRead(ForMatchedPlace, _27)"><span class="annotation">@34⦊</span>(a, b)<span class="annotation">⦉@34</span></span></span><span class="code" style="--layer: 0"> {</span></span> +<span class="line"><span class="code" style="--layer: 0"> (0 | 1, 2 | 3) => </span><span><span class="code even" style="--layer: 1" title="42:27-42:29: @38[0]: _0 = const ()"><span class="annotation">@37,38⦊</span>{}<span class="annotation">⦉@37,38</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> _ => </span><span><span class="code odd" style="--layer: 1" title="43:14-43:16: @35[0]: _0 = const ()"><span class="annotation">@35⦊</span>{}<span class="annotation">⦉@35</span></span></span><span class="code" style="--layer: 0"></span></span> +<span class="line"><span class="code" style="--layer: 0"> }</span></span> +<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code even" style="--layer: 1" title="45:2-45:2: @39.Return: return"><span class="annotation">@39⦊</span>‸<span class="annotation">⦉@39</span></span></span></span></div> +</body> +</html> diff --git a/src/test/run-make-fulldeps/coverage/match_or_pattern.rs b/src/test/run-make-fulldeps/coverage/match_or_pattern.rs new file mode 100644 index 00000000000..4c6a8a9b703 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/match_or_pattern.rs @@ -0,0 +1,45 @@ +#![feature(or_patterns)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut a: u8 = 0; + let mut b: u8 = 0; + if is_true { + a = 2; + b = 0; + } + match (a, b) { + // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. + // This test confirms a fix for Issue #79569. + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 0; + b = 0; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 2; + b = 2; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 0; + b = 2; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } +} |
