coverage: Migrate tests/coverage-map
into tests/coverage
This commit is contained in:
parent
e9d04c5e24
commit
49127c64d6
106 changed files with 5 additions and 2764 deletions
|
@ -1433,24 +1433,16 @@ impl Step for Coverage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, builder: &Builder<'_>) {
|
fn run(self, builder: &Builder<'_>) {
|
||||||
builder.ensure(Compiletest {
|
self.run_unified_suite(builder, CoverageMap::MODE);
|
||||||
compiler: self.compiler,
|
|
||||||
target: self.target,
|
|
||||||
mode: "coverage-map",
|
|
||||||
suite: "coverage-map",
|
|
||||||
path: "tests/coverage-map",
|
|
||||||
compare_mode: None,
|
|
||||||
});
|
|
||||||
self.run_unified_suite(builder, RunCoverage::MODE);
|
self.run_unified_suite(builder, RunCoverage::MODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default_test!(CoverageMap {
|
coverage_test_alias!(CoverageMap {
|
||||||
path: "tests/coverage-map",
|
alias_and_mode: "coverage-map",
|
||||||
mode: "coverage-map",
|
default: true,
|
||||||
suite: "coverage-map"
|
only_hosts: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
coverage_test_alias!(RunCoverage {
|
coverage_test_alias!(RunCoverage {
|
||||||
alias_and_mode: "run-coverage",
|
alias_and_mode: "run-coverage",
|
||||||
default: true,
|
default: true,
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
#![feature(c_unwind)]
|
|
||||||
#![allow(unused_assignments)]
|
|
||||||
|
|
||||||
extern "C" fn might_abort(should_abort: bool) {
|
|
||||||
if should_abort {
|
|
||||||
println!("aborting...");
|
|
||||||
panic!("panics and aborts");
|
|
||||||
} else {
|
|
||||||
println!("Don't Panic");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
let mut countdown = 10;
|
|
||||||
while countdown > 0 {
|
|
||||||
if countdown < 5 {
|
|
||||||
might_abort(false);
|
|
||||||
}
|
|
||||||
// See discussion (below the `Notes` section) on coverage results for the closing brace.
|
|
||||||
if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
|
|
||||||
// For the following example, the closing brace is the last character on the line.
|
|
||||||
// This shows the character after the closing brace is highlighted, even if that next
|
|
||||||
// character is a newline.
|
|
||||||
if countdown < 5 { might_abort(false); }
|
|
||||||
countdown -= 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notes:
|
|
||||||
// 1. Compare this program and its coverage results to those of the similar tests
|
|
||||||
// `panic_unwind.rs` and `try_error_result.rs`.
|
|
||||||
// 2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
|
|
||||||
// 3. The test does not invoke the abort. By executing to a successful completion, the coverage
|
|
||||||
// results show where the program did and did not execute.
|
|
||||||
// 4. If the program actually aborted, the coverage counters would not be saved (which "works as
|
|
||||||
// intended"). Coverage results would show no executed coverage regions.
|
|
||||||
// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
|
|
||||||
// (on Linux at least).
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Expect the following coverage results:
|
|
||||||
|
|
||||||
```text
|
|
||||||
16| 11| while countdown > 0 {
|
|
||||||
17| 10| if countdown < 5 {
|
|
||||||
18| 4| might_abort(false);
|
|
||||||
19| 6| }
|
|
||||||
```
|
|
||||||
|
|
||||||
This is actually correct.
|
|
||||||
|
|
||||||
The condition `countdown < 5` executed 10 times (10 loop iterations).
|
|
||||||
|
|
||||||
It evaluated to `true` 4 times, and executed the `might_abort()` call.
|
|
||||||
|
|
||||||
It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
|
|
||||||
`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
|
|
||||||
closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
|
|
||||||
non-true condition.
|
|
||||||
|
|
||||||
As another example of why this is important, say the condition was `countdown < 50`, which is always
|
|
||||||
`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
|
|
||||||
The closing brace would have a count of `0`, highlighting the missed coverage.
|
|
||||||
*/
|
|
|
@ -1,32 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
// failure-status: 101
|
|
||||||
|
|
||||||
fn might_fail_assert(one_plus_one: u32) {
|
|
||||||
println!("does 1 + 1 = {}?", one_plus_one);
|
|
||||||
assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
let mut countdown = 10;
|
|
||||||
while countdown > 0 {
|
|
||||||
if countdown == 1 {
|
|
||||||
might_fail_assert(3);
|
|
||||||
} else if countdown < 5 {
|
|
||||||
might_fail_assert(2);
|
|
||||||
}
|
|
||||||
countdown -= 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notes:
|
|
||||||
// 1. Compare this program and its coverage results to those of the very similar test
|
|
||||||
// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
|
|
||||||
// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
|
|
||||||
// related `assert_*!()` macro.
|
|
||||||
// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
|
|
||||||
// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
|
|
||||||
// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
|
|
||||||
// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
|
|
||||||
// (and in many other coverage tests). The `Assert` terminator is typically generated by the
|
|
||||||
// Rust compiler to check for runtime failures, such as numeric overflows.
|
|
|
@ -1,128 +0,0 @@
|
||||||
#![allow(unused_assignments, dead_code)]
|
|
||||||
|
|
||||||
// compile-flags: --edition=2018 -C opt-level=1
|
|
||||||
|
|
||||||
async fn c(x: u8) -> u8 {
|
|
||||||
if x == 8 {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn d() -> u8 { 1 }
|
|
||||||
|
|
||||||
async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
|
|
||||||
|
|
||||||
async fn f() -> u8 { 1 }
|
|
||||||
|
|
||||||
async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
|
|
||||||
|
|
||||||
pub async fn g(x: u8) {
|
|
||||||
match x {
|
|
||||||
y if e().await == y => (),
|
|
||||||
y if f().await == y => (),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn h(x: usize) { // The function signature is counted when called, but the body is not
|
|
||||||
// executed (not awaited) so the open brace has a `0` count (at least when
|
|
||||||
// displayed with `llvm-cov show` in color-mode).
|
|
||||||
match x {
|
|
||||||
y if foo().await[y] => (),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
|
|
||||||
// (a) the function signature, counted when the function is called; and
|
|
||||||
// (b) the open brace for the function body, counted once when the body is
|
|
||||||
// executed asynchronously.
|
|
||||||
match x {
|
|
||||||
y if c(x).await == y + 1 => { d().await; }
|
|
||||||
y if f().await == y + 1 => (),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn j(x: u8) {
|
|
||||||
// non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
|
|
||||||
fn c(x: u8) -> u8 {
|
|
||||||
if x == 8 {
|
|
||||||
1 // This line appears covered, but the 1-character expression span covering the `1`
|
|
||||||
// is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
|
|
||||||
// `fn j()` executes the open brace for the function body, followed by the function's
|
|
||||||
// first executable statement, `match x`. Inner function declarations are not
|
|
||||||
// "visible" to the MIR for `j()`, so the code region counts all lines between the
|
|
||||||
// open brace and the first statement as executed, which is, in a sense, true.
|
|
||||||
// `llvm-cov show` overcomes this kind of situation by showing the actual counts
|
|
||||||
// of the enclosed coverages, (that is, the `1` expression was not executed, and
|
|
||||||
// accurately displays a `0`).
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
|
|
||||||
fn f() -> u8 { 1 }
|
|
||||||
match x {
|
|
||||||
y if c(x) == y + 1 => { d(); }
|
|
||||||
y if f() == y + 1 => (),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn k(x: u8) { // unused function
|
|
||||||
match x {
|
|
||||||
1 => (),
|
|
||||||
2 => (),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn l(x: u8) {
|
|
||||||
match x {
|
|
||||||
1 => (),
|
|
||||||
2 => (),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn m(x: u8) -> u8 { x - 1 }
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let _ = g(10);
|
|
||||||
let _ = h(9);
|
|
||||||
let mut future = Box::pin(i(8));
|
|
||||||
j(7);
|
|
||||||
l(6);
|
|
||||||
let _ = m(5);
|
|
||||||
executor::block_on(future.as_mut());
|
|
||||||
}
|
|
||||||
|
|
||||||
mod executor {
|
|
||||||
use core::{
|
|
||||||
future::Future,
|
|
||||||
pin::Pin,
|
|
||||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn block_on<F: Future>(mut future: F) -> F::Output {
|
|
||||||
let mut future = unsafe { Pin::new_unchecked(&mut future) };
|
|
||||||
use std::hint::unreachable_unchecked;
|
|
||||||
static VTABLE: RawWakerVTable = RawWakerVTable::new(
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // clone
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // wake
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // wake_by_ref
|
|
||||||
|_| (),
|
|
||||||
);
|
|
||||||
let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
|
|
||||||
let mut context = Context::from_waker(&waker);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
|
|
||||||
break val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
// compile-flags: --edition=2018
|
|
||||||
|
|
||||||
fn non_async_func() {
|
|
||||||
println!("non_async_func was covered");
|
|
||||||
let b = true;
|
|
||||||
if b {
|
|
||||||
println!("non_async_func println in block");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn async_func() {
|
|
||||||
println!("async_func was covered");
|
|
||||||
let b = true;
|
|
||||||
if b {
|
|
||||||
println!("async_func println in block");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn async_func_just_println() {
|
|
||||||
println!("async_func_just_println was covered");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("codecovsample::main");
|
|
||||||
|
|
||||||
non_async_func();
|
|
||||||
|
|
||||||
executor::block_on(async_func());
|
|
||||||
executor::block_on(async_func_just_println());
|
|
||||||
}
|
|
||||||
|
|
||||||
mod executor {
|
|
||||||
use core::{
|
|
||||||
future::Future,
|
|
||||||
pin::Pin,
|
|
||||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn block_on<F: Future>(mut future: F) -> F::Output {
|
|
||||||
let mut future = unsafe { Pin::new_unchecked(&mut future) };
|
|
||||||
use std::hint::unreachable_unchecked;
|
|
||||||
static VTABLE: RawWakerVTable = RawWakerVTable::new(
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // clone
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // wake
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // wake_by_ref
|
|
||||||
|_| (),
|
|
||||||
);
|
|
||||||
let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
|
|
||||||
let mut context = Context::from_waker(&waker);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
|
|
||||||
break val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
|
|
||||||
|
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
mod foo {
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn called() {}
|
|
||||||
|
|
||||||
fn uncalled() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod bar {
|
|
||||||
pub fn call_me() {
|
|
||||||
super::foo::called();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod baz {
|
|
||||||
pub fn call_me() {
|
|
||||||
super::foo::called();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn never_called_function() {
|
|
||||||
println!("I am never called");
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
// Verify that coverage works with optimizations:
|
|
||||||
// compile-flags: -C opt-level=3
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
pub fn used_function() {
|
|
||||||
// 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 countdown = 0;
|
|
||||||
if is_true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
use_this_lib_crate();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_only_from_bin_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
// Expect for above function: `Unexecuted instantiation` (see below)
|
|
||||||
pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unused_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("unused_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unused_function() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
let mut countdown = 2;
|
|
||||||
if !is_true {
|
|
||||||
countdown = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn unused_private_function() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
let mut countdown = 2;
|
|
||||||
if !is_true {
|
|
||||||
countdown = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_this_lib_crate() {
|
|
||||||
used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
|
|
||||||
used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
|
|
||||||
"used from library used_crate.rs",
|
|
||||||
);
|
|
||||||
let some_vec = vec![5, 6, 7, 8];
|
|
||||||
used_only_from_this_lib_crate_generic_function(some_vec);
|
|
||||||
used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
|
|
||||||
// for example:
|
|
||||||
//
|
|
||||||
// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
|
|
||||||
//
|
|
||||||
// These notices appear when `llvm-cov` shows instantiations. This may be a
|
|
||||||
// default option, but it can be suppressed with:
|
|
||||||
//
|
|
||||||
// ```shell
|
|
||||||
// $ `llvm-cov show --show-instantiations=0 ...`
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
// The notice is triggered because the function is unused by the library itself,
|
|
||||||
// and when the library is compiled, a synthetic function is generated, so
|
|
||||||
// unused function coverage can be reported. Coverage can be skipped for unused
|
|
||||||
// generic functions with:
|
|
||||||
//
|
|
||||||
// ```shell
|
|
||||||
// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
// Even though this function is used by `uses_crate.rs` (and
|
|
||||||
// counted), with substitutions for `T`, those instantiations are only generated
|
|
||||||
// when the generic function is actually used (from the binary, not from this
|
|
||||||
// library crate). So the test result shows coverage for all instantiated
|
|
||||||
// versions and their generic type substitutions, plus the `Unexecuted
|
|
||||||
// instantiation` message for the non-substituted version. This is valid, but
|
|
||||||
// unfortunately a little confusing.
|
|
||||||
//
|
|
||||||
// The library crate has its own coverage map, and the only way to show unused
|
|
||||||
// coverage of a generic function is to include the generic function in the
|
|
||||||
// coverage map, marked as an "unused function". If the library were used by
|
|
||||||
// another binary that never used this generic function, then it would be valid
|
|
||||||
// to show the unused generic, with unknown substitution (`_`).
|
|
||||||
//
|
|
||||||
// The alternative is to exclude all generics from being included in the "unused
|
|
||||||
// functions" list, which would then omit coverage results for
|
|
||||||
// `unused_generic_function<T>()`, below.
|
|
|
@ -1,85 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
// Verify that coverage works with optimizations:
|
|
||||||
// compile-flags: -C opt-level=3
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
pub fn used_function() {
|
|
||||||
// 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 countdown = 0;
|
|
||||||
if is_true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
use_this_lib_crate();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn used_inline_function() {
|
|
||||||
// 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 countdown = 0;
|
|
||||||
if is_true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
use_this_lib_crate();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_only_from_bin_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn unused_generic_function<T: Debug>(arg: T) {
|
|
||||||
println!("unused_generic_function with {:?}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn unused_function() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
let mut countdown = 2;
|
|
||||||
if !is_true {
|
|
||||||
countdown = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn unused_private_function() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
let mut countdown = 2;
|
|
||||||
if !is_true {
|
|
||||||
countdown = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_this_lib_crate() {
|
|
||||||
used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
|
|
||||||
used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
|
|
||||||
"used from library used_crate.rs",
|
|
||||||
);
|
|
||||||
let some_vec = vec![5, 6, 7, 8];
|
|
||||||
used_only_from_this_lib_crate_generic_function(some_vec);
|
|
||||||
used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
#![feature(coverage_attribute)]
|
|
||||||
// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3
|
|
||||||
|
|
||||||
// Regression test for <https://github.com/rust-lang/rust/issues/117012>.
|
|
||||||
//
|
|
||||||
// If some coverage counters were removed by MIR optimizations, we need to take
|
|
||||||
// care not to refer to those counter IDs in coverage mappings, and instead
|
|
||||||
// replace them with a constant zero value. If we don't, `llvm-cov` might see
|
|
||||||
// a too-large counter ID and silently discard the entire function from its
|
|
||||||
// coverage reports.
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
struct Foo(u32);
|
|
||||||
|
|
||||||
fn eq_good() {
|
|
||||||
println!("a");
|
|
||||||
assert_eq!(Foo(1), Foo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eq_good_message() {
|
|
||||||
println!("b");
|
|
||||||
assert_eq!(Foo(1), Foo(1), "message b");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ne_good() {
|
|
||||||
println!("c");
|
|
||||||
assert_ne!(Foo(1), Foo(3));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ne_good_message() {
|
|
||||||
println!("d");
|
|
||||||
assert_ne!(Foo(1), Foo(3), "message d");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eq_bad() {
|
|
||||||
println!("e");
|
|
||||||
assert_eq!(Foo(1), Foo(3));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eq_bad_message() {
|
|
||||||
println!("f");
|
|
||||||
assert_eq!(Foo(1), Foo(3), "message f");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ne_bad() {
|
|
||||||
println!("g");
|
|
||||||
assert_ne!(Foo(1), Foo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ne_bad_message() {
|
|
||||||
println!("h");
|
|
||||||
assert_ne!(Foo(1), Foo(1), "message h");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
fn main() {
|
|
||||||
eq_good();
|
|
||||||
eq_good_message();
|
|
||||||
ne_good();
|
|
||||||
ne_good_message();
|
|
||||||
|
|
||||||
assert!(std::panic::catch_unwind(eq_bad).is_err());
|
|
||||||
assert!(std::panic::catch_unwind(eq_bad_message).is_err());
|
|
||||||
assert!(std::panic::catch_unwind(ne_bad).is_err());
|
|
||||||
assert!(std::panic::catch_unwind(ne_bad_message).is_err());
|
|
||||||
}
|
|
|
@ -1,220 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
// compile-flags: -C opt-level=2
|
|
||||||
|
|
||||||
// This test used to be sensitive to certain coverage-specific hacks in
|
|
||||||
// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by
|
|
||||||
// <https://github.com/rust-lang/rust/pull/83666>.
|
|
||||||
|
|
||||||
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 is_false = !is_true;
|
|
||||||
|
|
||||||
let mut some_string = Some(String::from("the string content"));
|
|
||||||
println!(
|
|
||||||
"The string or alt: {}"
|
|
||||||
,
|
|
||||||
some_string
|
|
||||||
.
|
|
||||||
unwrap_or_else
|
|
||||||
(
|
|
||||||
||
|
|
||||||
{
|
|
||||||
let mut countdown = 0;
|
|
||||||
if is_false {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
"alt string 1".to_owned()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
some_string = Some(String::from("the string content"));
|
|
||||||
let
|
|
||||||
a
|
|
||||||
=
|
|
||||||
||
|
|
||||||
{
|
|
||||||
let mut countdown = 0;
|
|
||||||
if is_false {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
"alt string 2".to_owned()
|
|
||||||
};
|
|
||||||
println!(
|
|
||||||
"The string or alt: {}"
|
|
||||||
,
|
|
||||||
some_string
|
|
||||||
.
|
|
||||||
unwrap_or_else
|
|
||||||
(
|
|
||||||
a
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
some_string = None;
|
|
||||||
println!(
|
|
||||||
"The string or alt: {}"
|
|
||||||
,
|
|
||||||
some_string
|
|
||||||
.
|
|
||||||
unwrap_or_else
|
|
||||||
(
|
|
||||||
||
|
|
||||||
{
|
|
||||||
let mut countdown = 0;
|
|
||||||
if is_false {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
"alt string 3".to_owned()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
some_string = None;
|
|
||||||
let
|
|
||||||
a
|
|
||||||
=
|
|
||||||
||
|
|
||||||
{
|
|
||||||
let mut countdown = 0;
|
|
||||||
if is_false {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
"alt string 4".to_owned()
|
|
||||||
};
|
|
||||||
println!(
|
|
||||||
"The string or alt: {}"
|
|
||||||
,
|
|
||||||
some_string
|
|
||||||
.
|
|
||||||
unwrap_or_else
|
|
||||||
(
|
|
||||||
a
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
let
|
|
||||||
quote_closure
|
|
||||||
=
|
|
||||||
|val|
|
|
||||||
{
|
|
||||||
let mut countdown = 0;
|
|
||||||
if is_false {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
format!("'{}'", val)
|
|
||||||
};
|
|
||||||
println!(
|
|
||||||
"Repeated, quoted string: {:?}"
|
|
||||||
,
|
|
||||||
std::iter::repeat("repeat me")
|
|
||||||
.take(5)
|
|
||||||
.map
|
|
||||||
(
|
|
||||||
quote_closure
|
|
||||||
)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
);
|
|
||||||
|
|
||||||
let
|
|
||||||
_unused_closure
|
|
||||||
=
|
|
||||||
|
|
|
||||||
mut countdown
|
|
||||||
|
|
|
||||||
{
|
|
||||||
if is_false {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
"closure should be unused".to_owned()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut countdown = 10;
|
|
||||||
let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
|
|
||||||
|
|
||||||
|
|
||||||
let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
|
|
||||||
let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
|
|
||||||
let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
|
|
||||||
|
|
||||||
let _shortish_unused_closure = | _unused_arg: u8 | {
|
|
||||||
println!("not called")
|
|
||||||
};
|
|
||||||
|
|
||||||
let _as_short_unused_closure = |
|
|
||||||
_unused_arg: u8
|
|
||||||
| { println!("not called") };
|
|
||||||
|
|
||||||
let _almost_as_short_unused_closure = |
|
|
||||||
_unused_arg: u8
|
|
||||||
| { println!("not called") }
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
|
|
||||||
println!("not called")
|
|
||||||
;
|
|
||||||
|
|
||||||
let _short_unused_closure_line_break_no_block2 =
|
|
||||||
| _unused_arg: u8 |
|
|
||||||
println!(
|
|
||||||
"not called"
|
|
||||||
)
|
|
||||||
;
|
|
||||||
|
|
||||||
let short_used_not_covered_closure_line_break_no_block_embedded_branch =
|
|
||||||
| _unused_arg: u8 |
|
|
||||||
println!(
|
|
||||||
"not called: {}",
|
|
||||||
if is_true { "check" } else { "me" }
|
|
||||||
)
|
|
||||||
;
|
|
||||||
|
|
||||||
let short_used_not_covered_closure_line_break_block_embedded_branch =
|
|
||||||
| _unused_arg: u8 |
|
|
||||||
{
|
|
||||||
println!(
|
|
||||||
"not called: {}",
|
|
||||||
if is_true { "check" } else { "me" }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
let short_used_covered_closure_line_break_no_block_embedded_branch =
|
|
||||||
| _unused_arg: u8 |
|
|
||||||
println!(
|
|
||||||
"not called: {}",
|
|
||||||
if is_true { "check" } else { "me" }
|
|
||||||
)
|
|
||||||
;
|
|
||||||
|
|
||||||
let short_used_covered_closure_line_break_block_embedded_branch =
|
|
||||||
| _unused_arg: u8 |
|
|
||||||
{
|
|
||||||
println!(
|
|
||||||
"not called: {}",
|
|
||||||
if is_true { "check" } else { "me" }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
if is_false {
|
|
||||||
short_used_not_covered_closure_macro(0);
|
|
||||||
short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
|
|
||||||
short_used_not_covered_closure_line_break_block_embedded_branch(0);
|
|
||||||
}
|
|
||||||
short_used_covered_closure_macro(0);
|
|
||||||
short_used_covered_closure_line_break_no_block_embedded_branch(0);
|
|
||||||
short_used_covered_closure_line_break_block_embedded_branch(0);
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
// Regression test for #115930.
|
|
||||||
// All of these closures are identical, and should produce identical output in
|
|
||||||
// the coverage report. However, an unstable sort was causing them to be treated
|
|
||||||
// inconsistently when preparing coverage spans.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let truthy = std::env::args().len() == 1;
|
|
||||||
|
|
||||||
let a
|
|
||||||
=
|
|
||||||
|
|
|
||||||
|
|
|
||||||
if truthy { true } else { false };
|
|
||||||
|
|
||||||
a();
|
|
||||||
if truthy { a(); }
|
|
||||||
|
|
||||||
let b
|
|
||||||
=
|
|
||||||
|
|
|
||||||
|
|
|
||||||
if truthy { true } else { false };
|
|
||||||
|
|
||||||
b();
|
|
||||||
if truthy { b(); }
|
|
||||||
|
|
||||||
let c
|
|
||||||
=
|
|
||||||
|
|
|
||||||
|
|
|
||||||
if truthy { true } else { false };
|
|
||||||
|
|
||||||
c();
|
|
||||||
if truthy { c(); }
|
|
||||||
|
|
||||||
let d
|
|
||||||
=
|
|
||||||
|
|
|
||||||
|
|
|
||||||
if truthy { true } else { false };
|
|
||||||
|
|
||||||
d();
|
|
||||||
if truthy { d(); }
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
// compile-flags: --edition=2018
|
|
||||||
#![feature(coverage_attribute)]
|
|
||||||
|
|
||||||
macro_rules! bail {
|
|
||||||
($msg:literal $(,)?) => {
|
|
||||||
if $msg.len() > 0 {
|
|
||||||
println!("no msg");
|
|
||||||
} else {
|
|
||||||
println!($msg);
|
|
||||||
}
|
|
||||||
return Err(String::from($msg));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! on_error {
|
|
||||||
($value:expr, $error_message:expr) => {
|
|
||||||
$value.or_else(|e| { // FIXME(85000): no coverage in closure macros
|
|
||||||
let message = format!($error_message, e);
|
|
||||||
if message.len() > 0 {
|
|
||||||
println!("{}", message);
|
|
||||||
Ok(String::from("ok"))
|
|
||||||
} else {
|
|
||||||
bail!("error");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_configuration_files() -> Result<String, String> {
|
|
||||||
Ok(String::from("config"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() -> Result<(), String> {
|
|
||||||
println!("Starting service");
|
|
||||||
let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
|
|
||||||
|
|
||||||
let startup_delay_duration = String::from("arg");
|
|
||||||
let _ = (config, startup_delay_duration);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
// compile-flags: --edition=2018
|
|
||||||
#![feature(coverage_attribute)]
|
|
||||||
|
|
||||||
macro_rules! bail {
|
|
||||||
($msg:literal $(,)?) => {
|
|
||||||
if $msg.len() > 0 {
|
|
||||||
println!("no msg");
|
|
||||||
} else {
|
|
||||||
println!($msg);
|
|
||||||
}
|
|
||||||
return Err(String::from($msg));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! on_error {
|
|
||||||
($value:expr, $error_message:expr) => {
|
|
||||||
$value.or_else(|e| { // FIXME(85000): no coverage in closure macros
|
|
||||||
let message = format!($error_message, e);
|
|
||||||
if message.len() > 0 {
|
|
||||||
println!("{}", message);
|
|
||||||
Ok(String::from("ok"))
|
|
||||||
} else {
|
|
||||||
bail!("error");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_configuration_files() -> Result<String, String> {
|
|
||||||
Ok(String::from("config"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn test() -> Result<(), String> {
|
|
||||||
println!("Starting service");
|
|
||||||
let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
|
|
||||||
|
|
||||||
let startup_delay_duration = String::from("arg");
|
|
||||||
let _ = (config, startup_delay_duration);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
fn main() {
|
|
||||||
executor::block_on(test()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
mod executor {
|
|
||||||
use core::{
|
|
||||||
future::Future,
|
|
||||||
pin::Pin,
|
|
||||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
pub fn block_on<F: Future>(mut future: F) -> F::Output {
|
|
||||||
let mut future = unsafe { Pin::new_unchecked(&mut future) };
|
|
||||||
use std::hint::unreachable_unchecked;
|
|
||||||
static VTABLE: RawWakerVTable = RawWakerVTable::new(
|
|
||||||
#[coverage(off)]
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // clone
|
|
||||||
#[coverage(off)]
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // wake
|
|
||||||
#[coverage(off)]
|
|
||||||
|_| unsafe { unreachable_unchecked() }, // wake_by_ref
|
|
||||||
#[coverage(off)]
|
|
||||||
|_| (),
|
|
||||||
);
|
|
||||||
let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
|
|
||||||
let mut context = Context::from_waker(&waker);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
|
|
||||||
break val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut countdown = 0;
|
|
||||||
if true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
const B: u32 = 100;
|
|
||||||
let x = if countdown > 7 {
|
|
||||||
countdown -= 4;
|
|
||||||
B
|
|
||||||
} else if countdown > 2 {
|
|
||||||
if countdown < 1 || countdown > 5 || countdown != 9 {
|
|
||||||
countdown = 0;
|
|
||||||
}
|
|
||||||
countdown -= 5;
|
|
||||||
countdown
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut countdown = 0;
|
|
||||||
if true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if countdown > 7 {
|
|
||||||
countdown -= 4;
|
|
||||||
} else if countdown > 2 {
|
|
||||||
if countdown < 1 || countdown > 5 || countdown != 9 {
|
|
||||||
countdown = 0;
|
|
||||||
}
|
|
||||||
countdown -= 5;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if true {
|
|
||||||
let mut countdown = 0;
|
|
||||||
if true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if countdown > 7 {
|
|
||||||
countdown -= 4;
|
|
||||||
}
|
|
||||||
else if countdown > 2 {
|
|
||||||
if countdown < 1 || countdown > 5 || countdown != 9 {
|
|
||||||
countdown = 0;
|
|
||||||
}
|
|
||||||
countdown -= 5;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut countdown = 0;
|
|
||||||
if true {
|
|
||||||
countdown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let z = if countdown > 7 {
|
|
||||||
countdown -= 4;
|
|
||||||
} else if countdown > 2 {
|
|
||||||
if countdown < 1 || countdown > 5 || countdown != 9 {
|
|
||||||
countdown = 0;
|
|
||||||
}
|
|
||||||
countdown -= 5;
|
|
||||||
} else {
|
|
||||||
let should_be_reachable = countdown;
|
|
||||||
println!("reached");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let w = if countdown > 7 {
|
|
||||||
countdown -= 4;
|
|
||||||
} else if countdown > 2 {
|
|
||||||
if countdown < 1 || countdown > 5 || countdown != 9 {
|
|
||||||
countdown = 0;
|
|
||||||
}
|
|
||||||
countdown -= 5;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
|
|
||||||
let mut x = 0;
|
|
||||||
for _ in 0..10 {
|
|
||||||
match is_true {
|
|
||||||
true => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
x = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x = 3;
|
|
||||||
}
|
|
||||||
for _ in 0..10 {
|
|
||||||
match is_true {
|
|
||||||
false => {
|
|
||||||
x = 1;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x = 3;
|
|
||||||
}
|
|
||||||
for _ in 0..10 {
|
|
||||||
match is_true {
|
|
||||||
true => {
|
|
||||||
x = 1;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x = 3;
|
|
||||||
}
|
|
||||||
for _ in 0..10 {
|
|
||||||
if is_true {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
x = 3;
|
|
||||||
}
|
|
||||||
for _ in 0..10 {
|
|
||||||
match is_true {
|
|
||||||
false => {
|
|
||||||
x = 1;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let _ = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x = 3;
|
|
||||||
}
|
|
||||||
for _ in 0..10 {
|
|
||||||
match is_true {
|
|
||||||
false => {
|
|
||||||
x = 1;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x = 3;
|
|
||||||
}
|
|
||||||
let _ = x;
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#![feature(coroutines, coroutine_trait)]
|
|
||||||
|
|
||||||
use std::ops::{Coroutine, CoroutineState};
|
|
||||||
use std::pin::Pin;
|
|
||||||
|
|
||||||
// The following implementation of a function called from a `yield` statement
|
|
||||||
// (apparently requiring the Result and the `String` type or constructor)
|
|
||||||
// creates conditions where the `coroutine::StateTransform` MIR transform will
|
|
||||||
// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
|
|
||||||
// to handle this condition, and still report dead block coverage.
|
|
||||||
fn get_u32(val: bool) -> Result<u32, String> {
|
|
||||||
if val { Ok(1) } else { Err(String::from("some error")) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
let mut coroutine = || {
|
|
||||||
yield get_u32(is_true);
|
|
||||||
return "foo";
|
|
||||||
};
|
|
||||||
|
|
||||||
match Pin::new(&mut coroutine).resume(()) {
|
|
||||||
CoroutineState::Yielded(Ok(1)) => {}
|
|
||||||
_ => panic!("unexpected return from resume"),
|
|
||||||
}
|
|
||||||
match Pin::new(&mut coroutine).resume(()) {
|
|
||||||
CoroutineState::Complete("foo") => {}
|
|
||||||
_ => panic!("unexpected return from resume"),
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
#![allow(dead_code, unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
pub fn unused_pub_fn_not_in_library() {
|
|
||||||
// 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 countdown = 0;
|
|
||||||
if is_true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unused_fn() {
|
|
||||||
// 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 countdown = 0;
|
|
||||||
if is_true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 countdown = 0;
|
|
||||||
if is_true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
// failure-status: 1
|
|
||||||
|
|
||||||
struct Firework {
|
|
||||||
strength: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Firework {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
println!("BOOM times {}!!!", self.strength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
let _firecracker = Firework { strength: 1 };
|
|
||||||
|
|
||||||
let _tnt = Firework { strength: 100 };
|
|
||||||
|
|
||||||
if true {
|
|
||||||
println!("Exiting with error...");
|
|
||||||
return Err(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = Firework { strength: 1000 };
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expected program output:
|
|
||||||
// Exiting with error...
|
|
||||||
// BOOM times 100!!!
|
|
||||||
// BOOM times 1!!!
|
|
||||||
// Error: 1
|
|
|
@ -1,41 +0,0 @@
|
||||||
#![feature(coverage_attribute)]
|
|
||||||
// compile-flags: --edition=2021
|
|
||||||
|
|
||||||
// Regression test for inconsistent handling of function signature spans that
|
|
||||||
// are followed by code using the `?` operator.
|
|
||||||
//
|
|
||||||
// For each of these similar functions, the line containing the function
|
|
||||||
// signature should be handled in the same way.
|
|
||||||
|
|
||||||
fn a() -> Option<i32>
|
|
||||||
{
|
|
||||||
Some(7i32);
|
|
||||||
Some(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn b() -> Option<i32>
|
|
||||||
{
|
|
||||||
Some(7i32)?;
|
|
||||||
Some(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn c() -> Option<i32>
|
|
||||||
{
|
|
||||||
let _ = Some(7i32)?;
|
|
||||||
Some(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn d() -> Option<i32>
|
|
||||||
{
|
|
||||||
let _: () = ();
|
|
||||||
Some(7i32)?;
|
|
||||||
Some(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
fn main() {
|
|
||||||
a();
|
|
||||||
b();
|
|
||||||
c();
|
|
||||||
d();
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
// failure-status: 1
|
|
||||||
|
|
||||||
struct Firework<T> where T: Copy + std::fmt::Display {
|
|
||||||
strength: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Firework<T> where T: Copy + std::fmt::Display {
|
|
||||||
#[inline(always)]
|
|
||||||
fn set_strength(&mut self, new_strength: T) {
|
|
||||||
self.strength = new_strength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
|
|
||||||
#[inline(always)]
|
|
||||||
fn drop(&mut self) {
|
|
||||||
println!("BOOM times {}!!!", self.strength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
let mut firecracker = Firework { strength: 1 };
|
|
||||||
firecracker.set_strength(2);
|
|
||||||
|
|
||||||
let mut tnt = Firework { strength: 100.1 };
|
|
||||||
tnt.set_strength(200.1);
|
|
||||||
tnt.set_strength(300.3);
|
|
||||||
|
|
||||||
if true {
|
|
||||||
println!("Exiting with error...");
|
|
||||||
return Err(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = Firework { strength: 1000 };
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expected program output:
|
|
||||||
// Exiting with error...
|
|
||||||
// BOOM times 100!!!
|
|
||||||
// BOOM times 1!!!
|
|
||||||
// Error: 1
|
|
|
@ -1,28 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
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
|
|
||||||
countdown
|
|
||||||
=
|
|
||||||
0
|
|
||||||
;
|
|
||||||
if
|
|
||||||
is_true
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
=
|
|
||||||
10
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
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 countdown = 0;
|
|
||||||
if
|
|
||||||
is_true
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
=
|
|
||||||
10
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else // Note coverage region difference without semicolon
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
=
|
|
||||||
100
|
|
||||||
}
|
|
||||||
|
|
||||||
if
|
|
||||||
is_true
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
=
|
|
||||||
10
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
=
|
|
||||||
100
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// Regression test for issue #98833.
|
|
||||||
// compile-flags: -Zinline-mir -Cdebug-assertions=off
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("{}", live::<false>());
|
|
||||||
|
|
||||||
let f = |x: bool| {
|
|
||||||
debug_assert!(
|
|
||||||
x
|
|
||||||
);
|
|
||||||
};
|
|
||||||
f(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn live<const B: bool>() -> u32 {
|
|
||||||
if B {
|
|
||||||
dead()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn dead() -> u32 {
|
|
||||||
42
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
// compile-flags: -Zinline-mir
|
|
||||||
|
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
permutations(&['a', 'b', 'c']);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn permutations<T: Copy + Display>(xs: &[T]) {
|
|
||||||
let mut ys = xs.to_owned();
|
|
||||||
permutate(&mut ys, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
|
|
||||||
let n = length(xs);
|
|
||||||
if k == n {
|
|
||||||
display(xs);
|
|
||||||
} else if k < n {
|
|
||||||
for i in k..n {
|
|
||||||
swap(xs, i, k);
|
|
||||||
permutate(xs, k + 1);
|
|
||||||
swap(xs, i, k);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn length<T>(xs: &[T]) -> usize {
|
|
||||||
xs.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
|
|
||||||
let t = xs[i];
|
|
||||||
xs[i] = xs[j];
|
|
||||||
xs[j] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn display<T: Display>(xs: &[T]) {
|
|
||||||
for x in xs {
|
|
||||||
print!("{}", x);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn error() {
|
|
||||||
panic!("error");
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables, dead_code)]
|
|
||||||
|
|
||||||
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 countdown = 0;
|
|
||||||
if is_true {
|
|
||||||
countdown = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod in_mod {
|
|
||||||
const IN_MOD_CONST: u32 = 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_func(a: u32) {
|
|
||||||
let b = 1;
|
|
||||||
let c = a + b;
|
|
||||||
println!("c = {}", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct InStruct {
|
|
||||||
in_struct_field: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
const IN_CONST: u32 = 1234;
|
|
||||||
|
|
||||||
trait InTrait {
|
|
||||||
fn trait_func(&mut self, incr: u32);
|
|
||||||
|
|
||||||
fn default_trait_func(&mut self) {
|
|
||||||
in_func(IN_CONST);
|
|
||||||
self.trait_func(IN_CONST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InTrait for InStruct {
|
|
||||||
fn trait_func(&mut self, incr: u32) {
|
|
||||||
self.in_struct_field += incr;
|
|
||||||
in_func(self.in_struct_field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InType = String;
|
|
||||||
|
|
||||||
if is_true {
|
|
||||||
in_func(countdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut val = InStruct {
|
|
||||||
in_struct_field: 101,
|
|
||||||
};
|
|
||||||
|
|
||||||
val.default_trait_func();
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
// Shows that rust-lang/rust/83601 is resolved
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
struct Foo(u32);
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let bar = Foo(1);
|
|
||||||
assert_eq!(bar, Foo(1));
|
|
||||||
let baz = Foo(0);
|
|
||||||
assert_ne!(baz, Foo(1));
|
|
||||||
println!("{:?}", Foo(1));
|
|
||||||
println!("{:?}", bar);
|
|
||||||
println!("{:?}", baz);
|
|
||||||
}
|
|
|
@ -1,182 +0,0 @@
|
||||||
// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
|
|
||||||
|
|
||||||
// failure-status: 101
|
|
||||||
#[derive(PartialEq, Eq)]
|
|
||||||
struct Foo(u32);
|
|
||||||
fn test3() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
let bar = Foo(1);
|
|
||||||
assert_eq!(bar, Foo(1));
|
|
||||||
let baz = Foo(0);
|
|
||||||
assert_ne!(baz, Foo(1));
|
|
||||||
println!("{:?}", Foo(1));
|
|
||||||
println!("{:?}", bar);
|
|
||||||
println!("{:?}", baz);
|
|
||||||
|
|
||||||
assert_eq!(Foo(1), Foo(1));
|
|
||||||
assert_ne!(Foo(0), Foo(1));
|
|
||||||
assert_eq!(Foo(2), Foo(2));
|
|
||||||
let bar = Foo(0);
|
|
||||||
assert_ne!(bar, Foo(3));
|
|
||||||
assert_ne!(Foo(0), Foo(4));
|
|
||||||
assert_eq!(Foo(3), Foo(3), "with a message");
|
|
||||||
println!("{:?}", bar);
|
|
||||||
println!("{:?}", Foo(1));
|
|
||||||
|
|
||||||
assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
|
|
||||||
assert_ne!(
|
|
||||||
Foo(0)
|
|
||||||
,
|
|
||||||
Foo(5)
|
|
||||||
,
|
|
||||||
"{}"
|
|
||||||
,
|
|
||||||
if
|
|
||||||
is_true
|
|
||||||
{
|
|
||||||
"true message"
|
|
||||||
} else {
|
|
||||||
"false message"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
Foo(1),
|
|
||||||
Foo(1)
|
|
||||||
);
|
|
||||||
assert_ne!(
|
|
||||||
Foo(0),
|
|
||||||
Foo(1)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Foo(2),
|
|
||||||
Foo(2)
|
|
||||||
);
|
|
||||||
let bar = Foo(1);
|
|
||||||
assert_ne!(
|
|
||||||
bar,
|
|
||||||
Foo(3)
|
|
||||||
);
|
|
||||||
if is_true {
|
|
||||||
assert_ne!(
|
|
||||||
Foo(0),
|
|
||||||
Foo(4)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
assert_eq!(
|
|
||||||
Foo(3),
|
|
||||||
Foo(3)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if is_true {
|
|
||||||
assert_ne!(
|
|
||||||
Foo(0),
|
|
||||||
Foo(4),
|
|
||||||
"with a message"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
assert_eq!(
|
|
||||||
Foo(3),
|
|
||||||
Foo(3),
|
|
||||||
"with a message"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
assert_ne!(
|
|
||||||
if is_true {
|
|
||||||
Foo(0)
|
|
||||||
} else {
|
|
||||||
Foo(1)
|
|
||||||
},
|
|
||||||
Foo(5)
|
|
||||||
);
|
|
||||||
assert_ne!(
|
|
||||||
Foo(5),
|
|
||||||
if is_true {
|
|
||||||
Foo(0)
|
|
||||||
} else {
|
|
||||||
Foo(1)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_ne!(
|
|
||||||
if is_true {
|
|
||||||
assert_eq!(
|
|
||||||
Foo(3),
|
|
||||||
Foo(3)
|
|
||||||
);
|
|
||||||
Foo(0)
|
|
||||||
} else {
|
|
||||||
assert_ne!(
|
|
||||||
if is_true {
|
|
||||||
Foo(0)
|
|
||||||
} else {
|
|
||||||
Foo(1)
|
|
||||||
},
|
|
||||||
Foo(5)
|
|
||||||
);
|
|
||||||
Foo(1)
|
|
||||||
},
|
|
||||||
Foo(5),
|
|
||||||
"with a message"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Foo(1),
|
|
||||||
Foo(3),
|
|
||||||
"this assert should fail"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Foo(3),
|
|
||||||
Foo(3),
|
|
||||||
"this assert should not be reached"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for Foo {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(f, "try and succeed")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut DEBUG_LEVEL_ENABLED: bool = false;
|
|
||||||
|
|
||||||
macro_rules! debug {
|
|
||||||
($($arg:tt)+) => (
|
|
||||||
if unsafe { DEBUG_LEVEL_ENABLED } {
|
|
||||||
println!($($arg)+);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test1() {
|
|
||||||
debug!("debug is enabled");
|
|
||||||
debug!("debug is enabled");
|
|
||||||
let _ = 0;
|
|
||||||
debug!("debug is enabled");
|
|
||||||
unsafe {
|
|
||||||
DEBUG_LEVEL_ENABLED = true;
|
|
||||||
}
|
|
||||||
debug!("debug is enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! call_debug {
|
|
||||||
($($arg:tt)+) => (
|
|
||||||
fn call_print(s: &str) {
|
|
||||||
print!("{}", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
call_print("called from call_debug: ");
|
|
||||||
debug!($($arg)+);
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test2() {
|
|
||||||
call_debug!("debug is enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
test1();
|
|
||||||
test2();
|
|
||||||
test3();
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
|
|
||||||
|
|
||||||
// aux-build:inline_always_with_dead_code.rs
|
|
||||||
extern crate inline_always_with_dead_code;
|
|
||||||
|
|
||||||
use inline_always_with_dead_code::{bar, baz};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
bar::call_me();
|
|
||||||
baz::call_me();
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#![allow(dead_code, unreachable_code)]
|
|
||||||
|
|
||||||
// Regression test for #93054: Functions using uninhabited types often only have a single,
|
|
||||||
// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
|
|
||||||
// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
|
|
||||||
|
|
||||||
// compile-flags: --edition=2021
|
|
||||||
|
|
||||||
enum Never {}
|
|
||||||
|
|
||||||
impl Never {
|
|
||||||
fn foo(self) {
|
|
||||||
match self {}
|
|
||||||
make().map(|never| match never {});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bar(&self) {
|
|
||||||
match *self {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn foo2(never: Never) {
|
|
||||||
match never {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make() -> Option<Never> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,61 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
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, mut b, mut c) = (0, 0, 0);
|
|
||||||
if is_true {
|
|
||||||
a = 1;
|
|
||||||
b = 10;
|
|
||||||
c = 100;
|
|
||||||
}
|
|
||||||
let
|
|
||||||
somebool
|
|
||||||
=
|
|
||||||
a < b
|
|
||||||
||
|
|
||||||
b < c
|
|
||||||
;
|
|
||||||
let
|
|
||||||
somebool
|
|
||||||
=
|
|
||||||
b < a
|
|
||||||
||
|
|
||||||
b < c
|
|
||||||
;
|
|
||||||
let somebool = a < b && b < c;
|
|
||||||
let somebool = b < a && b < c;
|
|
||||||
|
|
||||||
if
|
|
||||||
!
|
|
||||||
is_true
|
|
||||||
{
|
|
||||||
a = 2
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
if
|
|
||||||
is_true
|
|
||||||
{
|
|
||||||
b = 30
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c = 400
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !is_true {
|
|
||||||
a = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_true {
|
|
||||||
b = 30;
|
|
||||||
} else {
|
|
||||||
c = 400;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,150 +0,0 @@
|
||||||
// compile-flags: --edition=2021
|
|
||||||
// ignore-tidy-linelength
|
|
||||||
|
|
||||||
// This file deliberately contains line and column numbers larger than 127,
|
|
||||||
// to verify that `coverage-dump`'s ULEB128 parser can handle them.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
wide_function();
|
|
||||||
long_function();
|
|
||||||
far_function();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn wide_function() { /* */ (); }
|
|
||||||
|
|
||||||
fn long_function() {
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
fn far_function() {}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let result
|
|
||||||
=
|
|
||||||
loop
|
|
||||||
{
|
|
||||||
break
|
|
||||||
10
|
|
||||||
;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables, while_true)]
|
|
||||||
|
|
||||||
// This test confirms that (1) unexecuted infinite loops are handled correctly by the
|
|
||||||
// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
|
|
||||||
|
|
||||||
struct DebugTest;
|
|
||||||
|
|
||||||
impl std::fmt::Debug for DebugTest {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
if true {
|
|
||||||
if false {
|
|
||||||
while true {}
|
|
||||||
}
|
|
||||||
write!(f, "cool")?;
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..10 {
|
|
||||||
if true {
|
|
||||||
if false {
|
|
||||||
while true {}
|
|
||||||
}
|
|
||||||
write!(f, "cool")?;
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DisplayTest;
|
|
||||||
|
|
||||||
impl std::fmt::Display for DisplayTest {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
if false {
|
|
||||||
while true {}
|
|
||||||
}
|
|
||||||
write!(f, "cool")?;
|
|
||||||
}
|
|
||||||
for i in 0..10 {
|
|
||||||
if false {
|
|
||||||
} else {
|
|
||||||
if false {
|
|
||||||
while true {}
|
|
||||||
}
|
|
||||||
write!(f, "cool")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let debug_test = DebugTest;
|
|
||||||
println!("{:?}", debug_test);
|
|
||||||
let display_test = DisplayTest;
|
|
||||||
println!("{}", display_test);
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
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) => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
fn main() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
let mut countdown = 10;
|
|
||||||
|
|
||||||
'outer: while countdown > 0 {
|
|
||||||
let mut a = 100;
|
|
||||||
let mut b = 100;
|
|
||||||
for _ in 0..50 {
|
|
||||||
if a < 30 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
a -= 5;
|
|
||||||
b -= 5;
|
|
||||||
if b < 90 {
|
|
||||||
a -= 10;
|
|
||||||
if is_true {
|
|
||||||
break 'outer;
|
|
||||||
} else {
|
|
||||||
a -= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
countdown -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
// Enables `coverage(off)` on the entire crate
|
|
||||||
#![feature(coverage_attribute)]
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
fn do_not_add_coverage_1() {
|
|
||||||
println!("called but not covered");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_not_add_coverage_2() {
|
|
||||||
#![coverage(off)]
|
|
||||||
println!("called but not covered");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn do_not_add_coverage_not_called() {
|
|
||||||
println!("not called and not covered");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_coverage_1() {
|
|
||||||
println!("called and covered");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_coverage_2() {
|
|
||||||
println!("called and covered");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn add_coverage_not_called() {
|
|
||||||
println!("not called but covered");
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: These test-cases illustrate confusing results of nested functions.
|
|
||||||
// See https://github.com/rust-lang/rust/issues/93319
|
|
||||||
mod nested_fns {
|
|
||||||
#[coverage(off)]
|
|
||||||
pub fn outer_not_covered(is_true: bool) {
|
|
||||||
fn inner(is_true: bool) {
|
|
||||||
if is_true {
|
|
||||||
println!("called and covered");
|
|
||||||
} else {
|
|
||||||
println!("absolutely not covered");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("called but not covered");
|
|
||||||
inner(is_true);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn outer(is_true: bool) {
|
|
||||||
println!("called and covered");
|
|
||||||
inner_not_covered(is_true);
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
fn inner_not_covered(is_true: bool) {
|
|
||||||
if is_true {
|
|
||||||
println!("called but not covered");
|
|
||||||
} else {
|
|
||||||
println!("absolutely not covered");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn outer_both_covered(is_true: bool) {
|
|
||||||
println!("called and covered");
|
|
||||||
inner(is_true);
|
|
||||||
|
|
||||||
fn inner(is_true: bool) {
|
|
||||||
if is_true {
|
|
||||||
println!("called and covered");
|
|
||||||
} else {
|
|
||||||
println!("absolutely not covered");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let is_true = std::env::args().len() == 1;
|
|
||||||
|
|
||||||
do_not_add_coverage_1();
|
|
||||||
do_not_add_coverage_2();
|
|
||||||
add_coverage_1();
|
|
||||||
add_coverage_2();
|
|
||||||
|
|
||||||
nested_fns::outer_not_covered(is_true);
|
|
||||||
nested_fns::outer(is_true);
|
|
||||||
nested_fns::outer_both_covered(is_true);
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
// compile-flags: -Coverflow-checks=yes
|
|
||||||
// failure-status: 101
|
|
||||||
|
|
||||||
fn might_overflow(to_add: u32) -> u32 {
|
|
||||||
if to_add > 5 {
|
|
||||||
println!("this will probably overflow");
|
|
||||||
}
|
|
||||||
let add_to = u32::MAX - 5;
|
|
||||||
println!("does {} + {} overflow?", add_to, to_add);
|
|
||||||
let result = to_add + add_to;
|
|
||||||
println!("continuing after overflow check");
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
let mut countdown = 10;
|
|
||||||
while countdown > 0 {
|
|
||||||
if countdown == 1 {
|
|
||||||
let result = might_overflow(10);
|
|
||||||
println!("Result: {}", result);
|
|
||||||
} else if countdown < 5 {
|
|
||||||
let result = might_overflow(1);
|
|
||||||
println!("Result: {}", result);
|
|
||||||
}
|
|
||||||
countdown -= 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notes:
|
|
||||||
// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
|
|
||||||
// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
|
|
||||||
// 2. This test confirms the coverage generated when a program passes or fails a
|
|
||||||
// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
|
|
||||||
// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
|
|
||||||
// compiler-generated assertion failures are assumed to be a symptom of a program bug, not
|
|
||||||
// expected behavior. To simplify the coverage graphs and keep instrumented programs as
|
|
||||||
// small and fast as possible, `Assert` terminators are assumed to always succeed, and
|
|
||||||
// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
|
|
||||||
// get its own coverage counter.
|
|
||||||
// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
|
|
||||||
// In this test, the final count for the statements after the `if` block in `might_overflow()`
|
|
||||||
// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
|
|
||||||
// on the MIR graph and the structure of the code, this count could have been 3 (which might
|
|
||||||
// have been valid for the overflowed add `+`, but should have been 4 for the lines before
|
|
||||||
// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
|
|
||||||
// via StatementKind::Counter at the end of the block, but (as in the case in this test),
|
|
||||||
// a CounterKind::Expression is always evaluated. In this case, the expression was based on
|
|
||||||
// a `Counter` incremented as part of the evaluation of the `if` expression, which was
|
|
||||||
// executed, and counted, 4 times, before reaching the overflow add.
|
|
||||||
|
|
||||||
// If the program did not overflow, the coverage for `might_overflow()` would look like this:
|
|
||||||
//
|
|
||||||
// 4| |fn might_overflow(to_add: u32) -> u32 {
|
|
||||||
// 5| 4| if to_add > 5 {
|
|
||||||
// 6| 0| println!("this will probably overflow");
|
|
||||||
// 7| 4| }
|
|
||||||
// 8| 4| let add_to = u32::MAX - 5;
|
|
||||||
// 9| 4| println!("does {} + {} overflow?", add_to, to_add);
|
|
||||||
// 10| 4| let result = to_add + add_to;
|
|
||||||
// 11| 4| println!("continuing after overflow check");
|
|
||||||
// 12| 4| result
|
|
||||||
// 13| 4|}
|
|
|
@ -1,31 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
// failure-status: 101
|
|
||||||
|
|
||||||
fn might_panic(should_panic: bool) {
|
|
||||||
if should_panic {
|
|
||||||
println!("panicking...");
|
|
||||||
panic!("panics");
|
|
||||||
} else {
|
|
||||||
println!("Don't Panic");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
let mut countdown = 10;
|
|
||||||
while countdown > 0 {
|
|
||||||
if countdown == 1 {
|
|
||||||
might_panic(true);
|
|
||||||
} else if countdown < 5 {
|
|
||||||
might_panic(false);
|
|
||||||
}
|
|
||||||
countdown -= 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notes:
|
|
||||||
// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
|
|
||||||
// `try_error_result.rs`.
|
|
||||||
// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
|
|
||||||
// normal program exit cleanup, including writing out the current values of the coverage
|
|
||||||
// counters.
|
|
|
@ -1,46 +0,0 @@
|
||||||
// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
|
|
||||||
// structure of this test.
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct Version {
|
|
||||||
major: usize,
|
|
||||||
minor: usize,
|
|
||||||
patch: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Version {
|
|
||||||
pub fn new(major: usize, minor: usize, patch: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
major,
|
|
||||||
minor,
|
|
||||||
patch,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let version_3_2_1 = Version::new(3, 2, 1);
|
|
||||||
let version_3_3_0 = Version::new(3, 3, 0);
|
|
||||||
|
|
||||||
println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
This test verifies a bug was fixed that otherwise generated this error:
|
|
||||||
|
|
||||||
thread 'rustc' panicked at 'No counters provided the source_hash for function:
|
|
||||||
Instance {
|
|
||||||
def: Item(WithOptConstParam {
|
|
||||||
did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
|
|
||||||
const_param_did: None
|
|
||||||
}),
|
|
||||||
args: []
|
|
||||||
}'
|
|
||||||
The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
|
|
||||||
without a code region associated with any `Counter`. Code regions were associated with at least
|
|
||||||
one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
|
|
||||||
(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
|
|
||||||
`function_source_hash` without a code region, if necessary.
|
|
||||||
|
|
||||||
*/
|
|
|
@ -1,35 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
|
|
||||||
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 countdown = 0;
|
|
||||||
|
|
||||||
if
|
|
||||||
is_true
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
=
|
|
||||||
10
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
loop
|
|
||||||
{
|
|
||||||
if
|
|
||||||
countdown
|
|
||||||
==
|
|
||||||
0
|
|
||||||
{
|
|
||||||
break
|
|
||||||
;
|
|
||||||
}
|
|
||||||
countdown
|
|
||||||
-=
|
|
||||||
1
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
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 countdown = 1;
|
|
||||||
if is_true {
|
|
||||||
countdown = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for
|
|
||||||
_
|
|
||||||
in
|
|
||||||
0..2
|
|
||||||
{
|
|
||||||
let z
|
|
||||||
;
|
|
||||||
match
|
|
||||||
countdown
|
|
||||||
{
|
|
||||||
x
|
|
||||||
if
|
|
||||||
x
|
|
||||||
<
|
|
||||||
1
|
|
||||||
=>
|
|
||||||
{
|
|
||||||
z = countdown
|
|
||||||
;
|
|
||||||
let y = countdown
|
|
||||||
;
|
|
||||||
countdown = 10
|
|
||||||
;
|
|
||||||
}
|
|
||||||
_
|
|
||||||
=>
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
// compile-flags: --edition=2021
|
|
||||||
|
|
||||||
// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
|
|
||||||
// predictable order, while preserving their heterogeneous contents.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let cond = std::env::args().len() > 1;
|
|
||||||
generic_fn::<()>(cond);
|
|
||||||
generic_fn::<&'static str>(!cond);
|
|
||||||
if std::hint::black_box(false) {
|
|
||||||
generic_fn::<char>(cond);
|
|
||||||
}
|
|
||||||
generic_fn::<i32>(cond);
|
|
||||||
other_fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generic_fn<T>(cond: bool) {
|
|
||||||
if cond {
|
|
||||||
println!("{}", std::any::type_name::<T>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn other_fn() {}
|
|
|
@ -1,10 +0,0 @@
|
||||||
// Verify that the entry point injected by the test harness doesn't cause
|
|
||||||
// weird artifacts in the coverage report (e.g. issue #10749).
|
|
||||||
|
|
||||||
// compile-flags: --test
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn unused() {}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn my_test() {}
|
|
|
@ -1,5 +0,0 @@
|
||||||
fn main() {
|
|
||||||
if false {
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
// compile-flags: --edition=2021
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,118 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
// failure-status: 1
|
|
||||||
|
|
||||||
fn call(return_error: bool) -> Result<(), ()> {
|
|
||||||
if return_error {
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test1() -> Result<(), ()> {
|
|
||||||
let mut
|
|
||||||
countdown = 10
|
|
||||||
;
|
|
||||||
for
|
|
||||||
_
|
|
||||||
in
|
|
||||||
0..10
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
-= 1
|
|
||||||
;
|
|
||||||
if
|
|
||||||
countdown < 5
|
|
||||||
{
|
|
||||||
call(/*return_error=*/ true)?;
|
|
||||||
call(/*return_error=*/ false)?;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
call(/*return_error=*/ false)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Thing1;
|
|
||||||
impl Thing1 {
|
|
||||||
fn get_thing_2(&self, return_error: bool) -> Result<Thing2, ()> {
|
|
||||||
if return_error {
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
Ok(Thing2 {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Thing2;
|
|
||||||
impl Thing2 {
|
|
||||||
fn call(&self, return_error: bool) -> Result<u32, ()> {
|
|
||||||
if return_error {
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
Ok(57)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test2() -> Result<(), ()> {
|
|
||||||
let thing1 = Thing1{};
|
|
||||||
let mut
|
|
||||||
countdown = 10
|
|
||||||
;
|
|
||||||
for
|
|
||||||
_
|
|
||||||
in
|
|
||||||
0..10
|
|
||||||
{
|
|
||||||
countdown
|
|
||||||
-= 1
|
|
||||||
;
|
|
||||||
if
|
|
||||||
countdown < 5
|
|
||||||
{
|
|
||||||
thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
|
|
||||||
thing1
|
|
||||||
.
|
|
||||||
get_thing_2(/*return_error=*/ false)
|
|
||||||
?
|
|
||||||
.
|
|
||||||
call(/*return_error=*/ true)
|
|
||||||
.
|
|
||||||
expect_err(
|
|
||||||
"call should fail"
|
|
||||||
);
|
|
||||||
let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
|
|
||||||
assert_eq!(val, 57);
|
|
||||||
let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
|
|
||||||
assert_eq!(val, 57);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
|
|
||||||
assert_eq!(val, 57);
|
|
||||||
let val = thing1
|
|
||||||
.get_thing_2(/*return_error=*/ false)?
|
|
||||||
.call(/*return_error=*/ false)?;
|
|
||||||
assert_eq!(val, 57);
|
|
||||||
let val = thing1
|
|
||||||
.get_thing_2(/*return_error=*/ false)
|
|
||||||
?
|
|
||||||
.call(/*return_error=*/ false)
|
|
||||||
?
|
|
||||||
;
|
|
||||||
assert_eq!(val, 57);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), ()> {
|
|
||||||
test1().expect_err("test1 should fail");
|
|
||||||
test2()
|
|
||||||
?
|
|
||||||
;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
#![feature(core_intrinsics)]
|
|
||||||
#![feature(coverage_attribute)]
|
|
||||||
// compile-flags: --edition=2021
|
|
||||||
|
|
||||||
// <https://github.com/rust-lang/rust/issues/116171>
|
|
||||||
// If we instrument a function for coverage, but all of its counter-increment
|
|
||||||
// statements are removed by MIR optimizations, LLVM will think it isn't
|
|
||||||
// instrumented and it will disappear from coverage maps and coverage reports.
|
|
||||||
// Most MIR opts won't cause this because they tend not to remove statements
|
|
||||||
// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
|
|
||||||
// with `TerminatorKind::Unreachable`.
|
|
||||||
|
|
||||||
use std::hint::{black_box, unreachable_unchecked};
|
|
||||||
|
|
||||||
static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
|
|
||||||
|
|
||||||
fn unreachable_function() {
|
|
||||||
unsafe { unreachable_unchecked() }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use an intrinsic to more reliably trigger unreachable-propagation.
|
|
||||||
fn unreachable_intrinsic() {
|
|
||||||
unsafe { std::intrinsics::unreachable() }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[coverage(off)]
|
|
||||||
fn main() {
|
|
||||||
if black_box(false) {
|
|
||||||
UNREACHABLE_CLOSURE();
|
|
||||||
}
|
|
||||||
if black_box(false) {
|
|
||||||
unreachable_function();
|
|
||||||
}
|
|
||||||
if black_box(false) {
|
|
||||||
unreachable_intrinsic();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)]
|
|
||||||
|
|
||||||
fn foo<T>(x: T) {
|
|
||||||
let mut i = 0;
|
|
||||||
while i < 10 {
|
|
||||||
i != 0 || i != 0;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unused_template_func<T>(x: T) {
|
|
||||||
let mut i = 0;
|
|
||||||
while i < 10 {
|
|
||||||
i != 0 || i != 0;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unused_func(mut a: u32) {
|
|
||||||
if a != 0 {
|
|
||||||
a += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unused_func2(mut a: u32) {
|
|
||||||
if a != 0 {
|
|
||||||
a += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unused_func3(mut a: u32) {
|
|
||||||
if a != 0 {
|
|
||||||
a += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
foo::<u32>(0);
|
|
||||||
foo::<f32>(0.0);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
#[path = "auxiliary/unused_mod_helper.rs"]
|
|
||||||
mod unused_module;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("hello world!");
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
// This test was failing on Linux for a while due to #110393 somehow making
|
|
||||||
// the unused functions not instrumented, but it seems to be fine now.
|
|
||||||
|
|
||||||
// Validates coverage now works with optimizations
|
|
||||||
// compile-flags: -C opt-level=3
|
|
||||||
|
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
// aux-build:used_crate.rs
|
|
||||||
extern crate used_crate;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
used_crate::used_function();
|
|
||||||
let some_vec = vec![1, 2, 3, 4];
|
|
||||||
used_crate::used_only_from_bin_crate_generic_function(&some_vec);
|
|
||||||
used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
|
|
||||||
used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
|
|
||||||
used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
// This test was failing on Linux for a while due to #110393 somehow making
|
|
||||||
// the unused functions not instrumented, but it seems to be fine now.
|
|
||||||
|
|
||||||
// Validates coverage now works with optimizations
|
|
||||||
// compile-flags: -C opt-level=3
|
|
||||||
|
|
||||||
#![allow(unused_assignments, unused_variables)]
|
|
||||||
|
|
||||||
// aux-build:used_inline_crate.rs
|
|
||||||
extern crate used_inline_crate;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
used_inline_crate::used_function();
|
|
||||||
used_inline_crate::used_inline_function();
|
|
||||||
let some_vec = vec![1, 2, 3, 4];
|
|
||||||
used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
|
|
||||||
used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
|
|
||||||
used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
|
|
||||||
used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
|
|
||||||
"interesting?",
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
fn main() {
|
|
||||||
let num = 9;
|
|
||||||
while num >= 10 {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
#![allow(unused_assignments)]
|
|
||||||
// failure-status: 1
|
|
||||||
|
|
||||||
fn main() -> Result<(), u8> {
|
|
||||||
let mut countdown = 10;
|
|
||||||
while
|
|
||||||
countdown
|
|
||||||
>
|
|
||||||
0
|
|
||||||
{
|
|
||||||
if
|
|
||||||
countdown
|
|
||||||
<
|
|
||||||
5
|
|
||||||
{
|
|
||||||
return
|
|
||||||
if
|
|
||||||
countdown
|
|
||||||
>
|
|
||||||
8
|
|
||||||
{
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Err(1)
|
|
||||||
}
|
|
||||||
;
|
|
||||||
}
|
|
||||||
countdown
|
|
||||||
-=
|
|
||||||
1
|
|
||||||
;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
|
|
||||||
// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
|
|
||||||
// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
|
|
||||||
// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
|
|
||||||
// to the coverage test for early returns, but this is a limitation that should be fixed.
|
|
|
@ -1,37 +0,0 @@
|
||||||
#![feature(coroutines, coroutine_trait)]
|
|
||||||
#![allow(unused_assignments)]
|
|
||||||
|
|
||||||
use std::ops::{Coroutine, CoroutineState};
|
|
||||||
use std::pin::Pin;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut coroutine = || {
|
|
||||||
yield 1;
|
|
||||||
return "foo";
|
|
||||||
};
|
|
||||||
|
|
||||||
match Pin::new(&mut coroutine).resume(()) {
|
|
||||||
CoroutineState::Yielded(1) => {}
|
|
||||||
_ => panic!("unexpected value from resume"),
|
|
||||||
}
|
|
||||||
match Pin::new(&mut coroutine).resume(()) {
|
|
||||||
CoroutineState::Complete("foo") => {}
|
|
||||||
_ => panic!("unexpected value from resume"),
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut coroutine = || {
|
|
||||||
yield 1;
|
|
||||||
yield 2;
|
|
||||||
yield 3;
|
|
||||||
return "foo";
|
|
||||||
};
|
|
||||||
|
|
||||||
match Pin::new(&mut coroutine).resume(()) {
|
|
||||||
CoroutineState::Yielded(1) => {}
|
|
||||||
_ => panic!("unexpected value from resume"),
|
|
||||||
}
|
|
||||||
match Pin::new(&mut coroutine).resume(()) {
|
|
||||||
CoroutineState::Yielded(2) => {}
|
|
||||||
_ => panic!("unexpected value from resume"),
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue