4690f97099
This code was calling `sort_unstable_by`, but failed to impose a total order on the initial spans. That resulted in unpredictable handling of closure spans, producing inconsistencies in the coverage maps and in user-visible coverage reports. This patch fixes the problem by always sorting closure spans before otherwise-identical non-closure spans, and also switches to a stable sort in case the ordering is still not total.
228 lines
8.4 KiB
Plaintext
228 lines
8.4 KiB
Plaintext
LL| |#![allow(unused_assignments, unused_variables)]
|
|
LL| |// compile-flags: -C opt-level=2
|
|
LL| |
|
|
LL| |// This test used to be sensitive to certain coverage-specific hacks in
|
|
LL| |// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by
|
|
LL| |// <https://github.com/rust-lang/rust/pull/83666>.
|
|
LL| |
|
|
LL| 1|fn main() {
|
|
LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
|
|
LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
|
|
LL| 1| // dependent conditions.
|
|
LL| 1| let is_true = std::env::args().len() == 1;
|
|
LL| 1| let is_false = !is_true;
|
|
LL| 1|
|
|
LL| 1| let mut some_string = Some(String::from("the string content"));
|
|
LL| 1| println!(
|
|
LL| 1| "The string or alt: {}"
|
|
LL| 1| ,
|
|
LL| 1| some_string
|
|
LL| 1| .
|
|
LL| 1| unwrap_or_else
|
|
LL| 1| (
|
|
LL| 1| ||
|
|
LL| 0| {
|
|
LL| 0| let mut countdown = 0;
|
|
LL| 0| if is_false {
|
|
LL| 0| countdown = 10;
|
|
LL| 0| }
|
|
LL| 0| "alt string 1".to_owned()
|
|
LL| 1| }
|
|
LL| 1| )
|
|
LL| 1| );
|
|
LL| 1|
|
|
LL| 1| some_string = Some(String::from("the string content"));
|
|
LL| 1| let
|
|
LL| 1| a
|
|
LL| | =
|
|
LL| | ||
|
|
LL| 0| {
|
|
LL| 0| let mut countdown = 0;
|
|
LL| 0| if is_false {
|
|
LL| 0| countdown = 10;
|
|
LL| 0| }
|
|
LL| 0| "alt string 2".to_owned()
|
|
LL| 0| };
|
|
LL| 1| println!(
|
|
LL| 1| "The string or alt: {}"
|
|
LL| 1| ,
|
|
LL| 1| some_string
|
|
LL| 1| .
|
|
LL| 1| unwrap_or_else
|
|
LL| 1| (
|
|
LL| 1| a
|
|
LL| 1| )
|
|
LL| 1| );
|
|
LL| 1|
|
|
LL| 1| some_string = None;
|
|
LL| 1| println!(
|
|
LL| 1| "The string or alt: {}"
|
|
LL| 1| ,
|
|
LL| 1| some_string
|
|
LL| 1| .
|
|
LL| 1| unwrap_or_else
|
|
LL| 1| (
|
|
LL| 1| ||
|
|
LL| 1| {
|
|
LL| 1| let mut countdown = 0;
|
|
LL| 1| if is_false {
|
|
LL| 0| countdown = 10;
|
|
LL| 1| }
|
|
LL| 1| "alt string 3".to_owned()
|
|
LL| 1| }
|
|
LL| 1| )
|
|
LL| 1| );
|
|
LL| 1|
|
|
LL| 1| some_string = None;
|
|
LL| 1| let
|
|
LL| 1| a
|
|
LL| | =
|
|
LL| | ||
|
|
LL| 1| {
|
|
LL| 1| let mut countdown = 0;
|
|
LL| 1| if is_false {
|
|
LL| 0| countdown = 10;
|
|
LL| 1| }
|
|
LL| 1| "alt string 4".to_owned()
|
|
LL| 1| };
|
|
LL| 1| println!(
|
|
LL| 1| "The string or alt: {}"
|
|
LL| 1| ,
|
|
LL| 1| some_string
|
|
LL| 1| .
|
|
LL| 1| unwrap_or_else
|
|
LL| 1| (
|
|
LL| 1| a
|
|
LL| 1| )
|
|
LL| 1| );
|
|
LL| 1|
|
|
LL| 1| let
|
|
LL| 1| quote_closure
|
|
LL| | =
|
|
LL| | |val|
|
|
LL| 5| {
|
|
LL| 5| let mut countdown = 0;
|
|
LL| 5| if is_false {
|
|
LL| 0| countdown = 10;
|
|
LL| 5| }
|
|
LL| 5| format!("'{}'", val)
|
|
LL| 5| };
|
|
LL| 1| println!(
|
|
LL| 1| "Repeated, quoted string: {:?}"
|
|
LL| 1| ,
|
|
LL| 1| std::iter::repeat("repeat me")
|
|
LL| 1| .take(5)
|
|
LL| 1| .map
|
|
LL| 1| (
|
|
LL| 1| quote_closure
|
|
LL| 1| )
|
|
LL| 1| .collect::<Vec<_>>()
|
|
LL| 1| );
|
|
LL| 1|
|
|
LL| 1| let
|
|
LL| 1| _unused_closure
|
|
LL| | =
|
|
LL| | |
|
|
LL| | mut countdown
|
|
LL| | |
|
|
LL| 0| {
|
|
LL| 0| if is_false {
|
|
LL| 0| countdown = 10;
|
|
LL| 0| }
|
|
LL| 0| "closure should be unused".to_owned()
|
|
LL| 0| };
|
|
LL| |
|
|
LL| 1| let mut countdown = 10;
|
|
LL| 1| let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
|
|
^0
|
|
LL| |
|
|
LL| |
|
|
LL| 1| let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
|
|
LL| 1| let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
|
|
^0
|
|
LL| 1| let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
|
|
^0
|
|
LL| |
|
|
LL| |
|
|
LL| |
|
|
LL| |
|
|
LL| 1| let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
|
|
^0
|
|
LL| |
|
|
LL| 1| let _shortish_unused_closure = | _unused_arg: u8 | {
|
|
LL| 0| println!("not called")
|
|
LL| 0| };
|
|
LL| |
|
|
LL| 1| let _as_short_unused_closure = |
|
|
LL| | _unused_arg: u8
|
|
LL| 0| | { println!("not called") };
|
|
LL| |
|
|
LL| 1| let _almost_as_short_unused_closure = |
|
|
LL| | _unused_arg: u8
|
|
LL| 0| | { println!("not called") }
|
|
LL| | ;
|
|
LL| |
|
|
LL| |
|
|
LL| |
|
|
LL| |
|
|
LL| |
|
|
LL| 1| let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
|
|
LL| 0|println!("not called")
|
|
LL| | ;
|
|
LL| |
|
|
LL| 1| let _short_unused_closure_line_break_no_block2 =
|
|
LL| | | _unused_arg: u8 |
|
|
LL| 0| println!(
|
|
LL| 0| "not called"
|
|
LL| 0| )
|
|
LL| | ;
|
|
LL| |
|
|
LL| 1| let short_used_not_covered_closure_line_break_no_block_embedded_branch =
|
|
LL| | | _unused_arg: u8 |
|
|
LL| 0| println!(
|
|
LL| 0| "not called: {}",
|
|
LL| 0| if is_true { "check" } else { "me" }
|
|
LL| 0| )
|
|
LL| | ;
|
|
LL| |
|
|
LL| 1| let short_used_not_covered_closure_line_break_block_embedded_branch =
|
|
LL| | | _unused_arg: u8 |
|
|
LL| 0| {
|
|
LL| 0| println!(
|
|
LL| 0| "not called: {}",
|
|
LL| 0| if is_true { "check" } else { "me" }
|
|
LL| | )
|
|
LL| 0| }
|
|
LL| | ;
|
|
LL| |
|
|
LL| 1| let short_used_covered_closure_line_break_no_block_embedded_branch =
|
|
LL| | | _unused_arg: u8 |
|
|
LL| 1| println!(
|
|
LL| 1| "not called: {}",
|
|
LL| 1| if is_true { "check" } else { "me" }
|
|
^0
|
|
LL| 1| )
|
|
LL| | ;
|
|
LL| |
|
|
LL| 1| let short_used_covered_closure_line_break_block_embedded_branch =
|
|
LL| | | _unused_arg: u8 |
|
|
LL| 1| {
|
|
LL| 1| println!(
|
|
LL| 1| "not called: {}",
|
|
LL| 1| if is_true { "check" } else { "me" }
|
|
^0
|
|
LL| | )
|
|
LL| 1| }
|
|
LL| | ;
|
|
LL| |
|
|
LL| 1| if is_false {
|
|
LL| 0| short_used_not_covered_closure_macro(0);
|
|
LL| 0| short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
|
|
LL| 0| short_used_not_covered_closure_line_break_block_embedded_branch(0);
|
|
LL| 1| }
|
|
LL| 1| short_used_covered_closure_macro(0);
|
|
LL| 1| short_used_covered_closure_line_break_no_block_embedded_branch(0);
|
|
LL| 1| short_used_covered_closure_line_break_block_embedded_branch(0);
|
|
LL| 1|}
|
|
|