Auto merge of #84797 - richkadel:cover-unreachable-statements, r=tmandry
Report coverage `0` of dead blocks Fixes: #84018 With `-Z instrument-coverage`, coverage reporting of dead blocks (for example, blocks dropped because a conditional branch is dropped, based on const evaluation) is now supported. If `instrument-coverage` is enabled, `simplify::remove_dead_blocks()` finds all dropped coverage `Statement`s and adds their `code_region`s as `Unreachable` coverage `Statement`s to the `START_BLOCK`, so they are still included in the coverage map. Check out the resulting changes in the test coverage reports in this PR (in [commit 1](https://github.com/rust-lang/rust/pull/84797/commits/0b0d293c7c46bdadf80e5304a667e34c53c0cf7e)). r? `@tmandry` cc: `@wesleywiser`
This commit is contained in:
commit
e5f83d24ae
21 changed files with 102 additions and 65 deletions
|
|
@ -12,6 +12,7 @@
|
|||
12| 1| if b {
|
||||
13| 1| println!("non_async_func println in block");
|
||||
14| 1| }
|
||||
^0
|
||||
15| 1|}
|
||||
16| |
|
||||
17| |
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
5| 1| if true {
|
||||
6| 1| countdown = 10;
|
||||
7| 1| }
|
||||
^0
|
||||
8| |
|
||||
9| | const B: u32 = 100;
|
||||
10| 1| let x = if countdown > 7 {
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
24| 1| if true {
|
||||
25| 1| countdown = 10;
|
||||
26| 1| }
|
||||
^0
|
||||
27| |
|
||||
28| 1| if countdown > 7 {
|
||||
29| 1| countdown -= 4;
|
||||
|
|
@ -42,6 +44,7 @@
|
|||
41| 1| if true {
|
||||
42| 1| countdown = 10;
|
||||
43| 1| }
|
||||
^0
|
||||
44| |
|
||||
45| 1| if countdown > 7 {
|
||||
46| 1| countdown -= 4;
|
||||
|
|
@ -54,13 +57,14 @@
|
|||
53| | } else {
|
||||
54| 0| return;
|
||||
55| | }
|
||||
56| | } // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal
|
||||
57| | // `true` was const-evaluated. The compiler knows the `if` block will be executed.
|
||||
56| 0| }
|
||||
57| |
|
||||
58| |
|
||||
59| 1| let mut countdown = 0;
|
||||
60| 1| if true {
|
||||
61| 1| countdown = 1;
|
||||
62| 1| }
|
||||
^0
|
||||
63| |
|
||||
64| 1| let z = if countdown > 7 {
|
||||
^0
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
8| 1|//! assert_eq!(1, 1);
|
||||
9| |//! } else {
|
||||
10| |//! // this is not!
|
||||
11| |//! assert_eq!(1, 2);
|
||||
11| 0|//! assert_eq!(1, 2);
|
||||
12| |//! }
|
||||
13| 1|//! ```
|
||||
14| |//!
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
74| 1| if true {
|
||||
75| 1| assert_eq!(1, 1);
|
||||
76| | } else {
|
||||
77| | assert_eq!(1, 2);
|
||||
77| 0| assert_eq!(1, 2);
|
||||
78| | }
|
||||
79| 1|}
|
||||
80| |
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@
|
|||
19| 1| if true {
|
||||
20| 1| println!("Exiting with error...");
|
||||
21| 1| return Err(1);
|
||||
22| | }
|
||||
23| |
|
||||
24| | let _ = Firework { strength: 1000 };
|
||||
25| |
|
||||
26| | Ok(())
|
||||
22| 0| }
|
||||
23| 0|
|
||||
24| 0| let _ = Firework { strength: 1000 };
|
||||
25| 0|
|
||||
26| 0| Ok(())
|
||||
27| 1|}
|
||||
28| |
|
||||
29| |// Expected program output:
|
||||
|
|
|
|||
|
|
@ -52,15 +52,15 @@
|
|||
30| 1| if true {
|
||||
31| 1| println!("Exiting with error...");
|
||||
32| 1| return Err(1);
|
||||
33| | } // The remaining lines below have no coverage because `if true` (with the constant literal
|
||||
34| | // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.
|
||||
35| | // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown
|
||||
36| | // in other tests, the lines below would have coverage (which would show they had `0`
|
||||
37| | // executions, assuming the condition still evaluated to `true`).
|
||||
38| |
|
||||
39| | let _ = Firework { strength: 1000 };
|
||||
40| |
|
||||
41| | Ok(())
|
||||
33| 0| }
|
||||
34| 0|
|
||||
35| 0|
|
||||
36| 0|
|
||||
37| 0|
|
||||
38| 0|
|
||||
39| 0| let _ = Firework { strength: 1000 };
|
||||
40| 0|
|
||||
41| 0| Ok(())
|
||||
42| 1|}
|
||||
43| |
|
||||
44| |// Expected program output:
|
||||
|
|
|
|||
|
|
@ -9,23 +9,23 @@
|
|||
9| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
10| 1| if true {
|
||||
11| 1| if false {
|
||||
12| | while true {
|
||||
13| | }
|
||||
12| 0| while true {
|
||||
13| 0| }
|
||||
14| 1| }
|
||||
15| 1| write!(f, "error")?;
|
||||
^0
|
||||
16| | } else {
|
||||
17| | }
|
||||
15| 1| write!(f, "cool")?;
|
||||
^0
|
||||
16| 0| } else {
|
||||
17| 0| }
|
||||
18| |
|
||||
19| 10| for i in 0..10 {
|
||||
20| 10| if true {
|
||||
21| 10| if false {
|
||||
22| | while true {}
|
||||
22| 0| while true {}
|
||||
23| 10| }
|
||||
24| 10| write!(f, "error")?;
|
||||
^0
|
||||
25| | } else {
|
||||
26| | }
|
||||
24| 10| write!(f, "cool")?;
|
||||
^0
|
||||
25| 0| } else {
|
||||
26| 0| }
|
||||
27| | }
|
||||
28| 1| Ok(())
|
||||
29| 1| }
|
||||
|
|
@ -36,21 +36,21 @@
|
|||
34| |impl std::fmt::Display for DisplayTest {
|
||||
35| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
36| 1| if false {
|
||||
37| | } else {
|
||||
37| 0| } else {
|
||||
38| 1| if false {
|
||||
39| | while true {}
|
||||
39| 0| while true {}
|
||||
40| 1| }
|
||||
41| 1| write!(f, "error")?;
|
||||
^0
|
||||
41| 1| write!(f, "cool")?;
|
||||
^0
|
||||
42| | }
|
||||
43| 10| for i in 0..10 {
|
||||
44| 10| if false {
|
||||
45| | } else {
|
||||
45| 0| } else {
|
||||
46| 10| if false {
|
||||
47| | while true {}
|
||||
47| 0| while true {}
|
||||
48| 10| }
|
||||
49| 10| write!(f, "error")?;
|
||||
^0
|
||||
49| 10| write!(f, "cool")?;
|
||||
^0
|
||||
50| | }
|
||||
51| | }
|
||||
52| 1| Ok(())
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
1| 1|fn main() {
|
||||
2| 1| if false {
|
||||
3| | loop {}
|
||||
3| 0| loop {}
|
||||
4| 1| }
|
||||
5| 1|}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ fn main() {
|
|||
} else {
|
||||
return;
|
||||
}
|
||||
} // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal
|
||||
// `true` was const-evaluated. The compiler knows the `if` block will be executed.
|
||||
}
|
||||
|
||||
|
||||
let mut countdown = 0;
|
||||
if true {
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ fn main() -> Result<(),u8> {
|
|||
if true {
|
||||
println!("Exiting with error...");
|
||||
return Err(1);
|
||||
} // The remaining lines below have no coverage because `if true` (with the constant literal
|
||||
// `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.
|
||||
// Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown
|
||||
// in other tests, the lines below would have coverage (which would show they had `0`
|
||||
// executions, assuming the condition still evaluated to `true`).
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
let _ = Firework { strength: 1000 };
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl std::fmt::Debug for DebugTest {
|
|||
while true {
|
||||
}
|
||||
}
|
||||
write!(f, "error")?;
|
||||
write!(f, "cool")?;
|
||||
} else {
|
||||
}
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ impl std::fmt::Debug for DebugTest {
|
|||
if false {
|
||||
while true {}
|
||||
}
|
||||
write!(f, "error")?;
|
||||
write!(f, "cool")?;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ impl std::fmt::Display for DisplayTest {
|
|||
if false {
|
||||
while true {}
|
||||
}
|
||||
write!(f, "error")?;
|
||||
write!(f, "cool")?;
|
||||
}
|
||||
for i in 0..10 {
|
||||
if false {
|
||||
|
|
@ -46,7 +46,7 @@ impl std::fmt::Display for DisplayTest {
|
|||
if false {
|
||||
while true {}
|
||||
}
|
||||
write!(f, "error")?;
|
||||
write!(f, "cool")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue