+++ /dev/null
-# needs-profiler-support
-
-# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
-# corresponding with LLVM versions 12 and 13, respectively.
-# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
-# version during testing, with an additional directive at the top of this file
-# that sets, for example: `min-llvm-version: 12.0`
-
--include ../coverage/coverage_tools.mk
-
-BASEDIR=../coverage-llvmir
-
-ifeq ($(UNAME),Darwin)
- INSTR_PROF_DATA_SUFFIX=,regular,live_support
- DATA_SECTION_PREFIX=__DATA,
- LLVM_COV_SECTION_PREFIX=__LLVM_COV,
- COMDAT_IF_SUPPORTED=
-else
- INSTR_PROF_DATA_SUFFIX=
- DATA_SECTION_PREFIX=
- LLVM_COV_SECTION_PREFIX=
- COMDAT_IF_SUPPORTED=, comdat
-endif
-
-DEFINE_INTERNAL=define internal
-
-ifdef IS_WINDOWS
- LLVM_FILECHECK_OPTIONS=\
- -check-prefixes=CHECK,WINDOWS \
- -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
- -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
- -DINSTR_PROF_DATA='.lprfd$$M' \
- -DINSTR_PROF_NAME='.lprfn$$M' \
- -DINSTR_PROF_CNTS='.lprfc$$M' \
- -DINSTR_PROF_VALS='.lprfv$$M' \
- -DINSTR_PROF_VNODES='.lprfnd$$M' \
- -DINSTR_PROF_COVMAP='.lcovmap$$M' \
- -DINSTR_PROF_COVFUN='.lcovfun$$M' \
- -DINSTR_PROF_ORDERFILE='.lorderfile$$M'
-else
- LLVM_FILECHECK_OPTIONS=\
- -check-prefixes=CHECK \
- -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
- -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
- -DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \
- -DINSTR_PROF_NAME='$(DATA_SECTION_PREFIX)__llvm_prf_names' \
- -DINSTR_PROF_CNTS='$(DATA_SECTION_PREFIX)__llvm_prf_cnts' \
- -DINSTR_PROF_VALS='$(DATA_SECTION_PREFIX)__llvm_prf_vals' \
- -DINSTR_PROF_VNODES='$(DATA_SECTION_PREFIX)__llvm_prf_vnds' \
- -DINSTR_PROF_COVMAP='$(LLVM_COV_SECTION_PREFIX)__llvm_covmap' \
- -DINSTR_PROF_COVFUN='$(LLVM_COV_SECTION_PREFIX)__llvm_covfun' \
- -DINSTR_PROF_ORDERFILE='$(DATA_SECTION_PREFIX)__llvm_orderfile'
-endif
-
-all: test_llvm_ir
-
-test_llvm_ir:
- # Compile the test program with non-experimental coverage instrumentation, and generate LLVM IR
- $(RUSTC) $(BASEDIR)/testprog.rs \
- -Cinstrument-coverage \
- --emit=llvm-ir
-
- cat "$(TMPDIR)"/testprog.ll | \
- "$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
+++ /dev/null
-# Check for metadata, variables, declarations, and function definitions injected
-# into LLVM IR when compiling with -Cinstrument-coverage.
-
-WINDOWS: $__llvm_profile_runtime_user = comdat any
-
-CHECK: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
-CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
-
-CHECK: @__llvm_coverage_mapping = private constant
-CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
-
-WINDOWS: @__llvm_profile_runtime = external global i32
-
-CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
-CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
-
-CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
-CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called
-CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
-
-CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
-CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
-
-CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
-CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main
-CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
-
-CHECK: @__llvm_prf_nm = private constant
-CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
-
-CHECK: @llvm.used = appending global
-CHECK-SAME: @__llvm_coverage_mapping
-CHECK-SAME: @__llvm_prf_nm
-CHECK-SAME: section "llvm.metadata"
-
-CHECK: [[DEFINE_INTERNAL]] { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
-CHECK-NEXT: start:
-CHECK-NOT: [[DEFINE_INTERNAL]]
-CHECK: %pgocount = load i64, {{i64\*|ptr}}
-CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
-
-CHECK: declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
-
-WINDOWS: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
-WINDOWS-NEXT: %1 = load i32, {{i32\*|ptr}} @__llvm_profile_runtime
-WINDOWS-NEXT: ret i32 %1
-WINDOWS-NEXT: }
-
-CHECK: attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
-WINDOWS: attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
+++ /dev/null
-pub fn will_be_called() -> &'static str {
- let val = "called";
- println!("{}", val);
- val
-}
-
-pub fn will_not_be_called() -> bool {
- println!("should not have been called");
- false
-}
-
-pub fn print<T>(left: &str, value: T, right: &str)
-where
- T: std::fmt::Display,
-{
- println!("{}{}{}", left, value, right);
-}
-
-pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
-where
- F: FnOnce(&T)
-{
- if should_wrap {
- wrapper(&inner)
- }
-}
-
-fn main() {
- let less = 1;
- let more = 100;
-
- if less < more {
- wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
- wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
- } else {
- wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
- }
-}
+++ /dev/null
-# needs-profiler-support
-# ignore-windows-gnu
-
-# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
-# corresponding with LLVM versions 12 and 13, respectively.
-# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
-# version during testing, with an additional directive at the top of this file
-# that sets, for example: `min-llvm-version: 12.0`
-
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
--include ../coverage/coverage_tools.mk
-
-BASEDIR=../coverage-reports
-SOURCEDIR=../coverage
-
-# The `llvm-cov show` flag `--debug`, used to generate the `counters` output files, is only
-# enabled if LLVM assertions are enabled. This requires Rust config `llvm/optimize` and not
-# `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting
-# `NO_LLVM_ASSERTIONS=1`), so the tests must still pass even if the `--debug` flag is
-# not supported. (Note that `counters` files are only produced in the `$(TMPDIR)`
-# directory, for inspection and debugging support. They are *not* copied to `expected_*`
-# files when `--bless`ed.)
-LLVM_COV_DEBUG := $(shell \
- "$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \
- grep -q "Unknown command line argument '--debug'"; \
- echo $$?)
-ifeq ($(LLVM_COV_DEBUG), 1)
-DEBUG_FLAG=--debug
-endif
-
-# FIXME(richkadel): I'm adding `--ignore-filename-regex=` line(s) for specific test(s) that produce
-# `llvm-cov` results for multiple files (for example `uses_crate.rs` and `used_crate/mod.rs`) as a
-# workaround for two problems causing tests to fail on Windows:
-#
-# 1. When multiple files appear in the `llvm-cov show` results, each file's coverage results can
-# appear in different a different order. Whether this is random or, somehow, platform-specific,
-# the Windows output flips the order of the files, compared to Linux. In the `uses_crate.rs`
-# test, the only test-unique (interesting) results we care about are the results for only one
-# of the two files, `mod/uses_crate.rs`, so the workaround is to ignore all but this one file.
-# In the future, we may want a more sophisticated solution that splits apart `llvm-cov show`
-# results into separate results files for each result (taking care not to create new file
-# paths that might be too long for Windows MAX_PATH limits when creating these new sub-results,
-# as well).
-# 2. When multiple files appear in the `llvm-cov show` results, the results for each file are
-# prefixed with their filename, including platform-specific path separators (`\` for Windows,
-# and `/` everywhere else). This could be filtered or normalized of course, but by ignoring
-# coverage results for all but one of the file, the filenames are no longer included anyway.
-# If this changes (if/when we decide to support `llvm-cov show` results for multiple files),
-# the file path separator differences may need to be addressed.
-#
-# Since this is only a workaround, I decided to implement the override by adding an option for
-# each file to be ignored, using a `--ignore-filename-regex=` entry for each one, rather than
-# implement some more sophisticated solution with a new custom test directive in the test file
-# itself (similar to `expect-exit-status`) because that would add a lot of complexity and still
-# be a workaround, with the same result, with no benefit.
-#
-# Yes these `--ignore-filename-regex=` options are included in all invocations of `llvm-cov show`
-# for now, but it is effectively ignored for all tests that don't include this file anyway.
-#
-# (Note that it's also possible the `_counters.<test>.txt` and `<test>.json` files (if generated)
-# may order results from multiple files inconsistently, which might also have to be accomodated
-# if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators
-# appear to be normalized to `/` in those files, thankfully.)
-LLVM_COV_IGNORE_FILES=\
- --ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)'
-
-all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
-
-# Ensure there are no `expected` results for tests that may have been removed or renamed
-.PHONY: clear_expected_if_blessed
-clear_expected_if_blessed:
-ifdef RUSTC_BLESS_TEST
- rm -f expected_*
-endif
-
--include clear_expected_if_blessed
-
-%: $(SOURCEDIR)/lib/%.rs
- # Compile the test library with coverage instrumentation
- $(RUSTC) $(SOURCEDIR)/lib/$@.rs \
- $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \
- --crate-type rlib -Cinstrument-coverage
-
-%: $(SOURCEDIR)/%.rs
- # Compile the test program with coverage instrumentation
- $(RUSTC) $(SOURCEDIR)/$@.rs \
- $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
- -L "$(TMPDIR)" -Cinstrument-coverage
-
- # Run it in order to generate some profiling data,
- # with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
- # output the coverage stats for this run.
- LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
- $(call RUN,$@) || \
- ( \
- status=$$?; \
- grep -q "^\/\/ expect-exit-status-$$status" $(SOURCEDIR)/$@.rs || \
- ( >&2 echo "program exited with an unexpected exit status: $$status"; \
- false \
- ) \
- )
-
- # Run it through rustdoc as well to cover doctests.
- # `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone
- # might result in overwritten files and failed tests, as rustdoc spawns each
- # doctest as its own process, so make sure the filename is as unique as possible.
- LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \
- $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
- $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
- -L "$(TMPDIR)" -Cinstrument-coverage \
- -Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
-
- # Postprocess the profiling data so it can be used by the llvm-cov tool
- "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
- "$(TMPDIR)"/$@*.profraw \
- -o "$(TMPDIR)"/$@.profdata
-
- # Generate a coverage report using `llvm-cov show`.
- "$(LLVM_BIN_DIR)"/llvm-cov show \
- $(DEBUG_FLAG) \
- $(LLVM_COV_IGNORE_FILES) \
- --compilation-dir=. \
- --Xdemangler="$(RUST_DEMANGLER)" \
- --show-line-counts-or-regions \
- --instr-profile="$(TMPDIR)"/$@.profdata \
- $(call BIN,"$(TMPDIR)"/$@) \
- $$( \
- for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \
- [ -x "$$file" ] && printf "%s %s " -object $$file; \
- done \
- ) \
- 2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
- | "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
- > "$(TMPDIR)"/actual_show_coverage.$@.txt || \
- ( status=$$? ; \
- >&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
- exit $$status \
- )
-
-ifdef DEBUG_FLAG
- # The first line (beginning with "Args:" contains hard-coded, build-specific
- # file paths. Strip that line and keep the remaining lines with counter debug
- # data.
- tail -n +2 "$(TMPDIR)"/show_coverage_stderr.$@.txt \
- > "$(TMPDIR)"/actual_show_coverage_counters.$@.txt
-endif
-
-ifdef RUSTC_BLESS_TEST
- cp "$(TMPDIR)"/actual_show_coverage.$@.txt \
- expected_show_coverage.$@.txt
-else
- # Compare the show coverage output (`--bless` refreshes `typical` files).
- #
- # FIXME(richkadel): None of the Rust test source samples have the
- # `// ignore-llvm-cov-show-diffs` anymore. This directive exists to work around a limitation
- # with `llvm-cov show`. When reporting coverage for multiple instantiations of a generic function,
- # with different type substitutions, `llvm-cov show` prints these in a non-deterministic order,
- # breaking the `diff` comparision.
- #
- # A partial workaround is implemented below, with `diff --ignore-matching-lines=RE`
- # to ignore each line prefixing each generic instantiation coverage code region.
- #
- # This workaround only works if the coverage counts are identical across all reported
- # instantiations. If there is no way to ensure this, you may need to apply the
- # `// ignore-llvm-cov-show-diffs` directive, and check for differences using the
- # `.json` files to validate that results have not changed. (Until then, the JSON
- # files are redundant, so there is no need to generate `expected_*.json` files or
- # compare actual JSON results.)
-
- $(DIFF) --ignore-matching-lines='^ | .*::<.*>.*:$$' --ignore-matching-lines='^ | <.*>::.*:$$' \
- expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
- ( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
- >&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
- ) || \
- ( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \
- false \
- )
-endif
+++ /dev/null
- 1| |#![feature(c_unwind)]
- 2| |#![allow(unused_assignments)]
- 3| |
- 4| 12|extern "C" fn might_abort(should_abort: bool) {
- 5| 12| if should_abort {
- 6| 0| println!("aborting...");
- 7| 0| panic!("panics and aborts");
- 8| 12| } else {
- 9| 12| println!("Don't Panic");
- 10| 12| }
- 11| 12|}
- 12| |
- 13| 1|fn main() -> Result<(), u8> {
- 14| 1| let mut countdown = 10;
- 15| 11| while countdown > 0 {
- 16| 10| if countdown < 5 {
- 17| 4| might_abort(false);
- 18| 6| }
- 19| | // See discussion (below the `Notes` section) on coverage results for the closing brace.
- 20| 10| if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
- ^4 ^6
- 21| | // For the following example, the closing brace is the last character on the line.
- 22| | // This shows the character after the closing brace is highlighted, even if that next
- 23| | // character is a newline.
- 24| 10| if countdown < 5 { might_abort(false); }
- ^4 ^6
- 25| 10| countdown -= 1;
- 26| | }
- 27| 1| Ok(())
- 28| 1|}
- 29| |
- 30| |// Notes:
- 31| |// 1. Compare this program and its coverage results to those of the similar tests
- 32| |// `panic_unwind.rs` and `try_error_result.rs`.
- 33| |// 2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
- 34| |// 3. The test does not invoke the abort. By executing to a successful completion, the coverage
- 35| |// results show where the program did and did not execute.
- 36| |// 4. If the program actually aborted, the coverage counters would not be saved (which "works as
- 37| |// intended"). Coverage results would show no executed coverage regions.
- 38| |// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
- 39| |// (on Linux at least).
- 40| |
- 41| |/*
- 42| |
- 43| |Expect the following coverage results:
- 44| |
- 45| |```text
- 46| | 16| 11| while countdown > 0 {
- 47| | 17| 10| if countdown < 5 {
- 48| | 18| 4| might_abort(false);
- 49| | 19| 6| }
- 50| |```
- 51| |
- 52| |This is actually correct.
- 53| |
- 54| |The condition `countdown < 5` executed 10 times (10 loop iterations).
- 55| |
- 56| |It evaluated to `true` 4 times, and executed the `might_abort()` call.
- 57| |
- 58| |It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
- 59| |`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
- 60| |closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
- 61| |non-true condition.
- 62| |
- 63| |As another example of why this is important, say the condition was `countdown < 50`, which is always
- 64| |`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
- 65| |The closing brace would have a count of `0`, highlighting the missed coverage.
- 66| |*/
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |// expect-exit-status-101
- 3| |
- 4| 4|fn might_fail_assert(one_plus_one: u32) {
- 5| 4| println!("does 1 + 1 = {}?", one_plus_one);
- 6| 4| assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
- ^1
- 7| 3|}
- 8| |
- 9| 1|fn main() -> Result<(),u8> {
- 10| 1| let mut countdown = 10;
- 11| 11| while countdown > 0 {
- 12| 11| if countdown == 1 {
- 13| 1| might_fail_assert(3);
- 14| 10| } else if countdown < 5 {
- 15| 3| might_fail_assert(2);
- 16| 6| }
- 17| 10| countdown -= 1;
- 18| | }
- 19| 0| Ok(())
- 20| 0|}
- 21| |
- 22| |// Notes:
- 23| |// 1. Compare this program and its coverage results to those of the very similar test
- 24| |// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
- 25| |// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
- 26| |// related `assert_*!()` macro.
- 27| |// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
- 28| |// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
- 29| |// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
- 30| |// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
- 31| |// (and in many other coverage tests). The `Assert` terminator is typically generated by the
- 32| |// Rust compiler to check for runtime failures, such as numeric overflows.
-
+++ /dev/null
- 1| |#![allow(unused_assignments, dead_code)]
- 2| |
- 3| |// compile-flags: --edition=2018 -C opt-level=1
- 4| |
- 5| 1|async fn c(x: u8) -> u8 {
- 6| 1| if x == 8 {
- 7| 1| 1
- 8| | } else {
- 9| 0| 0
- 10| | }
- 11| 1|}
- 12| |
- 13| 0|async fn d() -> u8 { 1 }
- 14| |
- 15| 0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
- 16| |
- 17| 1|async fn f() -> u8 { 1 }
- 18| |
- 19| 0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
- 20| |
- 21| 1|pub async fn g(x: u8) {
- 22| 0| match x {
- 23| 0| y if e().await == y => (),
- 24| 0| y if f().await == y => (),
- 25| 0| _ => (),
- 26| | }
- 27| 0|}
- 28| |
- 29| 1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
- 30| 0| // executed (not awaited) so the open brace has a `0` count (at least when
- 31| 0| // displayed with `llvm-cov show` in color-mode).
- 32| 0| match x {
- 33| 0| y if foo().await[y] => (),
- 34| 0| _ => (),
- 35| | }
- 36| 0|}
- 37| |
- 38| 1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
- 39| 1| // (a) the function signature, counted when the function is called; and
- 40| 1| // (b) the open brace for the function body, counted once when the body is
- 41| 1| // executed asynchronously.
- 42| 1| match x {
- 43| 1| y if c(x).await == y + 1 => { d().await; }
- ^0 ^0 ^0 ^0
- 44| 1| y if f().await == y + 1 => (),
- ^0 ^0 ^0
- 45| 1| _ => (),
- 46| | }
- 47| 1|}
- 48| |
- 49| 1|fn j(x: u8) {
- 50| 1| // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
- 51| 1| fn c(x: u8) -> u8 {
- 52| 1| if x == 8 {
- 53| 1| 1 // This line appears covered, but the 1-character expression span covering the `1`
- ^0
- 54| 1| // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
- 55| 1| // `fn j()` executes the open brace for the funciton body, followed by the function's
- 56| 1| // first executable statement, `match x`. Inner function declarations are not
- 57| 1| // "visible" to the MIR for `j()`, so the code region counts all lines between the
- 58| 1| // open brace and the first statement as executed, which is, in a sense, true.
- 59| 1| // `llvm-cov show` overcomes this kind of situation by showing the actual counts
- 60| 1| // of the enclosed coverages, (that is, the `1` expression was not executed, and
- 61| 1| // accurately displays a `0`).
- 62| 1| } else {
- 63| 1| 0
- 64| 1| }
- 65| 1| }
- 66| 1| fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
- ^0
- 67| 1| fn f() -> u8 { 1 }
- 68| 1| match x {
- 69| 1| y if c(x) == y + 1 => { d(); }
- ^0 ^0
- 70| 1| y if f() == y + 1 => (),
- ^0 ^0
- 71| 1| _ => (),
- 72| | }
- 73| 1|}
- 74| |
- 75| 0|fn k(x: u8) { // unused function
- 76| 0| match x {
- 77| 0| 1 => (),
- 78| 0| 2 => (),
- 79| 0| _ => (),
- 80| | }
- 81| 0|}
- 82| |
- 83| 1|fn l(x: u8) {
- 84| 1| match x {
- 85| 0| 1 => (),
- 86| 0| 2 => (),
- 87| 1| _ => (),
- 88| | }
- 89| 1|}
- 90| |
- 91| 1|async fn m(x: u8) -> u8 { x - 1 }
- ^0
- 92| |
- 93| 1|fn main() {
- 94| 1| let _ = g(10);
- 95| 1| let _ = h(9);
- 96| 1| let mut future = Box::pin(i(8));
- 97| 1| j(7);
- 98| 1| l(6);
- 99| 1| let _ = m(5);
- 100| 1| executor::block_on(future.as_mut());
- 101| 1|}
- 102| |
- 103| |mod executor {
- 104| | use core::{
- 105| | future::Future,
- 106| | pin::Pin,
- 107| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
- 108| | };
- 109| |
- 110| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
- 111| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
- 112| 1| use std::hint::unreachable_unchecked;
- 113| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
- 114| 1| |_| unsafe { unreachable_unchecked() }, // clone
- ^0
- 115| 1| |_| unsafe { unreachable_unchecked() }, // wake
- ^0
- 116| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
- ^0
- 117| 1| |_| (),
- 118| 1| );
- 119| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
- 120| 1| let mut context = Context::from_waker(&waker);
- 121| |
- 122| | loop {
- 123| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
- 124| 1| break val;
- 125| 0| }
- 126| | }
- 127| 1| }
- 128| |}
-
+++ /dev/null
- 1| |// compile-flags: --edition=2018
- 2| |
- 3| |use core::{
- 4| | future::Future,
- 5| | marker::Send,
- 6| | pin::Pin,
- 7| |};
- 8| |
- 9| 1|fn non_async_func() {
- 10| 1| println!("non_async_func was covered");
- 11| 1| let b = true;
- 12| 1| if b {
- 13| 1| println!("non_async_func println in block");
- 14| 1| }
- ^0
- 15| 1|}
- 16| |
- 17| |
- 18| |
- 19| |
- 20| 1|async fn async_func() {
- 21| 1| println!("async_func was covered");
- 22| 1| let b = true;
- 23| 1| if b {
- 24| 1| println!("async_func println in block");
- 25| 1| }
- ^0
- 26| 1|}
- 27| |
- 28| |
- 29| |
- 30| |
- 31| 1|async fn async_func_just_println() {
- 32| 1| println!("async_func_just_println was covered");
- 33| 1|}
- 34| |
- 35| 1|fn main() {
- 36| 1| println!("codecovsample::main");
- 37| 1|
- 38| 1| non_async_func();
- 39| 1|
- 40| 1| executor::block_on(async_func());
- 41| 1| executor::block_on(async_func_just_println());
- 42| 1|}
- 43| |
- 44| |mod executor {
- 45| | use core::{
- 46| | future::Future,
- 47| | pin::Pin,
- 48| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
- 49| | };
- 50| |
- 51| 2| pub fn block_on<F: Future>(mut future: F) -> F::Output {
- 52| 2| let mut future = unsafe { Pin::new_unchecked(&mut future) };
- 53| 2| use std::hint::unreachable_unchecked;
- 54| 2| static VTABLE: RawWakerVTable = RawWakerVTable::new(
- 55| 2| |_| unsafe { unreachable_unchecked() }, // clone
- ^0
- 56| 2| |_| unsafe { unreachable_unchecked() }, // wake
- ^0
- 57| 2| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
- ^0
- 58| 2| |_| (),
- 59| 2| );
- 60| 2| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
- 61| 2| let mut context = Context::from_waker(&waker);
- 62| |
- 63| | loop {
- 64| 2| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
- 65| 2| break val;
- 66| 0| }
- 67| | }
- 68| 2| }
- ------------------
- | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func::{closure#0}>>:
- | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
- | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
- | 53| 1| use std::hint::unreachable_unchecked;
- | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
- | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone
- | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake
- | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
- | 58| 1| |_| (),
- | 59| 1| );
- | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
- | 61| 1| let mut context = Context::from_waker(&waker);
- | 62| |
- | 63| | loop {
- | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
- | 65| 1| break val;
- | 66| 0| }
- | 67| | }
- | 68| 1| }
- ------------------
- | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func_just_println::{closure#0}>>:
- | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
- | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
- | 53| 1| use std::hint::unreachable_unchecked;
- | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
- | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone
- | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake
- | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
- | 58| 1| |_| (),
- | 59| 1| );
- | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
- | 61| 1| let mut context = Context::from_waker(&waker);
- | 62| |
- | 63| | loop {
- | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
- | 65| 1| break val;
- | 66| 0| }
- | 67| | }
- | 68| 1| }
- ------------------
- 69| |}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1| let is_false = ! is_true;
- 9| 1|
- 10| 1| let mut some_string = Some(String::from("the string content"));
- 11| 1| println!(
- 12| 1| "The string or alt: {}"
- 13| 1| ,
- 14| 1| some_string
- 15| 1| .
- 16| 1| unwrap_or_else
- 17| 1| (
- 18| 1| ||
- 19| 0| {
- 20| 0| let mut countdown = 0;
- 21| 0| if is_false {
- 22| 0| countdown = 10;
- 23| 0| }
- 24| 0| "alt string 1".to_owned()
- 25| 1| }
- 26| 1| )
- 27| 1| );
- 28| 1|
- 29| 1| some_string = Some(String::from("the string content"));
- 30| 1| let
- 31| 1| a
- 32| 1| =
- 33| 1| ||
- 34| 0| {
- 35| 0| let mut countdown = 0;
- 36| 0| if is_false {
- 37| 0| countdown = 10;
- 38| 0| }
- 39| 0| "alt string 2".to_owned()
- 40| | };
- 41| 1| println!(
- 42| 1| "The string or alt: {}"
- 43| 1| ,
- 44| 1| some_string
- 45| 1| .
- 46| 1| unwrap_or_else
- 47| 1| (
- 48| 1| a
- 49| 1| )
- 50| 1| );
- 51| 1|
- 52| 1| some_string = None;
- 53| 1| println!(
- 54| 1| "The string or alt: {}"
- 55| 1| ,
- 56| 1| some_string
- 57| 1| .
- 58| 1| unwrap_or_else
- 59| 1| (
- 60| 1| ||
- 61| 1| {
- 62| 1| let mut countdown = 0;
- 63| 1| if is_false {
- 64| 0| countdown = 10;
- 65| 1| }
- 66| 1| "alt string 3".to_owned()
- 67| 1| }
- 68| 1| )
- 69| 1| );
- 70| 1|
- 71| 1| some_string = None;
- 72| 1| let
- 73| 1| a
- 74| 1| =
- 75| 1| ||
- 76| 1| {
- 77| 1| let mut countdown = 0;
- 78| 1| if is_false {
- 79| 0| countdown = 10;
- 80| 1| }
- 81| 1| "alt string 4".to_owned()
- 82| | };
- 83| 1| println!(
- 84| 1| "The string or alt: {}"
- 85| 1| ,
- 86| 1| some_string
- 87| 1| .
- 88| 1| unwrap_or_else
- 89| 1| (
- 90| 1| a
- 91| 1| )
- 92| 1| );
- 93| 1|
- 94| 1| let
- 95| 1| quote_closure
- 96| 1| =
- 97| 1| |val|
- 98| 5| {
- 99| 5| let mut countdown = 0;
- 100| 5| if is_false {
- 101| 0| countdown = 10;
- 102| 5| }
- 103| 5| format!("'{}'", val)
- 104| | };
- 105| 1| println!(
- 106| 1| "Repeated, quoted string: {:?}"
- 107| 1| ,
- 108| 1| std::iter::repeat("repeat me")
- 109| 1| .take(5)
- 110| 1| .map
- 111| 1| (
- 112| 1| quote_closure
- 113| 1| )
- 114| 1| .collect::<Vec<_>>()
- 115| 1| );
- 116| 1|
- 117| 1| let
- 118| 1| _unused_closure
- 119| | =
- 120| | |
- 121| | mut countdown
- 122| | |
- 123| 0| {
- 124| 0| if is_false {
- 125| 0| countdown = 10;
- 126| 0| }
- 127| 0| "closure should be unused".to_owned()
- 128| | };
- 129| |
- 130| 1| let mut countdown = 10;
- 131| 1| let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
- ^0
- 132| |
- 133| |
- 134| 1| let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
- 135| 1| let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
- ^0
- 136| 1| let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
- ^0
- 137| |
- 138| |
- 139| |
- 140| |
- 141| 1| let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
- ^0
- 142| |
- 143| 1| let _shortish_unused_closure = | _unused_arg: u8 | {
- 144| 0| println!("not called")
- 145| 0| };
- 146| |
- 147| 1| let _as_short_unused_closure = |
- 148| | _unused_arg: u8
- 149| 0| | { println!("not called") };
- 150| |
- 151| 1| let _almost_as_short_unused_closure = |
- 152| | _unused_arg: u8
- 153| 0| | { println!("not called") }
- 154| | ;
- 155| |
- 156| |
- 157| |
- 158| |
- 159| |
- 160| 1| let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
- 161| 0|println!("not called")
- 162| | ;
- 163| |
- 164| 1| let _short_unused_closure_line_break_no_block2 =
- 165| | | _unused_arg: u8 |
- 166| 0| println!(
- 167| 0| "not called"
- 168| 0| )
- 169| | ;
- 170| |
- 171| 1| let short_used_not_covered_closure_line_break_no_block_embedded_branch =
- 172| | | _unused_arg: u8 |
- 173| 0| println!(
- 174| 0| "not called: {}",
- 175| 0| if is_true { "check" } else { "me" }
- 176| | )
- 177| | ;
- 178| |
- 179| 1| let short_used_not_covered_closure_line_break_block_embedded_branch =
- 180| 1| | _unused_arg: u8 |
- 181| 0| {
- 182| 0| println!(
- 183| 0| "not called: {}",
- 184| 0| if is_true { "check" } else { "me" }
- 185| | )
- 186| | }
- 187| | ;
- 188| |
- 189| 1| let short_used_covered_closure_line_break_no_block_embedded_branch =
- 190| 1| | _unused_arg: u8 |
- 191| 1| println!(
- 192| 1| "not called: {}",
- 193| 1| if is_true { "check" } else { "me" }
- ^0
- 194| | )
- 195| | ;
- 196| |
- 197| 1| let short_used_covered_closure_line_break_block_embedded_branch =
- 198| 1| | _unused_arg: u8 |
- 199| 1| {
- 200| 1| println!(
- 201| 1| "not called: {}",
- 202| 1| if is_true { "check" } else { "me" }
- ^0
- 203| | )
- 204| | }
- 205| | ;
- 206| |
- 207| 1| if is_false {
- 208| 0| short_used_not_covered_closure_macro(0);
- 209| 0| short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
- 210| 0| short_used_not_covered_closure_line_break_block_embedded_branch(0);
- 211| 1| }
- 212| 1| short_used_covered_closure_macro(0);
- 213| 1| short_used_covered_closure_line_break_no_block_embedded_branch(0);
- 214| 1| short_used_covered_closure_line_break_block_embedded_branch(0);
- 215| 1|}
-
+++ /dev/null
- 1| |// compile-flags: --edition=2018
- 2| |#![feature(no_coverage)]
- 3| |
- 4| |macro_rules! bail {
- 5| | ($msg:literal $(,)?) => {
- 6| | if $msg.len() > 0 {
- 7| | println!("no msg");
- 8| | } else {
- 9| | println!($msg);
- 10| | }
- 11| | return Err(String::from($msg));
- 12| | };
- 13| |}
- 14| |
- 15| |macro_rules! on_error {
- 16| | ($value:expr, $error_message:expr) => {
- 17| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
- 18| | let message = format!($error_message, e);
- 19| | if message.len() > 0 {
- 20| | println!("{}", message);
- 21| | Ok(String::from("ok"))
- 22| | } else {
- 23| | bail!("error");
- 24| | }
- 25| | })
- 26| | };
- 27| |}
- 28| |
- 29| 1|fn load_configuration_files() -> Result<String, String> {
- 30| 1| Ok(String::from("config"))
- 31| 1|}
- 32| |
- 33| 1|pub fn main() -> Result<(), String> {
- 34| 1| println!("Starting service");
- 35| 1| let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
- ^0
- 36| |
- 37| 1| let startup_delay_duration = String::from("arg");
- 38| 1| let _ = (config, startup_delay_duration);
- 39| 1| Ok(())
- 40| 1|}
-
+++ /dev/null
- 1| |// compile-flags: --edition=2018
- 2| |#![feature(no_coverage)]
- 3| |
- 4| |macro_rules! bail {
- 5| | ($msg:literal $(,)?) => {
- 6| | if $msg.len() > 0 {
- 7| | println!("no msg");
- 8| | } else {
- 9| | println!($msg);
- 10| | }
- 11| | return Err(String::from($msg));
- 12| | };
- 13| |}
- 14| |
- 15| |macro_rules! on_error {
- 16| | ($value:expr, $error_message:expr) => {
- 17| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
- 18| | let message = format!($error_message, e);
- 19| | if message.len() > 0 {
- 20| | println!("{}", message);
- 21| | Ok(String::from("ok"))
- 22| | } else {
- 23| | bail!("error");
- 24| | }
- 25| | })
- 26| | };
- 27| |}
- 28| |
- 29| 1|fn load_configuration_files() -> Result<String, String> {
- 30| 1| Ok(String::from("config"))
- 31| 1|}
- 32| |
- 33| 1|pub async fn test() -> Result<(), String> {
- 34| 1| println!("Starting service");
- 35| 1| let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
- ^0
- 36| |
- 37| 1| let startup_delay_duration = String::from("arg");
- 38| 1| let _ = (config, startup_delay_duration);
- 39| 1| Ok(())
- 40| 1|}
- 41| |
- 42| |#[no_coverage]
- 43| |fn main() {
- 44| | executor::block_on(test());
- 45| |}
- 46| |
- 47| |mod executor {
- 48| | use core::{
- 49| | future::Future,
- 50| | pin::Pin,
- 51| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
- 52| | };
- 53| |
- 54| | #[no_coverage]
- 55| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
- 56| | let mut future = unsafe { Pin::new_unchecked(&mut future) };
- 57| | use std::hint::unreachable_unchecked;
- 58| | static VTABLE: RawWakerVTable = RawWakerVTable::new(
- 59| |
- 60| | #[no_coverage]
- 61| | |_| unsafe { unreachable_unchecked() }, // clone
- 62| |
- 63| | #[no_coverage]
- 64| | |_| unsafe { unreachable_unchecked() }, // wake
- 65| |
- 66| | #[no_coverage]
- 67| | |_| unsafe { unreachable_unchecked() }, // wake_by_ref
- 68| |
- 69| | #[no_coverage]
- 70| | |_| (),
- 71| | );
- 72| | let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
- 73| | let mut context = Context::from_waker(&waker);
- 74| |
- 75| | loop {
- 76| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
- 77| | break val;
- 78| | }
- 79| | }
- 80| | }
- 81| |}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 1|fn main() {
- 4| 1| let mut countdown = 0;
- 5| 1| if true {
- 6| 1| countdown = 10;
- 7| 1| }
- ^0
- 8| |
- 9| | const B: u32 = 100;
- 10| 1| let x = if countdown > 7 {
- 11| 1| countdown -= 4;
- 12| 1| B
- 13| 0| } else if countdown > 2 {
- 14| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
- 15| 0| countdown = 0;
- 16| 0| }
- 17| 0| countdown -= 5;
- 18| 0| countdown
- 19| | } else {
- 20| 0| return;
- 21| | };
- 22| |
- 23| 1| let mut countdown = 0;
- 24| 1| if true {
- 25| 1| countdown = 10;
- 26| 1| }
- ^0
- 27| |
- 28| 1| if countdown > 7 {
- 29| 1| countdown -= 4;
- 30| 1| } else if countdown > 2 {
- ^0
- 31| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
- 32| 0| countdown = 0;
- 33| 0| }
- 34| 0| countdown -= 5;
- 35| | } else {
- 36| 0| return;
- 37| | }
- 38| |
- 39| 1| if true {
- 40| 1| let mut countdown = 0;
- 41| 1| if true {
- 42| 1| countdown = 10;
- 43| 1| }
- ^0
- 44| |
- 45| 1| if countdown > 7 {
- 46| 1| countdown -= 4;
- 47| 1| }
- 48| 0| else if countdown > 2 {
- 49| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
- 50| 0| countdown = 0;
- 51| 0| }
- 52| 0| countdown -= 5;
- 53| | } else {
- 54| 0| return;
- 55| | }
- 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
- 65| 0| countdown -= 4;
- 66| 1| } else if countdown > 2 {
- 67| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
- 68| 0| countdown = 0;
- 69| 0| }
- 70| 0| countdown -= 5;
- 71| | } else {
- 72| 1| let should_be_reachable = countdown;
- 73| 1| println!("reached");
- 74| 1| return;
- 75| | };
- 76| |
- 77| 0| let w = if countdown > 7 {
- 78| 0| countdown -= 4;
- 79| 0| } else if countdown > 2 {
- 80| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
- 81| 0| countdown = 0;
- 82| 0| }
- 83| 0| countdown -= 5;
- 84| | } else {
- 85| 0| return;
- 86| | };
- 87| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 1|fn main() {
- 4| 1| let is_true = std::env::args().len() == 1;
- 5| 1|
- 6| 1| let mut x = 0;
- 7| 11| for _ in 0..10 {
- 8| 10| match is_true {
- 9| | true => {
- 10| 10| continue;
- 11| | }
- 12| 0| _ => {
- 13| 0| x = 1;
- 14| 0| }
- 15| 0| }
- 16| 0| x = 3;
- 17| | }
- 18| 11| for _ in 0..10 {
- 19| 10| match is_true {
- 20| 0| false => {
- 21| 0| x = 1;
- 22| 0| }
- 23| | _ => {
- 24| 10| continue;
- 25| | }
- 26| | }
- 27| 0| x = 3;
- 28| | }
- 29| 11| for _ in 0..10 {
- 30| 10| match is_true {
- 31| 10| true => {
- 32| 10| x = 1;
- 33| 10| }
- 34| | _ => {
- 35| 0| continue;
- 36| | }
- 37| | }
- 38| 10| x = 3;
- 39| | }
- 40| 11| for _ in 0..10 {
- 41| 10| if is_true {
- 42| 10| continue;
- 43| 0| }
- 44| 0| x = 3;
- 45| | }
- 46| 11| for _ in 0..10 {
- 47| 10| match is_true {
- 48| 0| false => {
- 49| 0| x = 1;
- 50| 0| }
- 51| 10| _ => {
- 52| 10| let _ = x;
- 53| 10| }
- 54| | }
- 55| 10| x = 3;
- 56| | }
- 57| 1| for _ in 0..10 {
- 58| 1| match is_true {
- 59| 0| false => {
- 60| 0| x = 1;
- 61| 0| }
- 62| | _ => {
- 63| 1| break;
- 64| | }
- 65| | }
- 66| 0| x = 3;
- 67| | }
- 68| | let _ = x;
- 69| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 0|pub fn unused_pub_fn_not_in_library() {
- 4| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 0| // dependent conditions.
- 7| 0| let is_true = std::env::args().len() == 1;
- 8| 0|
- 9| 0| let mut countdown = 0;
- 10| 0| if is_true {
- 11| 0| countdown = 10;
- 12| 0| }
- 13| 0|}
- 14| |
- 15| 0|fn unused_fn() {
- 16| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 17| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 18| 0| // dependent conditions.
- 19| 0| let is_true = std::env::args().len() == 1;
- 20| 0|
- 21| 0| let mut countdown = 0;
- 22| 0| if is_true {
- 23| 0| countdown = 10;
- 24| 0| }
- 25| 0|}
- 26| |
- 27| 1|fn main() {
- 28| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 29| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 30| 1| // dependent conditions.
- 31| 1| let is_true = std::env::args().len() == 1;
- 32| 1|
- 33| 1| let mut countdown = 0;
- 34| 1| if is_true {
- 35| 1| countdown = 10;
- 36| 1| }
- ^0
- 37| 1|}
-
+++ /dev/null
-../coverage/doctest.rs:
- 1| |//! This test ensures that code from doctests is properly re-mapped.
- 2| |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
- 3| |//!
- 4| |//! Just some random code:
- 5| 1|//! ```
- 6| 1|//! if true {
- 7| |//! // this is executed!
- 8| 1|//! assert_eq!(1, 1);
- 9| |//! } else {
- 10| |//! // this is not!
- 11| 0|//! assert_eq!(1, 2);
- 12| |//! }
- 13| 1|//! ```
- 14| |//!
- 15| |//! doctest testing external code:
- 16| |//! ```
- 17| 1|//! extern crate doctest_crate;
- 18| 1|//! doctest_crate::fn_run_in_doctests(1);
- 19| 1|//! ```
- 20| |//!
- 21| |//! doctest returning a result:
- 22| 1|//! ```
- 23| 2|//! #[derive(Debug, PartialEq)]
- ^1
- ------------------
- | Unexecuted instantiation: <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::ne
- ------------------
- | <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::eq:
- | 23| 2|//! #[derive(Debug, PartialEq)]
- ------------------
- 24| 1|//! struct SomeError {
- 25| 1|//! msg: String,
- 26| 1|//! }
- 27| 1|//! let mut res = Err(SomeError { msg: String::from("a message") });
- 28| 1|//! if res.is_ok() {
- 29| 0|//! res?;
- 30| |//! } else {
- 31| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
- 32| 1|//! println!("{:?}", res);
- 33| 1|//! }
- ^0
- 34| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
- 35| 1|//! res = Ok(1);
- 36| 1|//! }
- ^0
- 37| 1|//! res = Ok(0);
- 38| |//! }
- 39| |//! // need to be explicit because rustdoc cant infer the return type
- 40| 1|//! Ok::<(), SomeError>(())
- 41| 1|//! ```
- 42| |//!
- 43| |//! doctest with custom main:
- 44| |//! ```
- 45| 1|//! fn some_func() {
- 46| 1|//! println!("called some_func()");
- 47| 1|//! }
- 48| |//!
- 49| 0|//! #[derive(Debug)]
- 50| |//! struct SomeError;
- 51| |//!
- 52| |//! extern crate doctest_crate;
- 53| |//!
- 54| 1|//! fn doctest_main() -> Result<(), SomeError> {
- 55| 1|//! some_func();
- 56| 1|//! doctest_crate::fn_run_in_doctests(2);
- 57| 1|//! Ok(())
- 58| 1|//! }
- 59| |//!
- 60| |//! // this `main` is not shown as covered, as it clashes with all the other
- 61| |//! // `main` functions that were automatically generated for doctests
- 62| |//! fn main() -> Result<(), SomeError> {
- 63| |//! doctest_main()
- 64| |//! }
- 65| |//! ```
- 66| |
- 67| |/// doctest attached to fn testing external code:
- 68| |/// ```
- 69| 1|/// extern crate doctest_crate;
- 70| 1|/// doctest_crate::fn_run_in_doctests(3);
- 71| 1|/// ```
- 72| |///
- 73| 1|fn main() {
- 74| 1| if true {
- 75| 1| assert_eq!(1, 1);
- 76| | } else {
- 77| 0| assert_eq!(1, 2);
- 78| | }
- 79| 1|}
- 80| |
- 81| |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
- 82| |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
- 83| |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
- 84| |//
- 85| |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
- 86| |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
- 87| |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
- 88| |// one character past, the `if` block's closing brace. In both cases, these are most likely off
- 89| |// by the number of characters stripped from the beginning of each doc comment line: indent
- 90| |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
- 91| |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
- 92| |// more pronounced, and show up in more places, with background color used to show some distinct
- 93| |// code regions with different coverage counts.
- 94| |//
- 95| |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
- 96| |// character stripped from the beginning of doc comment lines with a space. This will give coverage
- 97| |// results the correct column offsets, and I think it should compile correctly, but I don't know
- 98| |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
- 99| |// if the indentation changed. I don't know if there is a more viable solution.
-
-../coverage/lib/doctest_crate.rs:
- 1| |/// A function run only from within doctests
- 2| 3|pub fn fn_run_in_doctests(conditional: usize) {
- 3| 3| match conditional {
- 4| 1| 1 => assert_eq!(1, 1), // this is run,
- 5| 1| 2 => assert_eq!(1, 1), // this,
- 6| 1| 3 => assert_eq!(1, 1), // and this too
- 7| 0| _ => assert_eq!(1, 2), // however this is not
- 8| | }
- 9| 3|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |// expect-exit-status-1
- 3| |
- 4| |struct Firework {
- 5| | strength: i32,
- 6| |}
- 7| |
- 8| |impl Drop for Firework {
- 9| 2| fn drop(&mut self) {
- 10| 2| println!("BOOM times {}!!!", self.strength);
- 11| 2| }
- 12| |}
- 13| |
- 14| 1|fn main() -> Result<(),u8> {
- 15| 1| let _firecracker = Firework { strength: 1 };
- 16| 1|
- 17| 1| let _tnt = Firework { strength: 100 };
- 18| 1|
- 19| 1| if true {
- 20| 1| println!("Exiting with error...");
- 21| 1| return Err(1);
- 22| 0| }
- 23| 0|
- 24| 0| let _ = Firework { strength: 1000 };
- 25| 0|
- 26| 0| Ok(())
- 27| 1|}
- 28| |
- 29| |// Expected program output:
- 30| |// Exiting with error...
- 31| |// BOOM times 100!!!
- 32| |// BOOM times 1!!!
- 33| |// Error: 1
-
+++ /dev/null
- 1| |#![feature(generators, generator_trait)]
- 2| |
- 3| |use std::ops::{Generator, GeneratorState};
- 4| |use std::pin::Pin;
- 5| |
- 6| |// The following implementation of a function called from a `yield` statement
- 7| |// (apparently requiring the Result and the `String` type or constructor)
- 8| |// creates conditions where the `generator::StateTransform` MIR transform will
- 9| |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
- 10| |// to handle this condition, and still report dead block coverage.
- 11| 1|fn get_u32(val: bool) -> Result<u32, String> {
- 12| 1| if val { Ok(1) } else { Err(String::from("some error")) }
- ^0
- 13| 1|}
- 14| |
- 15| 1|fn main() {
- 16| 1| let is_true = std::env::args().len() == 1;
- 17| 1| let mut generator = || {
- 18| 1| yield get_u32(is_true);
- 19| 1| return "foo";
- 20| | };
- 21| |
- 22| 1| match Pin::new(&mut generator).resume(()) {
- 23| 1| GeneratorState::Yielded(Ok(1)) => {}
- 24| 0| _ => panic!("unexpected return from resume"),
- 25| | }
- 26| 1| match Pin::new(&mut generator).resume(()) {
- 27| 1| GeneratorState::Complete("foo") => {}
- 28| 0| _ => panic!("unexpected return from resume"),
- 29| | }
- 30| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |// expect-exit-status-1
- 3| |
- 4| |struct Firework<T> where T: Copy + std::fmt::Display {
- 5| | strength: T,
- 6| |}
- 7| |
- 8| |impl<T> Firework<T> where T: Copy + std::fmt::Display {
- 9| | #[inline(always)]
- 10| 3| fn set_strength(&mut self, new_strength: T) {
- 11| 3| self.strength = new_strength;
- 12| 3| }
- ------------------
- | <generics::Firework<i32>>::set_strength:
- | 10| 1| fn set_strength(&mut self, new_strength: T) {
- | 11| 1| self.strength = new_strength;
- | 12| 1| }
- ------------------
- | <generics::Firework<f64>>::set_strength:
- | 10| 2| fn set_strength(&mut self, new_strength: T) {
- | 11| 2| self.strength = new_strength;
- | 12| 2| }
- ------------------
- 13| |}
- 14| |
- 15| |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
- 16| | #[inline(always)]
- 17| 2| fn drop(&mut self) {
- 18| 2| println!("BOOM times {}!!!", self.strength);
- 19| 2| }
- ------------------
- | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
- | 17| 1| fn drop(&mut self) {
- | 18| 1| println!("BOOM times {}!!!", self.strength);
- | 19| 1| }
- ------------------
- | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
- | 17| 1| fn drop(&mut self) {
- | 18| 1| println!("BOOM times {}!!!", self.strength);
- | 19| 1| }
- ------------------
- 20| |}
- 21| |
- 22| 1|fn main() -> Result<(),u8> {
- 23| 1| let mut firecracker = Firework { strength: 1 };
- 24| 1| firecracker.set_strength(2);
- 25| 1|
- 26| 1| let mut tnt = Firework { strength: 100.1 };
- 27| 1| tnt.set_strength(200.1);
- 28| 1| tnt.set_strength(300.3);
- 29| 1|
- 30| 1| if true {
- 31| 1| println!("Exiting with error...");
- 32| 1| return Err(1);
- 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:
- 45| |// Exiting with error...
- 46| |// BOOM times 100!!!
- 47| |// BOOM times 1!!!
- 48| |// Error: 1
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let
- 8| 1| is_true
- 9| 1| =
- 10| 1| std::env::args().len()
- 11| 1| ==
- 12| 1| 1
- 13| 1| ;
- 14| 1| let
- 15| 1| mut
- 16| 1| countdown
- 17| 1| =
- 18| 1| 0
- 19| 1| ;
- 20| 1| if
- 21| 1| is_true
- 22| 1| {
- 23| 1| countdown
- 24| 1| =
- 25| 1| 10
- 26| 1| ;
- 27| 1| }
- ^0
- 28| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1|
- 9| 1| let mut countdown = 0;
- 10| 1| if
- 11| 1| is_true
- 12| 1| {
- 13| 1| countdown
- 14| 1| =
- 15| 1| 10
- 16| 1| ;
- 17| 1| }
- 18| | else // Note coverage region difference without semicolon
- 19| | {
- 20| 0| countdown
- 21| 0| =
- 22| 0| 100
- 23| | }
- 24| |
- 25| | if
- 26| 1| is_true
- 27| 1| {
- 28| 1| countdown
- 29| 1| =
- 30| 1| 10
- 31| 1| ;
- 32| 1| }
- 33| | else
- 34| 0| {
- 35| 0| countdown
- 36| 0| =
- 37| 0| 100
- 38| 0| ;
- 39| 0| }
- 40| 1|}
-
+++ /dev/null
- 1| |// Regression test for issue #98833.
- 2| |// compile-flags: -Zinline-mir -Cdebug-assertions=off
- 3| |
- 4| 1|fn main() {
- 5| 1| println!("{}", live::<false>());
- 6| 1|
- 7| 1| let f = |x: bool| {
- 8| | debug_assert!(
- 9| | x
- 10| | );
- 11| 1| };
- 12| 1| f(false);
- 13| 1|}
- 14| |
- 15| |#[inline]
- 16| 1|fn live<const B: bool>() -> u32 {
- 17| 1| if B {
- 18| 0| dead()
- 19| | } else {
- 20| 1| 0
- 21| | }
- 22| 1|}
- 23| |
- 24| |#[inline]
- 25| 0|fn dead() -> u32 {
- 26| 0| 42
- 27| 0|}
-
+++ /dev/null
- 1| |// compile-flags: -Zinline-mir
- 2| |
- 3| |use std::fmt::Display;
- 4| |
- 5| 1|fn main() {
- 6| 1| permutations(&['a', 'b', 'c']);
- 7| 1|}
- 8| |
- 9| |#[inline(always)]
- 10| 1|fn permutations<T: Copy + Display>(xs: &[T]) {
- 11| 1| let mut ys = xs.to_owned();
- 12| 1| permutate(&mut ys, 0);
- 13| 1|}
- 14| |
- 15| 16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
- 16| 16| let n = length(xs);
- 17| 16| if k == n {
- 18| 6| display(xs);
- 19| 10| } else if k < n {
- 20| 15| for i in k..n {
- ^10
- 21| 15| swap(xs, i, k);
- 22| 15| permutate(xs, k + 1);
- 23| 15| swap(xs, i, k);
- 24| 15| }
- 25| 0| } else {
- 26| 0| error();
- 27| 0| }
- 28| 16|}
- 29| |
- 30| 16|fn length<T>(xs: &[T]) -> usize {
- 31| 16| xs.len()
- 32| 16|}
- 33| |
- 34| |#[inline]
- 35| 30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
- 36| 30| let t = xs[i];
- 37| 30| xs[i] = xs[j];
- 38| 30| xs[j] = t;
- 39| 30|}
- 40| |
- 41| 6|fn display<T: Display>(xs: &[T]) {
- 42| 24| for x in xs {
- ^18
- 43| 18| print!("{}", x);
- 44| 18| }
- 45| 6| println!();
- 46| 6|}
- 47| |
- 48| |#[inline(always)]
- 49| 0|fn error() {
- 50| 0| panic!("error");
- 51| 0|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables, dead_code)]
- 2| |
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1|
- 9| 1| let mut countdown = 0;
- 10| 1| if is_true {
- 11| 1| countdown = 10;
- 12| 1| }
- ^0
- 13| |
- 14| | mod in_mod {
- 15| | const IN_MOD_CONST: u32 = 1000;
- 16| | }
- 17| |
- 18| 3| fn in_func(a: u32) {
- 19| 3| let b = 1;
- 20| 3| let c = a + b;
- 21| 3| println!("c = {}", c)
- 22| 3| }
- 23| |
- 24| | struct InStruct {
- 25| | in_struct_field: u32,
- 26| | }
- 27| |
- 28| | const IN_CONST: u32 = 1234;
- 29| |
- 30| | trait InTrait {
- 31| | fn trait_func(&mut self, incr: u32);
- 32| |
- 33| 1| fn default_trait_func(&mut self) {
- 34| 1| in_func(IN_CONST);
- 35| 1| self.trait_func(IN_CONST);
- 36| 1| }
- 37| | }
- 38| |
- 39| | impl InTrait for InStruct {
- 40| 1| fn trait_func(&mut self, incr: u32) {
- 41| 1| self.in_struct_field += incr;
- 42| 1| in_func(self.in_struct_field);
- 43| 1| }
- 44| | }
- 45| |
- 46| | type InType = String;
- 47| |
- 48| 1| if is_true {
- 49| 1| in_func(countdown);
- 50| 1| }
- ^0
- 51| |
- 52| 1| let mut val = InStruct {
- 53| 1| in_struct_field: 101,
- 54| 1| };
- 55| 1|
- 56| 1| val.default_trait_func();
- 57| 1|}
-
+++ /dev/null
- 1| |// Shows that rust-lang/rust/83601 is resolved
- 2| |
- 3| 3|#[derive(Debug, PartialEq, Eq)]
- ^2
- ------------------
- | <issue_83601::Foo as core::cmp::PartialEq>::eq:
- | 3| 2|#[derive(Debug, PartialEq, Eq)]
- ------------------
- | Unexecuted instantiation: <issue_83601::Foo as core::cmp::PartialEq>::ne
- ------------------
- 4| |struct Foo(u32);
- 5| |
- 6| 1|fn main() {
- 7| 1| let bar = Foo(1);
- 8| 1| assert_eq!(bar, Foo(1));
- 9| 1| let baz = Foo(0);
- 10| 1| assert_ne!(baz, Foo(1));
- 11| 1| println!("{:?}", Foo(1));
- 12| 1| println!("{:?}", bar);
- 13| 1| println!("{:?}", baz);
- 14| 1|}
-
+++ /dev/null
- 1| |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
- 2| |
- 3| |// expect-exit-status-101
- 4| 21|#[derive(PartialEq, Eq)]
- ------------------
- | <issue_84561::Foo as core::cmp::PartialEq>::eq:
- | 4| 21|#[derive(PartialEq, Eq)]
- ------------------
- | Unexecuted instantiation: <issue_84561::Foo as core::cmp::PartialEq>::ne
- ------------------
- 5| |struct Foo(u32);
- 6| 1|fn test3() {
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1| let bar = Foo(1);
- 9| 1| assert_eq!(bar, Foo(1));
- 10| 1| let baz = Foo(0);
- 11| 1| assert_ne!(baz, Foo(1));
- 12| 1| println!("{:?}", Foo(1));
- 13| 1| println!("{:?}", bar);
- 14| 1| println!("{:?}", baz);
- 15| 1|
- 16| 1| assert_eq!(Foo(1), Foo(1));
- 17| 1| assert_ne!(Foo(0), Foo(1));
- 18| 1| assert_eq!(Foo(2), Foo(2));
- 19| 1| let bar = Foo(0);
- 20| 1| assert_ne!(bar, Foo(3));
- 21| 1| assert_ne!(Foo(0), Foo(4));
- 22| 1| assert_eq!(Foo(3), Foo(3), "with a message");
- ^0
- 23| 1| println!("{:?}", bar);
- 24| 1| println!("{:?}", Foo(1));
- 25| 1|
- 26| 1| assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
- ^0 ^0 ^0
- 27| 1| assert_ne!(
- 28| | Foo(0)
- 29| | ,
- 30| | Foo(5)
- 31| | ,
- 32| 0| "{}"
- 33| 0| ,
- 34| 0| if
- 35| 0| is_true
- 36| | {
- 37| 0| "true message"
- 38| | } else {
- 39| 0| "false message"
- 40| | }
- 41| | );
- 42| |
- 43| 1| let is_true = std::env::args().len() == 1;
- 44| 1|
- 45| 1| assert_eq!(
- 46| 1| Foo(1),
- 47| 1| Foo(1)
- 48| 1| );
- 49| 1| assert_ne!(
- 50| 1| Foo(0),
- 51| 1| Foo(1)
- 52| 1| );
- 53| 1| assert_eq!(
- 54| 1| Foo(2),
- 55| 1| Foo(2)
- 56| 1| );
- 57| 1| let bar = Foo(1);
- 58| 1| assert_ne!(
- 59| 1| bar,
- 60| 1| Foo(3)
- 61| 1| );
- 62| 1| if is_true {
- 63| 1| assert_ne!(
- 64| 1| Foo(0),
- 65| 1| Foo(4)
- 66| 1| );
- 67| | } else {
- 68| 0| assert_eq!(
- 69| 0| Foo(3),
- 70| 0| Foo(3)
- 71| 0| );
- 72| | }
- 73| 1| if is_true {
- 74| 1| assert_ne!(
- 75| | Foo(0),
- 76| | Foo(4),
- 77| 0| "with a message"
- 78| | );
- 79| | } else {
- 80| 0| assert_eq!(
- 81| | Foo(3),
- 82| | Foo(3),
- 83| 0| "with a message"
- 84| | );
- 85| | }
- 86| 1| assert_ne!(
- 87| 1| if is_true {
- 88| 1| Foo(0)
- 89| | } else {
- 90| 0| Foo(1)
- 91| | },
- 92| | Foo(5)
- 93| | );
- 94| 1| assert_ne!(
- 95| 1| Foo(5),
- 96| 1| if is_true {
- 97| 1| Foo(0)
- 98| | } else {
- 99| 0| Foo(1)
- 100| | }
- 101| | );
- 102| 1| assert_ne!(
- 103| 1| if is_true {
- 104| 1| assert_eq!(
- 105| 1| Foo(3),
- 106| 1| Foo(3)
- 107| 1| );
- 108| 1| Foo(0)
- 109| | } else {
- 110| 0| assert_ne!(
- 111| 0| if is_true {
- 112| 0| Foo(0)
- 113| | } else {
- 114| 0| Foo(1)
- 115| | },
- 116| | Foo(5)
- 117| | );
- 118| 0| Foo(1)
- 119| | },
- 120| | Foo(5),
- 121| 0| "with a message"
- 122| | );
- 123| 1| assert_eq!(
- 124| | Foo(1),
- 125| | Foo(3),
- 126| 1| "this assert should fail"
- 127| | );
- 128| 0| assert_eq!(
- 129| | Foo(3),
- 130| | Foo(3),
- 131| 0| "this assert should not be reached"
- 132| | );
- 133| 0|}
- 134| |
- 135| |impl std::fmt::Debug for Foo {
- 136| | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- 137| 7| write!(f, "try and succeed")?;
- ^0
- 138| 7| Ok(())
- 139| 7| }
- 140| |}
- 141| |
- 142| |static mut DEBUG_LEVEL_ENABLED: bool = false;
- 143| |
- 144| |macro_rules! debug {
- 145| | ($($arg:tt)+) => (
- 146| | if unsafe { DEBUG_LEVEL_ENABLED } {
- 147| | println!($($arg)+);
- 148| | }
- 149| | );
- 150| |}
- 151| |
- 152| 1|fn test1() {
- 153| 1| debug!("debug is enabled");
- ^0
- 154| 1| debug!("debug is enabled");
- ^0
- 155| 1| let _ = 0;
- 156| 1| debug!("debug is enabled");
- ^0
- 157| 1| unsafe {
- 158| 1| DEBUG_LEVEL_ENABLED = true;
- 159| 1| }
- 160| 1| debug!("debug is enabled");
- 161| 1|}
- 162| |
- 163| |macro_rules! call_debug {
- 164| | ($($arg:tt)+) => (
- 165| 1| fn call_print(s: &str) {
- 166| 1| print!("{}", s);
- 167| 1| }
- 168| |
- 169| | call_print("called from call_debug: ");
- 170| | debug!($($arg)+);
- 171| | );
- 172| |}
- 173| |
- 174| 1|fn test2() {
- 175| 1| call_debug!("debug is enabled");
- 176| 1|}
- 177| |
- 178| 1|fn main() {
- 179| 1| test1();
- 180| 1| test2();
- 181| 1| test3();
- 182| 1|}
-
+++ /dev/null
-../coverage/issue-85461.rs:
- 1| |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
- 2| |
- 3| |extern crate inline_always_with_dead_code;
- 4| |
- 5| |use inline_always_with_dead_code::{bar, baz};
- 6| |
- 7| 1|fn main() {
- 8| 1| bar::call_me();
- 9| 1| baz::call_me();
- 10| 1|}
-
-../coverage/lib/inline_always_with_dead_code.rs:
- 1| |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
- 2| |
- 3| |#![allow(dead_code)]
- 4| |
- 5| |mod foo {
- 6| | #[inline(always)]
- 7| 2| pub fn called() { }
- 8| |
- 9| 0| fn uncalled() { }
- 10| |}
- 11| |
- 12| |pub mod bar {
- 13| 1| pub fn call_me() {
- 14| 1| super::foo::called();
- 15| 1| }
- 16| |}
- 17| |
- 18| |pub mod baz {
- 19| 1| pub fn call_me() {
- 20| 1| super::foo::called();
- 21| 1| }
- 22| |}
-
+++ /dev/null
- 1| |// Regression test for #93054: Functions using uninhabited types often only have a single,
- 2| |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
- 3| |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
- 4| |
- 5| |// compile-flags: --edition=2021
- 6| |
- 7| |enum Never { }
- 8| |
- 9| |impl Never {
- 10| | fn foo(self) {
- 11| | match self { }
- 12| | make().map(|never| match never { });
- 13| | }
- 14| |
- 15| | fn bar(&self) {
- 16| | match *self { }
- 17| | }
- 18| |}
- 19| |
- 20| 0|async fn foo2(never: Never) {
- 21| | match never { }
- 22| |}
- 23| |
- 24| 0|fn make() -> Option<Never> {
- 25| 0| None
- 26| 0|}
- 27| |
- 28| 1|fn main() { }
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1|
- 9| 1| let (mut a, mut b, mut c) = (0, 0, 0);
- 10| 1| if is_true {
- 11| 1| a = 1;
- 12| 1| b = 10;
- 13| 1| c = 100;
- 14| 1| }
- ^0
- 15| | let
- 16| 1| somebool
- 17| | =
- 18| 1| a < b
- 19| | ||
- 20| 0| b < c
- 21| | ;
- 22| | let
- 23| 1| somebool
- 24| | =
- 25| 1| b < a
- 26| | ||
- 27| 1| b < c
- 28| | ;
- 29| 1| let somebool = a < b && b < c;
- 30| 1| let somebool = b < a && b < c;
- ^0
- 31| |
- 32| | if
- 33| 1| !
- 34| 1| is_true
- 35| 0| {
- 36| 0| a = 2
- 37| 0| ;
- 38| 1| }
- 39| |
- 40| | if
- 41| 1| is_true
- 42| 1| {
- 43| 1| b = 30
- 44| 1| ;
- 45| 1| }
- 46| | else
- 47| 0| {
- 48| 0| c = 400
- 49| 0| ;
- 50| 0| }
- 51| |
- 52| 1| if !is_true {
- 53| 0| a = 2;
- 54| 1| }
- 55| |
- 56| 1| if is_true {
- 57| 1| b = 30;
- 58| 1| } else {
- 59| 0| c = 400;
- 60| 0| }
- 61| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 1|fn main() {
- 4| 1| let result
- 5| 1| =
- 6| 1| loop
- 7| 1| {
- 8| 1| break
- 9| 1| 10
- 10| 1| ;
- 11| 1| }
- 12| 1| ;
- 13| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables, while_true)]
- 2| |
- 3| |// This test confirms that (1) unexecuted infinite loops are handled correctly by the
- 4| |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
- 5| |
- 6| |struct DebugTest;
- 7| |
- 8| |impl std::fmt::Debug for DebugTest {
- 9| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- 10| 1| if true {
- 11| 1| if false {
- 12| 0| while true {
- 13| 0| }
- 14| 1| }
- 15| 1| write!(f, "cool")?;
- ^0
- 16| 0| } else {
- 17| 0| }
- 18| |
- 19| 11| for i in 0..10 {
- ^10
- 20| 10| if true {
- 21| 10| if false {
- 22| 0| while true {}
- 23| 10| }
- 24| 10| write!(f, "cool")?;
- ^0
- 25| 0| } else {
- 26| 0| }
- 27| | }
- 28| 1| Ok(())
- 29| 1| }
- 30| |}
- 31| |
- 32| |struct DisplayTest;
- 33| |
- 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| 0| } else {
- 38| 1| if false {
- 39| 0| while true {}
- 40| 1| }
- 41| 1| write!(f, "cool")?;
- ^0
- 42| | }
- 43| 11| for i in 0..10 {
- ^10
- 44| 10| if false {
- 45| 0| } else {
- 46| 10| if false {
- 47| 0| while true {}
- 48| 10| }
- 49| 10| write!(f, "cool")?;
- ^0
- 50| | }
- 51| | }
- 52| 1| Ok(())
- 53| 1| }
- 54| |}
- 55| |
- 56| 1|fn main() {
- 57| 1| let debug_test = DebugTest;
- 58| 1| println!("{:?}", debug_test);
- 59| 1| let display_test = DisplayTest;
- 60| 1| println!("{}", display_test);
- 61| 1|}
-
+++ /dev/null
- 1| |#![feature(or_patterns)]
- 2| |
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1|
- 9| 1| let mut a: u8 = 0;
- 10| 1| let mut b: u8 = 0;
- 11| 1| if is_true {
- 12| 1| a = 2;
- 13| 1| b = 0;
- 14| 1| }
- ^0
- 15| 1| match (a, b) {
- 16| | // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
- 17| | // This test confirms a fix for Issue #79569.
- 18| 0| (0 | 1, 2 | 3) => {}
- 19| 1| _ => {}
- 20| | }
- 21| 1| if is_true {
- 22| 1| a = 0;
- 23| 1| b = 0;
- 24| 1| }
- ^0
- 25| 1| match (a, b) {
- 26| 0| (0 | 1, 2 | 3) => {}
- 27| 1| _ => {}
- 28| | }
- 29| 1| if is_true {
- 30| 1| a = 2;
- 31| 1| b = 2;
- 32| 1| }
- ^0
- 33| 1| match (a, b) {
- 34| 0| (0 | 1, 2 | 3) => {}
- 35| 1| _ => {}
- 36| | }
- 37| 1| if is_true {
- 38| 1| a = 0;
- 39| 1| b = 2;
- 40| 1| }
- ^0
- 41| 1| match (a, b) {
- 42| 1| (0 | 1, 2 | 3) => {}
- 43| 0| _ => {}
- 44| | }
- 45| 1|}
-
+++ /dev/null
- 1| 1|fn main() {
- 2| 1| let is_true = std::env::args().len() == 1;
- 3| 1| let mut countdown = 10;
- 4| |
- 5| 1| 'outer: while countdown > 0 {
- 6| 1| let mut a = 100;
- 7| 1| let mut b = 100;
- 8| 3| for _ in 0..50 {
- 9| 3| if a < 30 {
- 10| 0| break;
- 11| 3| }
- 12| 3| a -= 5;
- 13| 3| b -= 5;
- 14| 3| if b < 90 {
- 15| 1| a -= 10;
- 16| 1| if is_true {
- 17| 1| break 'outer;
- 18| 0| } else {
- 19| 0| a -= 2;
- 20| 0| }
- 21| 2| }
- 22| | }
- 23| 0| countdown -= 1;
- 24| | }
- 25| 1|}
-
+++ /dev/null
- 1| |// Enables `no_coverage` on the entire crate
- 2| |#![feature(no_coverage)]
- 3| |
- 4| |#[no_coverage]
- 5| |fn do_not_add_coverage_1() {
- 6| | println!("called but not covered");
- 7| |}
- 8| |
- 9| |fn do_not_add_coverage_2() {
- 10| | #![no_coverage]
- 11| | println!("called but not covered");
- 12| |}
- 13| |
- 14| |#[no_coverage]
- 15| |fn do_not_add_coverage_not_called() {
- 16| | println!("not called and not covered");
- 17| |}
- 18| |
- 19| 1|fn add_coverage_1() {
- 20| 1| println!("called and covered");
- 21| 1|}
- 22| |
- 23| 1|fn add_coverage_2() {
- 24| 1| println!("called and covered");
- 25| 1|}
- 26| |
- 27| 0|fn add_coverage_not_called() {
- 28| 0| println!("not called but covered");
- 29| 0|}
- 30| |
- 31| |// FIXME: These test-cases illustrate confusing results of nested functions.
- 32| |// See https://github.com/rust-lang/rust/issues/93319
- 33| |mod nested_fns {
- 34| | #[no_coverage]
- 35| | pub fn outer_not_covered(is_true: bool) {
- 36| 1| fn inner(is_true: bool) {
- 37| 1| if is_true {
- 38| 1| println!("called and covered");
- 39| 1| } else {
- 40| 0| println!("absolutely not covered");
- 41| 0| }
- 42| 1| }
- 43| | println!("called but not covered");
- 44| | inner(is_true);
- 45| | }
- 46| |
- 47| 1| pub fn outer(is_true: bool) {
- 48| 1| println!("called and covered");
- 49| 1| inner_not_covered(is_true);
- 50| 1|
- 51| 1| #[no_coverage]
- 52| 1| fn inner_not_covered(is_true: bool) {
- 53| 1| if is_true {
- 54| 1| println!("called but not covered");
- 55| 1| } else {
- 56| 1| println!("absolutely not covered");
- 57| 1| }
- 58| 1| }
- 59| 1| }
- 60| |
- 61| 1| pub fn outer_both_covered(is_true: bool) {
- 62| 1| println!("called and covered");
- 63| 1| inner(is_true);
- 64| 1|
- 65| 1| fn inner(is_true: bool) {
- 66| 1| if is_true {
- 67| 1| println!("called and covered");
- 68| 1| } else {
- 69| 0| println!("absolutely not covered");
- 70| 0| }
- 71| 1| }
- 72| 1| }
- 73| |}
- 74| |
- 75| 1|fn main() {
- 76| 1| let is_true = std::env::args().len() == 1;
- 77| 1|
- 78| 1| do_not_add_coverage_1();
- 79| 1| do_not_add_coverage_2();
- 80| 1| add_coverage_1();
- 81| 1| add_coverage_2();
- 82| 1|
- 83| 1| nested_fns::outer_not_covered(is_true);
- 84| 1| nested_fns::outer(is_true);
- 85| 1| nested_fns::outer_both_covered(is_true);
- 86| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |// expect-exit-status-101
- 3| |
- 4| 4|fn might_overflow(to_add: u32) -> u32 {
- 5| 4| if to_add > 5 {
- 6| 1| println!("this will probably overflow");
- 7| 3| }
- 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|}
- 14| |
- 15| 1|fn main() -> Result<(),u8> {
- 16| 1| let mut countdown = 10;
- 17| 11| while countdown > 0 {
- 18| 11| if countdown == 1 {
- 19| 1| let result = might_overflow(10);
- 20| 1| println!("Result: {}", result);
- 21| 10| } else if countdown < 5 {
- 22| 3| let result = might_overflow(1);
- 23| 3| println!("Result: {}", result);
- 24| 6| }
- 25| 10| countdown -= 1;
- 26| | }
- 27| 0| Ok(())
- 28| 0|}
- 29| |
- 30| |// Notes:
- 31| |// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
- 32| |// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
- 33| |// 2. This test confirms the coverage generated when a program passes or fails a
- 34| |// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
- 35| |// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
- 36| |// compiler-generated assertion failures are assumed to be a symptom of a program bug, not
- 37| |// expected behavior. To simplify the coverage graphs and keep instrumented programs as
- 38| |// small and fast as possible, `Assert` terminators are assumed to always succeed, and
- 39| |// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
- 40| |// get its own coverage counter.
- 41| |// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
- 42| |// In this test, the final count for the statements after the `if` block in `might_overflow()`
- 43| |// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
- 44| |// on the MIR graph and the structure of the code, this count could have been 3 (which might
- 45| |// have been valid for the overflowed add `+`, but should have been 4 for the lines before
- 46| |// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
- 47| |// via StatementKind::Counter at the end of the block, but (as in the case in this test),
- 48| |// a CounterKind::Expression is always evaluated. In this case, the expression was based on
- 49| |// a `Counter` incremented as part of the evaluation of the `if` expression, which was
- 50| |// executed, and counted, 4 times, before reaching the overflow add.
- 51| |
- 52| |// If the program did not overflow, the coverage for `might_overflow()` would look like this:
- 53| |//
- 54| |// 4| |fn might_overflow(to_add: u32) -> u32 {
- 55| |// 5| 4| if to_add > 5 {
- 56| |// 6| 0| println!("this will probably overflow");
- 57| |// 7| 4| }
- 58| |// 8| 4| let add_to = u32::MAX - 5;
- 59| |// 9| 4| println!("does {} + {} overflow?", add_to, to_add);
- 60| |// 10| 4| let result = to_add + add_to;
- 61| |// 11| 4| println!("continuing after overflow check");
- 62| |// 12| 4| result
- 63| |// 13| 4|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |// expect-exit-status-101
- 3| |
- 4| 4|fn might_panic(should_panic: bool) {
- 5| 4| if should_panic {
- 6| 1| println!("panicking...");
- 7| 1| panic!("panics");
- 8| 3| } else {
- 9| 3| println!("Don't Panic");
- 10| 3| }
- 11| 3|}
- 12| |
- 13| 1|fn main() -> Result<(), u8> {
- 14| 1| let mut countdown = 10;
- 15| 11| while countdown > 0 {
- 16| 11| if countdown == 1 {
- 17| 1| might_panic(true);
- 18| 10| } else if countdown < 5 {
- 19| 3| might_panic(false);
- 20| 6| }
- 21| 10| countdown -= 1;
- 22| | }
- 23| 0| Ok(())
- 24| 0|}
- 25| |
- 26| |// Notes:
- 27| |// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
- 28| |// `try_error_result.rs`.
- 29| |// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
- 30| |// normal program exit cleanup, including writing out the current values of the coverage
- 31| |// counters.
-
+++ /dev/null
- 1| |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
- 2| |// structure of this test.
- 3| |
- 4| 2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
- ^0 ^0 ^0 ^1 ^1 ^0^0
- ------------------
- | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::ne
- ------------------
- | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::eq
- ------------------
- 5| |pub struct Version {
- 6| | major: usize,
- 7| | minor: usize,
- 8| | patch: usize,
- 9| |}
- 10| |
- 11| |impl Version {
- 12| 2| pub fn new(major: usize, minor: usize, patch: usize) -> Self {
- 13| 2| Self {
- 14| 2| major,
- 15| 2| minor,
- 16| 2| patch,
- 17| 2| }
- 18| 2| }
- 19| |}
- 20| |
- 21| 1|fn main() {
- 22| 1| let version_3_2_1 = Version::new(3, 2, 1);
- 23| 1| let version_3_3_0 = Version::new(3, 3, 0);
- 24| 1|
- 25| 1| println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
- 26| 1|}
- 27| |
- 28| |/*
- 29| |
- 30| |This test verifies a bug was fixed that otherwise generated this error:
- 31| |
- 32| |thread 'rustc' panicked at 'No counters provided the source_hash for function:
- 33| | Instance {
- 34| | def: Item(WithOptConstParam {
- 35| | did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
- 36| | const_param_did: None
- 37| | }),
- 38| | substs: []
- 39| | }'
- 40| |The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
- 41| |without a code region associated with any `Counter`. Code regions were associated with at least
- 42| |one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
- 43| |(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
- 44| |`function_source_hash` without a code region, if necessary.
- 45| |
- 46| |*/
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1|
- 9| 1| let mut countdown = 0;
- 10| 1|
- 11| 1| if
- 12| 1| is_true
- 13| 1| {
- 14| 1| countdown
- 15| 1| =
- 16| 1| 10
- 17| 1| ;
- 18| 1| }
- ^0
- 19| |
- 20| | loop
- 21| | {
- 22| | if
- 23| 11| countdown
- 24| 11| ==
- 25| 11| 0
- 26| | {
- 27| 1| break
- 28| | ;
- 29| 10| }
- 30| 10| countdown
- 31| 10| -=
- 32| 10| 1
- 33| | ;
- 34| | }
- 35| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| 1|fn main() {
- 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 6| 1| // dependent conditions.
- 7| 1| let is_true = std::env::args().len() == 1;
- 8| 1|
- 9| 1| let mut countdown = 1;
- 10| 1| if is_true {
- 11| 1| countdown = 0;
- 12| 1| }
- ^0
- 13| |
- 14| | for
- 15| | _
- 16| | in
- 17| 3| 0..2
- 18| | {
- 19| | let z
- 20| | ;
- 21| | match
- 22| 2| countdown
- 23| | {
- 24| 1| x
- 25| | if
- 26| 2| x
- 27| 2| <
- 28| 2| 1
- 29| | =>
- 30| 1| {
- 31| 1| z = countdown
- 32| 1| ;
- 33| 1| let y = countdown
- 34| 1| ;
- 35| 1| countdown = 10
- 36| 1| ;
- 37| 1| }
- 38| | _
- 39| | =>
- 40| 1| {}
- 41| | }
- 42| | }
- 43| 1|}
-
+++ /dev/null
- 1| 1|fn main() {
- 2| 1| if false {
- 3| 0| loop {}
- 4| 1| }
- 5| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |// expect-exit-status-1
- 3| |
- 4| 6|fn call(return_error: bool) -> Result<(),()> {
- 5| 6| if return_error {
- 6| 1| Err(())
- 7| | } else {
- 8| 5| Ok(())
- 9| | }
- 10| 6|}
- 11| |
- 12| 1|fn test1() -> Result<(),()> {
- 13| 1| let mut
- 14| 1| countdown = 10
- 15| | ;
- 16| | for
- 17| | _
- 18| | in
- 19| 6| 0..10
- 20| | {
- 21| 6| countdown
- 22| 6| -= 1
- 23| 6| ;
- 24| 6| if
- 25| 6| countdown < 5
- 26| | {
- 27| 1| call(/*return_error=*/ true)?;
- 28| 0| call(/*return_error=*/ false)?;
- 29| | }
- 30| | else
- 31| | {
- 32| 5| call(/*return_error=*/ false)?;
- ^0
- 33| | }
- 34| | }
- 35| 0| Ok(())
- 36| 1|}
- 37| |
- 38| |struct Thing1;
- 39| |impl Thing1 {
- 40| 18| fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
- 41| 18| if return_error {
- 42| 1| Err(())
- 43| | } else {
- 44| 17| Ok(Thing2{})
- 45| | }
- 46| 18| }
- 47| |}
- 48| |
- 49| |struct Thing2;
- 50| |impl Thing2 {
- 51| 17| fn call(&self, return_error: bool) -> Result<u32,()> {
- 52| 17| if return_error {
- 53| 2| Err(())
- 54| | } else {
- 55| 15| Ok(57)
- 56| | }
- 57| 17| }
- 58| |}
- 59| |
- 60| 1|fn test2() -> Result<(),()> {
- 61| 1| let thing1 = Thing1{};
- 62| 1| let mut
- 63| 1| countdown = 10
- 64| | ;
- 65| | for
- 66| | _
- 67| | in
- 68| 6| 0..10
- 69| | {
- 70| 6| countdown
- 71| 6| -= 1
- 72| 6| ;
- 73| 6| if
- 74| 6| countdown < 5
- 75| | {
- 76| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
- ^0
- 77| 1| thing1
- 78| 1| .
- 79| 1| get_thing_2(/*return_error=*/ false)
- 80| 0| ?
- 81| | .
- 82| 1| call(/*return_error=*/ true)
- 83| 1| .
- 84| 1| expect_err(
- 85| 1| "call should fail"
- 86| 1| );
- 87| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
- ^0 ^0 ^0
- 88| 0| assert_eq!(val, 57);
- 89| 0| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
- 90| 0| assert_eq!(val, 57);
- 91| | }
- 92| | else
- 93| | {
- 94| 5| let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
- ^0 ^0
- 95| 5| assert_eq!(val, 57);
- 96| 5| let val = thing1
- 97| 5| .get_thing_2(/*return_error=*/ false)?
- ^0
- 98| 5| .call(/*return_error=*/ false)?;
- ^0
- 99| 5| assert_eq!(val, 57);
- 100| 5| let val = thing1
- 101| 5| .get_thing_2(/*return_error=*/ false)
- 102| 0| ?
- 103| 5| .call(/*return_error=*/ false)
- 104| 0| ?
- 105| | ;
- 106| 5| assert_eq!(val, 57);
- 107| | }
- 108| | }
- 109| 0| Ok(())
- 110| 1|}
- 111| |
- 112| 1|fn main() -> Result<(),()> {
- 113| 1| test1().expect_err("test1 should fail");
- 114| 1| test2()
- 115| 1| ?
- 116| | ;
- 117| 0| Ok(())
- 118| 1|}
-
+++ /dev/null
- 1| 2|fn foo<T>(x: T) {
- 2| 2| let mut i = 0;
- 3| 22| while i < 10 {
- 4| 20| i != 0 || i != 0;
- ^2
- 5| 20| i += 1;
- 6| | }
- 7| 2|}
- ------------------
- | unused::foo::<f32>:
- | 1| 1|fn foo<T>(x: T) {
- | 2| 1| let mut i = 0;
- | 3| 11| while i < 10 {
- | 4| 10| i != 0 || i != 0;
- | ^1
- | 5| 10| i += 1;
- | 6| | }
- | 7| 1|}
- ------------------
- | unused::foo::<u32>:
- | 1| 1|fn foo<T>(x: T) {
- | 2| 1| let mut i = 0;
- | 3| 11| while i < 10 {
- | 4| 10| i != 0 || i != 0;
- | ^1
- | 5| 10| i += 1;
- | 6| | }
- | 7| 1|}
- ------------------
- 8| |
- 9| 0|fn unused_template_func<T>(x: T) {
- 10| 0| let mut i = 0;
- 11| 0| while i < 10 {
- 12| 0| i != 0 || i != 0;
- 13| 0| i += 1;
- 14| | }
- 15| 0|}
- 16| |
- 17| 0|fn unused_func(mut a: u32) {
- 18| 0| if a != 0 {
- 19| 0| a += 1;
- 20| 0| }
- 21| 0|}
- 22| |
- 23| 0|fn unused_func2(mut a: u32) {
- 24| 0| if a != 0 {
- 25| 0| a += 1;
- 26| 0| }
- 27| 0|}
- 28| |
- 29| 0|fn unused_func3(mut a: u32) {
- 30| 0| if a != 0 {
- 31| 0| a += 1;
- 32| 0| }
- 33| 0|}
- 34| |
- 35| 1|fn main() -> Result<(), u8> {
- 36| 1| foo::<u32>(0);
- 37| 1| foo::<f32>(0.0);
- 38| 1| Ok(())
- 39| 1|}
-
+++ /dev/null
- 1| 0|pub fn never_called_function() {
- 2| 0| println!("I am never called");
- 3| 0|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
- 3| |use std::fmt::Debug;
- 4| |
- 5| 1|pub fn used_function() {
- 6| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 7| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 8| 1| // dependent conditions.
- 9| 1| let is_true = std::env::args().len() == 1;
- 10| 1| let mut countdown = 0;
- 11| 1| if is_true {
- 12| 1| countdown = 10;
- 13| 1| }
- ^0
- 14| 1| use_this_lib_crate();
- 15| 1|}
- 16| |
- 17| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
- 18| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
- 19| 2|}
- ------------------
- | used_crate::used_only_from_bin_crate_generic_function::<&str>:
- | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
- | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
- | 19| 1|}
- ------------------
- | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
- | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
- | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
- | 19| 1|}
- ------------------
- | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
- ------------------
- 20| |// Expect for above function: `Unexecuted instantiation` (see below)
- 21| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
- 22| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
- 23| 2|}
- ------------------
- | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
- | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
- | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
- | 23| 1|}
- ------------------
- | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
- | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
- | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
- | 23| 1|}
- ------------------
- 24| |
- 25| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- 26| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- 27| 2|}
- ------------------
- | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
- | 25| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 26| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 27| 1|}
- ------------------
- | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
- | 25| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 26| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 27| 1|}
- ------------------
- 28| |
- 29| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- 30| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- 31| 2|}
- ------------------
- | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
- | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 31| 1|}
- ------------------
- | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
- | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 31| 1|}
- ------------------
- 32| |
- 33| 0|pub fn unused_generic_function<T: Debug>(arg: T) {
- 34| 0| println!("unused_generic_function with {:?}", arg);
- 35| 0|}
- 36| |
- 37| 0|pub fn unused_function() {
- 38| 0| let is_true = std::env::args().len() == 1;
- 39| 0| let mut countdown = 2;
- 40| 0| if !is_true {
- 41| 0| countdown = 20;
- 42| 0| }
- 43| 0|}
- 44| |
- 45| 0|fn unused_private_function() {
- 46| 0| let is_true = std::env::args().len() == 1;
- 47| 0| let mut countdown = 2;
- 48| 0| if !is_true {
- 49| 0| countdown = 20;
- 50| 0| }
- 51| 0|}
- 52| |
- 53| 1|fn use_this_lib_crate() {
- 54| 1| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
- 55| 1| used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
- 56| 1| "used from library used_crate.rs",
- 57| 1| );
- 58| 1| let some_vec = vec![5, 6, 7, 8];
- 59| 1| used_only_from_this_lib_crate_generic_function(some_vec);
- 60| 1| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
- 61| 1|}
- 62| |
- 63| |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
- 64| |// for example:
- 65| |//
- 66| |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
- 67| |//
- 68| |// These notices appear when `llvm-cov` shows instantiations. This may be a
- 69| |// default option, but it can be suppressed with:
- 70| |//
- 71| |// ```shell
- 72| |// $ `llvm-cov show --show-instantiations=0 ...`
- 73| |// ```
- 74| |//
- 75| |// The notice is triggered because the function is unused by the library itself,
- 76| |// and when the library is compiled, a synthetic function is generated, so
- 77| |// unused function coverage can be reported. Coverage can be skipped for unused
- 78| |// generic functions with:
- 79| |//
- 80| |// ```shell
- 81| |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
- 82| |// ```
- 83| |//
- 84| |// Even though this function is used by `uses_crate.rs` (and
- 85| |// counted), with substitutions for `T`, those instantiations are only generated
- 86| |// when the generic function is actually used (from the binary, not from this
- 87| |// library crate). So the test result shows coverage for all instantiated
- 88| |// versions and their generic type substitutions, plus the `Unexecuted
- 89| |// instantiation` message for the non-substituted version. This is valid, but
- 90| |// unfortunately a little confusing.
- 91| |//
- 92| |// The library crate has its own coverage map, and the only way to show unused
- 93| |// coverage of a generic function is to include the generic function in the
- 94| |// coverage map, marked as an "unused function". If the library were used by
- 95| |// another binary that never used this generic function, then it would be valid
- 96| |// to show the unused generic, with unknown substitution (`_`).
- 97| |//
- 98| |// The alternative is to exclude all generics from being included in the "unused
- 99| |// functions" list, which would then omit coverage results for
- 100| |// `unused_generic_function<T>()`, below.
-
+++ /dev/null
- 1| |#![allow(unused_assignments, unused_variables)]
- 2| |
- 3| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
- 4| |
- 5| |use std::fmt::Debug;
- 6| |
- 7| 1|pub fn used_function() {
- 8| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 9| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 10| 1| // dependent conditions.
- 11| 1| let is_true = std::env::args().len() == 1;
- 12| 1| let mut countdown = 0;
- 13| 1| if is_true {
- 14| 1| countdown = 10;
- 15| 1| }
- ^0
- 16| 1| use_this_lib_crate();
- 17| 1|}
- 18| |
- 19| |#[inline(always)]
- 20| 1|pub fn used_inline_function() {
- 21| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
- 22| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- 23| 1| // dependent conditions.
- 24| 1| let is_true = std::env::args().len() == 1;
- 25| 1| let mut countdown = 0;
- 26| 1| if is_true {
- 27| 1| countdown = 10;
- 28| 1| }
- ^0
- 29| 1| use_this_lib_crate();
- 30| 1|}
- 31| |
- 32| |
- 33| |
- 34| |
- 35| |
- 36| |
- 37| |
- 38| |#[inline(always)]
- 39| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
- 40| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
- 41| 2|}
- ------------------
- | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
- | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
- | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
- | 41| 1|}
- ------------------
- | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
- | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
- | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
- | 41| 1|}
- ------------------
- | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
- ------------------
- 42| |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
- 43| |
- 44| |#[inline(always)]
- 45| 4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
- 46| 4| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
- 47| 4|}
- ------------------
- | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
- | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
- | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
- | 47| 2|}
- ------------------
- | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
- | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
- | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
- | 47| 2|}
- ------------------
- 48| |
- 49| |#[inline(always)]
- 50| 3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- 51| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- 52| 3|}
- ------------------
- | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
- | 50| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 51| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 52| 1|}
- ------------------
- | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
- | 50| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 51| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 52| 2|}
- ------------------
- 53| |
- 54| |#[inline(always)]
- 55| 3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- 56| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- 57| 3|}
- ------------------
- | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
- | 55| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 56| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 57| 1|}
- ------------------
- | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
- | 55| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
- | 56| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
- | 57| 2|}
- ------------------
- 58| |
- 59| |#[inline(always)]
- 60| 0|pub fn unused_generic_function<T: Debug>(arg: T) {
- 61| 0| println!("unused_generic_function with {:?}", arg);
- 62| 0|}
- 63| |
- 64| |#[inline(always)]
- 65| 0|pub fn unused_function() {
- 66| 0| let is_true = std::env::args().len() == 1;
- 67| 0| let mut countdown = 2;
- 68| 0| if !is_true {
- 69| 0| countdown = 20;
- 70| 0| }
- 71| 0|}
- 72| |
- 73| |#[inline(always)]
- 74| 0|fn unused_private_function() {
- 75| 0| let is_true = std::env::args().len() == 1;
- 76| 0| let mut countdown = 2;
- 77| 0| if !is_true {
- 78| 0| countdown = 20;
- 79| 0| }
- 80| 0|}
- 81| |
- 82| 2|fn use_this_lib_crate() {
- 83| 2| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
- 84| 2| used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
- 85| 2| "used from library used_crate.rs",
- 86| 2| );
- 87| 2| let some_vec = vec![5, 6, 7, 8];
- 88| 2| used_only_from_this_lib_crate_generic_function(some_vec);
- 89| 2| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
- 90| 2|}
-
+++ /dev/null
- 1| 1|fn main() {
- 2| 1| let num = 9;
- 3| 1| while num >= 10 {
- 4| 0| }
- 5| 1|}
-
+++ /dev/null
- 1| |#![allow(unused_assignments)]
- 2| |// expect-exit-status-1
- 3| |
- 4| 1|fn main() -> Result<(),u8> {
- 5| 1| let mut countdown = 10;
- 6| | while
- 7| 7| countdown
- 8| 7| >
- 9| 7| 0
- 10| | {
- 11| | if
- 12| 7| countdown
- 13| 7| <
- 14| 7| 5
- 15| | {
- 16| | return
- 17| | if
- 18| 1| countdown
- 19| 1| >
- 20| 1| 8
- 21| | {
- 22| 0| Ok(())
- 23| | }
- 24| | else
- 25| | {
- 26| 1| Err(1)
- 27| | }
- 28| | ;
- 29| 6| }
- 30| 6| countdown
- 31| 6| -=
- 32| 6| 1
- 33| | ;
- 34| | }
- 35| 0| Ok(())
- 36| 1|}
- 37| |
- 38| |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
- 39| |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
- 40| |// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
- 41| |// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
- 42| |// to the coverage test for early returns, but this is a limitation that should be fixed.
-
+++ /dev/null
- 1| |#![feature(generators, generator_trait)]
- 2| |#![allow(unused_assignments)]
- 3| |
- 4| |use std::ops::{Generator, GeneratorState};
- 5| |use std::pin::Pin;
- 6| |
- 7| 1|fn main() {
- 8| 1| let mut generator = || {
- 9| 1| yield 1;
- 10| 1| return "foo"
- 11| | };
- 12| |
- 13| 1| match Pin::new(&mut generator).resume(()) {
- 14| 1| GeneratorState::Yielded(1) => {}
- 15| 0| _ => panic!("unexpected value from resume"),
- 16| | }
- 17| 1| match Pin::new(&mut generator).resume(()) {
- 18| 1| GeneratorState::Complete("foo") => {}
- 19| 0| _ => panic!("unexpected value from resume"),
- 20| | }
- 21| |
- 22| 1| let mut generator = || {
- 23| 1| yield 1;
- 24| 1| yield 2;
- 25| 0| yield 3;
- 26| 0| return "foo"
- 27| | };
- 28| |
- 29| 1| match Pin::new(&mut generator).resume(()) {
- 30| 1| GeneratorState::Yielded(1) => {}
- 31| 0| _ => panic!("unexpected value from resume"),
- 32| | }
- 33| 1| match Pin::new(&mut generator).resume(()) {
- 34| 1| GeneratorState::Yielded(2) => {}
- 35| 0| _ => panic!("unexpected value from resume"),
- 36| | }
- 37| 1|}
-
+++ /dev/null
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-import sys
-
-# Normalize file paths in output
-for line in sys.stdin:
- if line.startswith("..") and line.rstrip().endswith(".rs:"):
- print(line.replace("\\", "/"), end='')
- else:
- print(line, end='')
+++ /dev/null
-IMPORTANT: The Rust test programs in this directory generate various output
-files in the `../coverage*` directories (`expected` and `actual` files).
-
-Microsoft Windows has a relatively short limit on file paths (not individual
-path components, but the entire path). The files generated by these
-`../coverage*` tests typically have file paths that include the program
-source file name plus function and type names (depending on the program).
-
-Keep the test file names short, and keep function names and other symbols
-short as well, to avoid hitting the Windows limits.
+++ /dev/null
-#![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 `TerminatorKind::Abort`.
-// 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.
-*/
+++ /dev/null
-#![allow(unused_assignments)]
-// expect-exit-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.
+++ /dev/null
-#![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 funciton 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;
- }
- }
- }
-}
+++ /dev/null
-// compile-flags: --edition=2018
-
-use core::{
- future::Future,
- marker::Send,
- pin::Pin,
-};
-
-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;
- }
- }
- }
-}
+++ /dev/null
-#![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
-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);
-}
+++ /dev/null
-// compile-flags: --edition=2018
-#![feature(no_coverage)]
-
-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(())
-}
+++ /dev/null
-// compile-flags: --edition=2018
-#![feature(no_coverage)]
-
-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(())
-}
-
-#[no_coverage]
-fn main() {
- executor::block_on(test());
-}
-
-mod executor {
- use core::{
- future::Future,
- pin::Pin,
- task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
- };
-
- #[no_coverage]
- 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(
-
- #[no_coverage]
- |_| unsafe { unreachable_unchecked() }, // clone
-
- #[no_coverage]
- |_| unsafe { unreachable_unchecked() }, // wake
-
- #[no_coverage]
- |_| unsafe { unreachable_unchecked() }, // wake_by_ref
-
- #[no_coverage]
- |_| (),
- );
- 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;
- }
- }
- }
-}
+++ /dev/null
-# Directory "coverage" supports the tests at prefix ../coverage-*
-
-# Use ./x.py [options] test src/test/run-make-fulldeps/coverage to run all related tests.
+++ /dev/null
-#![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;
- };
-}
+++ /dev/null
-#![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;
-}
+++ /dev/null
-# Common Makefile include for Rust `run-make-fulldeps/coverage-* tests. Include this
-# file with the line:
-#
-# -include ../coverage/coverage_tools.mk
-
--include ../tools.mk
+++ /dev/null
-#![allow(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;
- }
-}
+++ /dev/null
-//! This test ensures that code from doctests is properly re-mapped.
-//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
-//!
-//! Just some random code:
-//! ```
-//! if true {
-//! // this is executed!
-//! assert_eq!(1, 1);
-//! } else {
-//! // this is not!
-//! assert_eq!(1, 2);
-//! }
-//! ```
-//!
-//! doctest testing external code:
-//! ```
-//! extern crate doctest_crate;
-//! doctest_crate::fn_run_in_doctests(1);
-//! ```
-//!
-//! doctest returning a result:
-//! ```
-//! #[derive(Debug, PartialEq)]
-//! struct SomeError {
-//! msg: String,
-//! }
-//! let mut res = Err(SomeError { msg: String::from("a message") });
-//! if res.is_ok() {
-//! res?;
-//! } else {
-//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
-//! println!("{:?}", res);
-//! }
-//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
-//! res = Ok(1);
-//! }
-//! res = Ok(0);
-//! }
-//! // need to be explicit because rustdoc cant infer the return type
-//! Ok::<(), SomeError>(())
-//! ```
-//!
-//! doctest with custom main:
-//! ```
-//! fn some_func() {
-//! println!("called some_func()");
-//! }
-//!
-//! #[derive(Debug)]
-//! struct SomeError;
-//!
-//! extern crate doctest_crate;
-//!
-//! fn doctest_main() -> Result<(), SomeError> {
-//! some_func();
-//! doctest_crate::fn_run_in_doctests(2);
-//! Ok(())
-//! }
-//!
-//! // this `main` is not shown as covered, as it clashes with all the other
-//! // `main` functions that were automatically generated for doctests
-//! fn main() -> Result<(), SomeError> {
-//! doctest_main()
-//! }
-//! ```
-
-/// doctest attached to fn testing external code:
-/// ```
-/// extern crate doctest_crate;
-/// doctest_crate::fn_run_in_doctests(3);
-/// ```
-///
-fn main() {
- if true {
- assert_eq!(1, 1);
- } else {
- assert_eq!(1, 2);
- }
-}
-
-// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
-// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
-// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
-//
-// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
-// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
-// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
-// one character past, the `if` block's closing brace. In both cases, these are most likely off
-// by the number of characters stripped from the beginning of each doc comment line: indent
-// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
-// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
-// more pronounced, and show up in more places, with background color used to show some distinct
-// code regions with different coverage counts.
-//
-// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
-// character stripped from the beginning of doc comment lines with a space. This will give coverage
-// results the correct column offsets, and I think it should compile correctly, but I don't know
-// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
-// if the indentation changed. I don't know if there is a more viable solution.
+++ /dev/null
-#![allow(unused_assignments)]
-// expect-exit-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
+++ /dev/null
-#![feature(generators, generator_trait)]
-
-use std::ops::{Generator, GeneratorState};
-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 `generator::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 generator = || {
- yield get_u32(is_true);
- return "foo";
- };
-
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Yielded(Ok(1)) => {}
- _ => panic!("unexpected return from resume"),
- }
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Complete("foo") => {}
- _ => panic!("unexpected return from resume"),
- }
-}
+++ /dev/null
-#![allow(unused_assignments)]
-// expect-exit-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
+++ /dev/null
-#![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
- ;
- }
-}
+++ /dev/null
-#![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
- ;
- }
-}
+++ /dev/null
-// 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
-}
+++ /dev/null
-// 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");
-}
+++ /dev/null
-#![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();
-}
+++ /dev/null
-// 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);
-}
+++ /dev/null
-// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
-
-// expect-exit-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();
-}
+++ /dev/null
-// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
-
-extern crate inline_always_with_dead_code;
-
-use inline_always_with_dead_code::{bar, baz};
-
-fn main() {
- bar::call_me();
- baz::call_me();
-}
+++ /dev/null
-// 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() { }
+++ /dev/null
-#![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;
- }
-}
+++ /dev/null
-/// A function run only from within doctests
-pub fn fn_run_in_doctests(conditional: usize) {
- match conditional {
- 1 => assert_eq!(1, 1), // this is run,
- 2 => assert_eq!(1, 1), // this,
- 3 => assert_eq!(1, 1), // and this too
- _ => assert_eq!(1, 2), // however this is not
- }
-}
+++ /dev/null
-// 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();
- }
-}
+++ /dev/null
-pub fn never_called_function() {
- println!("I am never called");
-}
+++ /dev/null
-#![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-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;
- }
-}
-
-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.
+++ /dev/null
-#![allow(unused_assignments, unused_variables)]
-
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-
-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)]
-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");
-}
+++ /dev/null
-#![allow(unused_assignments, unused_variables)]
-
-fn main() {
- let result
- =
- loop
- {
- break
- 10
- ;
- }
- ;
-}
+++ /dev/null
-#![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);
-}
+++ /dev/null
-#![feature(or_patterns)]
-
-fn main() {
- // Initialize test constants in a way that cannot be determined at compile time, to ensure
- // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
- // dependent conditions.
- let is_true = std::env::args().len() == 1;
-
- let mut a: u8 = 0;
- let mut b: u8 = 0;
- if is_true {
- a = 2;
- b = 0;
- }
- match (a, b) {
- // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
- // This test confirms a fix for Issue #79569.
- (0 | 1, 2 | 3) => {}
- _ => {}
- }
- if is_true {
- a = 0;
- b = 0;
- }
- match (a, b) {
- (0 | 1, 2 | 3) => {}
- _ => {}
- }
- if is_true {
- a = 2;
- b = 2;
- }
- match (a, b) {
- (0 | 1, 2 | 3) => {}
- _ => {}
- }
- if is_true {
- a = 0;
- b = 2;
- }
- match (a, b) {
- (0 | 1, 2 | 3) => {}
- _ => {}
- }
-}
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-// Enables `no_coverage` on the entire crate
-#![feature(no_coverage)]
-
-#[no_coverage]
-fn do_not_add_coverage_1() {
- println!("called but not covered");
-}
-
-fn do_not_add_coverage_2() {
- #![no_coverage]
- println!("called but not covered");
-}
-
-#[no_coverage]
-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");
-}
-
-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 {
- #[no_coverage]
- 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);
-
- #[no_coverage]
- 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);
-}
+++ /dev/null
-#![allow(unused_assignments)]
-// expect-exit-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|}
+++ /dev/null
-#![allow(unused_assignments)]
-// expect-exit-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.
+++ /dev/null
-// 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
- }),
- substs: []
- }'
-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.
-
-*/
+++ /dev/null
-#![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
- ;
- }
-}
+++ /dev/null
-#![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
- ;
- }
- _
- =>
- {}
- }
- }
-}
+++ /dev/null
-fn main() {
- if false {
- loop {}
- }
-}
+++ /dev/null
-#![allow(unused_assignments)]
-// expect-exit-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(())
-}
+++ /dev/null
-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(())
-}
+++ /dev/null
-#[path = "lib/unused_mod_helper.rs"]
-mod unused_module;
-
-fn main() {
- println!("hello world!");
-}
+++ /dev/null
-#![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-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?");
-}
+++ /dev/null
-#![allow(unused_assignments, unused_variables)]
-
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-
-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?",
- );
-}
+++ /dev/null
-fn main() {
- let num = 9;
- while num >= 10 {
- }
-}
+++ /dev/null
-#![allow(unused_assignments)]
-// expect-exit-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.
+++ /dev/null
-#![feature(generators, generator_trait)]
-#![allow(unused_assignments)]
-
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-fn main() {
- let mut generator = || {
- yield 1;
- return "foo"
- };
-
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Yielded(1) => {}
- _ => panic!("unexpected value from resume"),
- }
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Complete("foo") => {}
- _ => panic!("unexpected value from resume"),
- }
-
- let mut generator = || {
- yield 1;
- yield 2;
- yield 3;
- return "foo"
- };
-
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Yielded(1) => {}
- _ => panic!("unexpected value from resume"),
- }
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Yielded(2) => {}
- _ => panic!("unexpected value from resume"),
- }
-}
--- /dev/null
+# needs-profiler-support
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+-include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-llvmir
+
+ifeq ($(UNAME),Darwin)
+ INSTR_PROF_DATA_SUFFIX=,regular,live_support
+ DATA_SECTION_PREFIX=__DATA,
+ LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+ COMDAT_IF_SUPPORTED=
+else
+ INSTR_PROF_DATA_SUFFIX=
+ DATA_SECTION_PREFIX=
+ LLVM_COV_SECTION_PREFIX=
+ COMDAT_IF_SUPPORTED=, comdat
+endif
+
+DEFINE_INTERNAL=define internal
+
+ifdef IS_WINDOWS
+ LLVM_FILECHECK_OPTIONS=\
+ -check-prefixes=CHECK,WINDOWS \
+ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+ -DINSTR_PROF_DATA='.lprfd$$M' \
+ -DINSTR_PROF_NAME='.lprfn$$M' \
+ -DINSTR_PROF_CNTS='.lprfc$$M' \
+ -DINSTR_PROF_VALS='.lprfv$$M' \
+ -DINSTR_PROF_VNODES='.lprfnd$$M' \
+ -DINSTR_PROF_COVMAP='.lcovmap$$M' \
+ -DINSTR_PROF_COVFUN='.lcovfun$$M' \
+ -DINSTR_PROF_ORDERFILE='.lorderfile$$M'
+else
+ LLVM_FILECHECK_OPTIONS=\
+ -check-prefixes=CHECK \
+ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+ -DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \
+ -DINSTR_PROF_NAME='$(DATA_SECTION_PREFIX)__llvm_prf_names' \
+ -DINSTR_PROF_CNTS='$(DATA_SECTION_PREFIX)__llvm_prf_cnts' \
+ -DINSTR_PROF_VALS='$(DATA_SECTION_PREFIX)__llvm_prf_vals' \
+ -DINSTR_PROF_VNODES='$(DATA_SECTION_PREFIX)__llvm_prf_vnds' \
+ -DINSTR_PROF_COVMAP='$(LLVM_COV_SECTION_PREFIX)__llvm_covmap' \
+ -DINSTR_PROF_COVFUN='$(LLVM_COV_SECTION_PREFIX)__llvm_covfun' \
+ -DINSTR_PROF_ORDERFILE='$(DATA_SECTION_PREFIX)__llvm_orderfile'
+endif
+
+all: test_llvm_ir
+
+test_llvm_ir:
+ # Compile the test program with non-experimental coverage instrumentation, and generate LLVM IR
+ $(RUSTC) $(BASEDIR)/testprog.rs \
+ -Cinstrument-coverage \
+ --emit=llvm-ir
+
+ cat "$(TMPDIR)"/testprog.ll | \
+ "$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
--- /dev/null
+# Check for metadata, variables, declarations, and function definitions injected
+# into LLVM IR when compiling with -Cinstrument-coverage.
+
+WINDOWS: $__llvm_profile_runtime_user = comdat any
+
+CHECK: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
+CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
+
+CHECK: @__llvm_coverage_mapping = private constant
+CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
+
+WINDOWS: @__llvm_profile_runtime = external global i32
+
+CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called
+CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
+
+CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main
+CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
+
+CHECK: @__llvm_prf_nm = private constant
+CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
+
+CHECK: @llvm.used = appending global
+CHECK-SAME: @__llvm_coverage_mapping
+CHECK-SAME: @__llvm_prf_nm
+CHECK-SAME: section "llvm.metadata"
+
+CHECK: [[DEFINE_INTERNAL]] { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+CHECK-NEXT: start:
+CHECK-NOT: [[DEFINE_INTERNAL]]
+CHECK: %pgocount = load i64, {{i64\*|ptr}}
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK: declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
+
+WINDOWS: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+WINDOWS-NEXT: %1 = load i32, {{i32\*|ptr}} @__llvm_profile_runtime
+WINDOWS-NEXT: ret i32 %1
+WINDOWS-NEXT: }
+
+CHECK: attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
+WINDOWS: attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
--- /dev/null
+pub fn will_be_called() -> &'static str {
+ let val = "called";
+ println!("{}", val);
+ val
+}
+
+pub fn will_not_be_called() -> bool {
+ println!("should not have been called");
+ false
+}
+
+pub fn print<T>(left: &str, value: T, right: &str)
+where
+ T: std::fmt::Display,
+{
+ println!("{}{}{}", left, value, right);
+}
+
+pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
+where
+ F: FnOnce(&T)
+{
+ if should_wrap {
+ wrapper(&inner)
+ }
+}
+
+fn main() {
+ let less = 1;
+ let more = 100;
+
+ if less < more {
+ wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
+ wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
+ } else {
+ wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
+ }
+}
--- /dev/null
+# needs-profiler-support
+# ignore-windows-gnu
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
+# properly. Since we only have GCC on the CI ignore the test for now.
+
+-include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-reports
+SOURCEDIR=../coverage
+
+# The `llvm-cov show` flag `--debug`, used to generate the `counters` output files, is only
+# enabled if LLVM assertions are enabled. This requires Rust config `llvm/optimize` and not
+# `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting
+# `NO_LLVM_ASSERTIONS=1`), so the tests must still pass even if the `--debug` flag is
+# not supported. (Note that `counters` files are only produced in the `$(TMPDIR)`
+# directory, for inspection and debugging support. They are *not* copied to `expected_*`
+# files when `--bless`ed.)
+LLVM_COV_DEBUG := $(shell \
+ "$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \
+ grep -q "Unknown command line argument '--debug'"; \
+ echo $$?)
+ifeq ($(LLVM_COV_DEBUG), 1)
+DEBUG_FLAG=--debug
+endif
+
+# FIXME(richkadel): I'm adding `--ignore-filename-regex=` line(s) for specific test(s) that produce
+# `llvm-cov` results for multiple files (for example `uses_crate.rs` and `used_crate/mod.rs`) as a
+# workaround for two problems causing tests to fail on Windows:
+#
+# 1. When multiple files appear in the `llvm-cov show` results, each file's coverage results can
+# appear in different a different order. Whether this is random or, somehow, platform-specific,
+# the Windows output flips the order of the files, compared to Linux. In the `uses_crate.rs`
+# test, the only test-unique (interesting) results we care about are the results for only one
+# of the two files, `mod/uses_crate.rs`, so the workaround is to ignore all but this one file.
+# In the future, we may want a more sophisticated solution that splits apart `llvm-cov show`
+# results into separate results files for each result (taking care not to create new file
+# paths that might be too long for Windows MAX_PATH limits when creating these new sub-results,
+# as well).
+# 2. When multiple files appear in the `llvm-cov show` results, the results for each file are
+# prefixed with their filename, including platform-specific path separators (`\` for Windows,
+# and `/` everywhere else). This could be filtered or normalized of course, but by ignoring
+# coverage results for all but one of the file, the filenames are no longer included anyway.
+# If this changes (if/when we decide to support `llvm-cov show` results for multiple files),
+# the file path separator differences may need to be addressed.
+#
+# Since this is only a workaround, I decided to implement the override by adding an option for
+# each file to be ignored, using a `--ignore-filename-regex=` entry for each one, rather than
+# implement some more sophisticated solution with a new custom test directive in the test file
+# itself (similar to `expect-exit-status`) because that would add a lot of complexity and still
+# be a workaround, with the same result, with no benefit.
+#
+# Yes these `--ignore-filename-regex=` options are included in all invocations of `llvm-cov show`
+# for now, but it is effectively ignored for all tests that don't include this file anyway.
+#
+# (Note that it's also possible the `_counters.<test>.txt` and `<test>.json` files (if generated)
+# may order results from multiple files inconsistently, which might also have to be accomodated
+# if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators
+# appear to be normalized to `/` in those files, thankfully.)
+LLVM_COV_IGNORE_FILES=\
+ --ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)'
+
+all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
+
+# Ensure there are no `expected` results for tests that may have been removed or renamed
+.PHONY: clear_expected_if_blessed
+clear_expected_if_blessed:
+ifdef RUSTC_BLESS_TEST
+ rm -f expected_*
+endif
+
+-include clear_expected_if_blessed
+
+%: $(SOURCEDIR)/lib/%.rs
+ # Compile the test library with coverage instrumentation
+ $(RUSTC) $(SOURCEDIR)/lib/$@.rs \
+ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \
+ --crate-type rlib -Cinstrument-coverage
+
+%: $(SOURCEDIR)/%.rs
+ # Compile the test program with coverage instrumentation
+ $(RUSTC) $(SOURCEDIR)/$@.rs \
+ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+ -L "$(TMPDIR)" -Cinstrument-coverage
+
+ # Run it in order to generate some profiling data,
+ # with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
+ # output the coverage stats for this run.
+ LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
+ $(call RUN,$@) || \
+ ( \
+ status=$$?; \
+ grep -q "^\/\/ expect-exit-status-$$status" $(SOURCEDIR)/$@.rs || \
+ ( >&2 echo "program exited with an unexpected exit status: $$status"; \
+ false \
+ ) \
+ )
+
+ # Run it through rustdoc as well to cover doctests.
+ # `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone
+ # might result in overwritten files and failed tests, as rustdoc spawns each
+ # doctest as its own process, so make sure the filename is as unique as possible.
+ LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \
+ $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
+ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
+ -L "$(TMPDIR)" -Cinstrument-coverage \
+ -Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
+
+ # Postprocess the profiling data so it can be used by the llvm-cov tool
+ "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
+ "$(TMPDIR)"/$@*.profraw \
+ -o "$(TMPDIR)"/$@.profdata
+
+ # Generate a coverage report using `llvm-cov show`.
+ "$(LLVM_BIN_DIR)"/llvm-cov show \
+ $(DEBUG_FLAG) \
+ $(LLVM_COV_IGNORE_FILES) \
+ --compilation-dir=. \
+ --Xdemangler="$(RUST_DEMANGLER)" \
+ --show-line-counts-or-regions \
+ --instr-profile="$(TMPDIR)"/$@.profdata \
+ $(call BIN,"$(TMPDIR)"/$@) \
+ $$( \
+ for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \
+ [ -x "$$file" ] && printf "%s %s " -object $$file; \
+ done \
+ ) \
+ 2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+ | "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
+ > "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+ ( status=$$? ; \
+ >&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
+ exit $$status \
+ )
+
+ifdef DEBUG_FLAG
+ # The first line (beginning with "Args:" contains hard-coded, build-specific
+ # file paths. Strip that line and keep the remaining lines with counter debug
+ # data.
+ tail -n +2 "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+ > "$(TMPDIR)"/actual_show_coverage_counters.$@.txt
+endif
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/actual_show_coverage.$@.txt \
+ expected_show_coverage.$@.txt
+else
+ # Compare the show coverage output (`--bless` refreshes `typical` files).
+ #
+ # FIXME(richkadel): None of the Rust test source samples have the
+ # `// ignore-llvm-cov-show-diffs` anymore. This directive exists to work around a limitation
+ # with `llvm-cov show`. When reporting coverage for multiple instantiations of a generic function,
+ # with different type substitutions, `llvm-cov show` prints these in a non-deterministic order,
+ # breaking the `diff` comparision.
+ #
+ # A partial workaround is implemented below, with `diff --ignore-matching-lines=RE`
+ # to ignore each line prefixing each generic instantiation coverage code region.
+ #
+ # This workaround only works if the coverage counts are identical across all reported
+ # instantiations. If there is no way to ensure this, you may need to apply the
+ # `// ignore-llvm-cov-show-diffs` directive, and check for differences using the
+ # `.json` files to validate that results have not changed. (Until then, the JSON
+ # files are redundant, so there is no need to generate `expected_*.json` files or
+ # compare actual JSON results.)
+
+ $(DIFF) --ignore-matching-lines='^ | .*::<.*>.*:$$' --ignore-matching-lines='^ | <.*>::.*:$$' \
+ expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
+ ( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
+ >&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
+ ) || \
+ ( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \
+ false \
+ )
+endif
--- /dev/null
+ 1| |#![feature(c_unwind)]
+ 2| |#![allow(unused_assignments)]
+ 3| |
+ 4| 12|extern "C" fn might_abort(should_abort: bool) {
+ 5| 12| if should_abort {
+ 6| 0| println!("aborting...");
+ 7| 0| panic!("panics and aborts");
+ 8| 12| } else {
+ 9| 12| println!("Don't Panic");
+ 10| 12| }
+ 11| 12|}
+ 12| |
+ 13| 1|fn main() -> Result<(), u8> {
+ 14| 1| let mut countdown = 10;
+ 15| 11| while countdown > 0 {
+ 16| 10| if countdown < 5 {
+ 17| 4| might_abort(false);
+ 18| 6| }
+ 19| | // See discussion (below the `Notes` section) on coverage results for the closing brace.
+ 20| 10| if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+ ^4 ^6
+ 21| | // For the following example, the closing brace is the last character on the line.
+ 22| | // This shows the character after the closing brace is highlighted, even if that next
+ 23| | // character is a newline.
+ 24| 10| if countdown < 5 { might_abort(false); }
+ ^4 ^6
+ 25| 10| countdown -= 1;
+ 26| | }
+ 27| 1| Ok(())
+ 28| 1|}
+ 29| |
+ 30| |// Notes:
+ 31| |// 1. Compare this program and its coverage results to those of the similar tests
+ 32| |// `panic_unwind.rs` and `try_error_result.rs`.
+ 33| |// 2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+ 34| |// 3. The test does not invoke the abort. By executing to a successful completion, the coverage
+ 35| |// results show where the program did and did not execute.
+ 36| |// 4. If the program actually aborted, the coverage counters would not be saved (which "works as
+ 37| |// intended"). Coverage results would show no executed coverage regions.
+ 38| |// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+ 39| |// (on Linux at least).
+ 40| |
+ 41| |/*
+ 42| |
+ 43| |Expect the following coverage results:
+ 44| |
+ 45| |```text
+ 46| | 16| 11| while countdown > 0 {
+ 47| | 17| 10| if countdown < 5 {
+ 48| | 18| 4| might_abort(false);
+ 49| | 19| 6| }
+ 50| |```
+ 51| |
+ 52| |This is actually correct.
+ 53| |
+ 54| |The condition `countdown < 5` executed 10 times (10 loop iterations).
+ 55| |
+ 56| |It evaluated to `true` 4 times, and executed the `might_abort()` call.
+ 57| |
+ 58| |It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+ 59| |`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+ 60| |closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+ 61| |non-true condition.
+ 62| |
+ 63| |As another example of why this is important, say the condition was `countdown < 50`, which is always
+ 64| |`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+ 65| |The closing brace would have a count of `0`, highlighting the missed coverage.
+ 66| |*/
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-101
+ 3| |
+ 4| 4|fn might_fail_assert(one_plus_one: u32) {
+ 5| 4| println!("does 1 + 1 = {}?", one_plus_one);
+ 6| 4| assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+ ^1
+ 7| 3|}
+ 8| |
+ 9| 1|fn main() -> Result<(),u8> {
+ 10| 1| let mut countdown = 10;
+ 11| 11| while countdown > 0 {
+ 12| 11| if countdown == 1 {
+ 13| 1| might_fail_assert(3);
+ 14| 10| } else if countdown < 5 {
+ 15| 3| might_fail_assert(2);
+ 16| 6| }
+ 17| 10| countdown -= 1;
+ 18| | }
+ 19| 0| Ok(())
+ 20| 0|}
+ 21| |
+ 22| |// Notes:
+ 23| |// 1. Compare this program and its coverage results to those of the very similar test
+ 24| |// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+ 25| |// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+ 26| |// related `assert_*!()` macro.
+ 27| |// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+ 28| |// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+ 29| |// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+ 30| |// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+ 31| |// (and in many other coverage tests). The `Assert` terminator is typically generated by the
+ 32| |// Rust compiler to check for runtime failures, such as numeric overflows.
+
--- /dev/null
+ 1| |#![allow(unused_assignments, dead_code)]
+ 2| |
+ 3| |// compile-flags: --edition=2018 -C opt-level=1
+ 4| |
+ 5| 1|async fn c(x: u8) -> u8 {
+ 6| 1| if x == 8 {
+ 7| 1| 1
+ 8| | } else {
+ 9| 0| 0
+ 10| | }
+ 11| 1|}
+ 12| |
+ 13| 0|async fn d() -> u8 { 1 }
+ 14| |
+ 15| 0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+ 16| |
+ 17| 1|async fn f() -> u8 { 1 }
+ 18| |
+ 19| 0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+ 20| |
+ 21| 1|pub async fn g(x: u8) {
+ 22| 0| match x {
+ 23| 0| y if e().await == y => (),
+ 24| 0| y if f().await == y => (),
+ 25| 0| _ => (),
+ 26| | }
+ 27| 0|}
+ 28| |
+ 29| 1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
+ 30| 0| // executed (not awaited) so the open brace has a `0` count (at least when
+ 31| 0| // displayed with `llvm-cov show` in color-mode).
+ 32| 0| match x {
+ 33| 0| y if foo().await[y] => (),
+ 34| 0| _ => (),
+ 35| | }
+ 36| 0|}
+ 37| |
+ 38| 1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+ 39| 1| // (a) the function signature, counted when the function is called; and
+ 40| 1| // (b) the open brace for the function body, counted once when the body is
+ 41| 1| // executed asynchronously.
+ 42| 1| match x {
+ 43| 1| y if c(x).await == y + 1 => { d().await; }
+ ^0 ^0 ^0 ^0
+ 44| 1| y if f().await == y + 1 => (),
+ ^0 ^0 ^0
+ 45| 1| _ => (),
+ 46| | }
+ 47| 1|}
+ 48| |
+ 49| 1|fn j(x: u8) {
+ 50| 1| // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+ 51| 1| fn c(x: u8) -> u8 {
+ 52| 1| if x == 8 {
+ 53| 1| 1 // This line appears covered, but the 1-character expression span covering the `1`
+ ^0
+ 54| 1| // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+ 55| 1| // `fn j()` executes the open brace for the funciton body, followed by the function's
+ 56| 1| // first executable statement, `match x`. Inner function declarations are not
+ 57| 1| // "visible" to the MIR for `j()`, so the code region counts all lines between the
+ 58| 1| // open brace and the first statement as executed, which is, in a sense, true.
+ 59| 1| // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+ 60| 1| // of the enclosed coverages, (that is, the `1` expression was not executed, and
+ 61| 1| // accurately displays a `0`).
+ 62| 1| } else {
+ 63| 1| 0
+ 64| 1| }
+ 65| 1| }
+ 66| 1| fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+ ^0
+ 67| 1| fn f() -> u8 { 1 }
+ 68| 1| match x {
+ 69| 1| y if c(x) == y + 1 => { d(); }
+ ^0 ^0
+ 70| 1| y if f() == y + 1 => (),
+ ^0 ^0
+ 71| 1| _ => (),
+ 72| | }
+ 73| 1|}
+ 74| |
+ 75| 0|fn k(x: u8) { // unused function
+ 76| 0| match x {
+ 77| 0| 1 => (),
+ 78| 0| 2 => (),
+ 79| 0| _ => (),
+ 80| | }
+ 81| 0|}
+ 82| |
+ 83| 1|fn l(x: u8) {
+ 84| 1| match x {
+ 85| 0| 1 => (),
+ 86| 0| 2 => (),
+ 87| 1| _ => (),
+ 88| | }
+ 89| 1|}
+ 90| |
+ 91| 1|async fn m(x: u8) -> u8 { x - 1 }
+ ^0
+ 92| |
+ 93| 1|fn main() {
+ 94| 1| let _ = g(10);
+ 95| 1| let _ = h(9);
+ 96| 1| let mut future = Box::pin(i(8));
+ 97| 1| j(7);
+ 98| 1| l(6);
+ 99| 1| let _ = m(5);
+ 100| 1| executor::block_on(future.as_mut());
+ 101| 1|}
+ 102| |
+ 103| |mod executor {
+ 104| | use core::{
+ 105| | future::Future,
+ 106| | pin::Pin,
+ 107| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ 108| | };
+ 109| |
+ 110| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ 111| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ 112| 1| use std::hint::unreachable_unchecked;
+ 113| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ 114| 1| |_| unsafe { unreachable_unchecked() }, // clone
+ ^0
+ 115| 1| |_| unsafe { unreachable_unchecked() }, // wake
+ ^0
+ 116| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ ^0
+ 117| 1| |_| (),
+ 118| 1| );
+ 119| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ 120| 1| let mut context = Context::from_waker(&waker);
+ 121| |
+ 122| | loop {
+ 123| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ 124| 1| break val;
+ 125| 0| }
+ 126| | }
+ 127| 1| }
+ 128| |}
+
--- /dev/null
+ 1| |// compile-flags: --edition=2018
+ 2| |
+ 3| |use core::{
+ 4| | future::Future,
+ 5| | marker::Send,
+ 6| | pin::Pin,
+ 7| |};
+ 8| |
+ 9| 1|fn non_async_func() {
+ 10| 1| println!("non_async_func was covered");
+ 11| 1| let b = true;
+ 12| 1| if b {
+ 13| 1| println!("non_async_func println in block");
+ 14| 1| }
+ ^0
+ 15| 1|}
+ 16| |
+ 17| |
+ 18| |
+ 19| |
+ 20| 1|async fn async_func() {
+ 21| 1| println!("async_func was covered");
+ 22| 1| let b = true;
+ 23| 1| if b {
+ 24| 1| println!("async_func println in block");
+ 25| 1| }
+ ^0
+ 26| 1|}
+ 27| |
+ 28| |
+ 29| |
+ 30| |
+ 31| 1|async fn async_func_just_println() {
+ 32| 1| println!("async_func_just_println was covered");
+ 33| 1|}
+ 34| |
+ 35| 1|fn main() {
+ 36| 1| println!("codecovsample::main");
+ 37| 1|
+ 38| 1| non_async_func();
+ 39| 1|
+ 40| 1| executor::block_on(async_func());
+ 41| 1| executor::block_on(async_func_just_println());
+ 42| 1|}
+ 43| |
+ 44| |mod executor {
+ 45| | use core::{
+ 46| | future::Future,
+ 47| | pin::Pin,
+ 48| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ 49| | };
+ 50| |
+ 51| 2| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ 52| 2| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ 53| 2| use std::hint::unreachable_unchecked;
+ 54| 2| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ 55| 2| |_| unsafe { unreachable_unchecked() }, // clone
+ ^0
+ 56| 2| |_| unsafe { unreachable_unchecked() }, // wake
+ ^0
+ 57| 2| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ ^0
+ 58| 2| |_| (),
+ 59| 2| );
+ 60| 2| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ 61| 2| let mut context = Context::from_waker(&waker);
+ 62| |
+ 63| | loop {
+ 64| 2| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ 65| 2| break val;
+ 66| 0| }
+ 67| | }
+ 68| 2| }
+ ------------------
+ | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func::{closure#0}>>:
+ | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ | 53| 1| use std::hint::unreachable_unchecked;
+ | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone
+ | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake
+ | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ | 58| 1| |_| (),
+ | 59| 1| );
+ | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ | 61| 1| let mut context = Context::from_waker(&waker);
+ | 62| |
+ | 63| | loop {
+ | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ | 65| 1| break val;
+ | 66| 0| }
+ | 67| | }
+ | 68| 1| }
+ ------------------
+ | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func_just_println::{closure#0}>>:
+ | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ | 53| 1| use std::hint::unreachable_unchecked;
+ | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone
+ | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake
+ | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ | 58| 1| |_| (),
+ | 59| 1| );
+ | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ | 61| 1| let mut context = Context::from_waker(&waker);
+ | 62| |
+ | 63| | loop {
+ | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ | 65| 1| break val;
+ | 66| 0| }
+ | 67| | }
+ | 68| 1| }
+ ------------------
+ 69| |}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1| let is_false = ! is_true;
+ 9| 1|
+ 10| 1| let mut some_string = Some(String::from("the string content"));
+ 11| 1| println!(
+ 12| 1| "The string or alt: {}"
+ 13| 1| ,
+ 14| 1| some_string
+ 15| 1| .
+ 16| 1| unwrap_or_else
+ 17| 1| (
+ 18| 1| ||
+ 19| 0| {
+ 20| 0| let mut countdown = 0;
+ 21| 0| if is_false {
+ 22| 0| countdown = 10;
+ 23| 0| }
+ 24| 0| "alt string 1".to_owned()
+ 25| 1| }
+ 26| 1| )
+ 27| 1| );
+ 28| 1|
+ 29| 1| some_string = Some(String::from("the string content"));
+ 30| 1| let
+ 31| 1| a
+ 32| 1| =
+ 33| 1| ||
+ 34| 0| {
+ 35| 0| let mut countdown = 0;
+ 36| 0| if is_false {
+ 37| 0| countdown = 10;
+ 38| 0| }
+ 39| 0| "alt string 2".to_owned()
+ 40| | };
+ 41| 1| println!(
+ 42| 1| "The string or alt: {}"
+ 43| 1| ,
+ 44| 1| some_string
+ 45| 1| .
+ 46| 1| unwrap_or_else
+ 47| 1| (
+ 48| 1| a
+ 49| 1| )
+ 50| 1| );
+ 51| 1|
+ 52| 1| some_string = None;
+ 53| 1| println!(
+ 54| 1| "The string or alt: {}"
+ 55| 1| ,
+ 56| 1| some_string
+ 57| 1| .
+ 58| 1| unwrap_or_else
+ 59| 1| (
+ 60| 1| ||
+ 61| 1| {
+ 62| 1| let mut countdown = 0;
+ 63| 1| if is_false {
+ 64| 0| countdown = 10;
+ 65| 1| }
+ 66| 1| "alt string 3".to_owned()
+ 67| 1| }
+ 68| 1| )
+ 69| 1| );
+ 70| 1|
+ 71| 1| some_string = None;
+ 72| 1| let
+ 73| 1| a
+ 74| 1| =
+ 75| 1| ||
+ 76| 1| {
+ 77| 1| let mut countdown = 0;
+ 78| 1| if is_false {
+ 79| 0| countdown = 10;
+ 80| 1| }
+ 81| 1| "alt string 4".to_owned()
+ 82| | };
+ 83| 1| println!(
+ 84| 1| "The string or alt: {}"
+ 85| 1| ,
+ 86| 1| some_string
+ 87| 1| .
+ 88| 1| unwrap_or_else
+ 89| 1| (
+ 90| 1| a
+ 91| 1| )
+ 92| 1| );
+ 93| 1|
+ 94| 1| let
+ 95| 1| quote_closure
+ 96| 1| =
+ 97| 1| |val|
+ 98| 5| {
+ 99| 5| let mut countdown = 0;
+ 100| 5| if is_false {
+ 101| 0| countdown = 10;
+ 102| 5| }
+ 103| 5| format!("'{}'", val)
+ 104| | };
+ 105| 1| println!(
+ 106| 1| "Repeated, quoted string: {:?}"
+ 107| 1| ,
+ 108| 1| std::iter::repeat("repeat me")
+ 109| 1| .take(5)
+ 110| 1| .map
+ 111| 1| (
+ 112| 1| quote_closure
+ 113| 1| )
+ 114| 1| .collect::<Vec<_>>()
+ 115| 1| );
+ 116| 1|
+ 117| 1| let
+ 118| 1| _unused_closure
+ 119| | =
+ 120| | |
+ 121| | mut countdown
+ 122| | |
+ 123| 0| {
+ 124| 0| if is_false {
+ 125| 0| countdown = 10;
+ 126| 0| }
+ 127| 0| "closure should be unused".to_owned()
+ 128| | };
+ 129| |
+ 130| 1| let mut countdown = 10;
+ 131| 1| let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+ ^0
+ 132| |
+ 133| |
+ 134| 1| let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+ 135| 1| let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+ ^0
+ 136| 1| let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+ ^0
+ 137| |
+ 138| |
+ 139| |
+ 140| |
+ 141| 1| let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+ ^0
+ 142| |
+ 143| 1| let _shortish_unused_closure = | _unused_arg: u8 | {
+ 144| 0| println!("not called")
+ 145| 0| };
+ 146| |
+ 147| 1| let _as_short_unused_closure = |
+ 148| | _unused_arg: u8
+ 149| 0| | { println!("not called") };
+ 150| |
+ 151| 1| let _almost_as_short_unused_closure = |
+ 152| | _unused_arg: u8
+ 153| 0| | { println!("not called") }
+ 154| | ;
+ 155| |
+ 156| |
+ 157| |
+ 158| |
+ 159| |
+ 160| 1| let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+ 161| 0|println!("not called")
+ 162| | ;
+ 163| |
+ 164| 1| let _short_unused_closure_line_break_no_block2 =
+ 165| | | _unused_arg: u8 |
+ 166| 0| println!(
+ 167| 0| "not called"
+ 168| 0| )
+ 169| | ;
+ 170| |
+ 171| 1| let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+ 172| | | _unused_arg: u8 |
+ 173| 0| println!(
+ 174| 0| "not called: {}",
+ 175| 0| if is_true { "check" } else { "me" }
+ 176| | )
+ 177| | ;
+ 178| |
+ 179| 1| let short_used_not_covered_closure_line_break_block_embedded_branch =
+ 180| 1| | _unused_arg: u8 |
+ 181| 0| {
+ 182| 0| println!(
+ 183| 0| "not called: {}",
+ 184| 0| if is_true { "check" } else { "me" }
+ 185| | )
+ 186| | }
+ 187| | ;
+ 188| |
+ 189| 1| let short_used_covered_closure_line_break_no_block_embedded_branch =
+ 190| 1| | _unused_arg: u8 |
+ 191| 1| println!(
+ 192| 1| "not called: {}",
+ 193| 1| if is_true { "check" } else { "me" }
+ ^0
+ 194| | )
+ 195| | ;
+ 196| |
+ 197| 1| let short_used_covered_closure_line_break_block_embedded_branch =
+ 198| 1| | _unused_arg: u8 |
+ 199| 1| {
+ 200| 1| println!(
+ 201| 1| "not called: {}",
+ 202| 1| if is_true { "check" } else { "me" }
+ ^0
+ 203| | )
+ 204| | }
+ 205| | ;
+ 206| |
+ 207| 1| if is_false {
+ 208| 0| short_used_not_covered_closure_macro(0);
+ 209| 0| short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+ 210| 0| short_used_not_covered_closure_line_break_block_embedded_branch(0);
+ 211| 1| }
+ 212| 1| short_used_covered_closure_macro(0);
+ 213| 1| short_used_covered_closure_line_break_no_block_embedded_branch(0);
+ 214| 1| short_used_covered_closure_line_break_block_embedded_branch(0);
+ 215| 1|}
+
--- /dev/null
+ 1| |// compile-flags: --edition=2018
+ 2| |#![feature(no_coverage)]
+ 3| |
+ 4| |macro_rules! bail {
+ 5| | ($msg:literal $(,)?) => {
+ 6| | if $msg.len() > 0 {
+ 7| | println!("no msg");
+ 8| | } else {
+ 9| | println!($msg);
+ 10| | }
+ 11| | return Err(String::from($msg));
+ 12| | };
+ 13| |}
+ 14| |
+ 15| |macro_rules! on_error {
+ 16| | ($value:expr, $error_message:expr) => {
+ 17| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+ 18| | let message = format!($error_message, e);
+ 19| | if message.len() > 0 {
+ 20| | println!("{}", message);
+ 21| | Ok(String::from("ok"))
+ 22| | } else {
+ 23| | bail!("error");
+ 24| | }
+ 25| | })
+ 26| | };
+ 27| |}
+ 28| |
+ 29| 1|fn load_configuration_files() -> Result<String, String> {
+ 30| 1| Ok(String::from("config"))
+ 31| 1|}
+ 32| |
+ 33| 1|pub fn main() -> Result<(), String> {
+ 34| 1| println!("Starting service");
+ 35| 1| let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+ ^0
+ 36| |
+ 37| 1| let startup_delay_duration = String::from("arg");
+ 38| 1| let _ = (config, startup_delay_duration);
+ 39| 1| Ok(())
+ 40| 1|}
+
--- /dev/null
+ 1| |// compile-flags: --edition=2018
+ 2| |#![feature(no_coverage)]
+ 3| |
+ 4| |macro_rules! bail {
+ 5| | ($msg:literal $(,)?) => {
+ 6| | if $msg.len() > 0 {
+ 7| | println!("no msg");
+ 8| | } else {
+ 9| | println!($msg);
+ 10| | }
+ 11| | return Err(String::from($msg));
+ 12| | };
+ 13| |}
+ 14| |
+ 15| |macro_rules! on_error {
+ 16| | ($value:expr, $error_message:expr) => {
+ 17| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+ 18| | let message = format!($error_message, e);
+ 19| | if message.len() > 0 {
+ 20| | println!("{}", message);
+ 21| | Ok(String::from("ok"))
+ 22| | } else {
+ 23| | bail!("error");
+ 24| | }
+ 25| | })
+ 26| | };
+ 27| |}
+ 28| |
+ 29| 1|fn load_configuration_files() -> Result<String, String> {
+ 30| 1| Ok(String::from("config"))
+ 31| 1|}
+ 32| |
+ 33| 1|pub async fn test() -> Result<(), String> {
+ 34| 1| println!("Starting service");
+ 35| 1| let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+ ^0
+ 36| |
+ 37| 1| let startup_delay_duration = String::from("arg");
+ 38| 1| let _ = (config, startup_delay_duration);
+ 39| 1| Ok(())
+ 40| 1|}
+ 41| |
+ 42| |#[no_coverage]
+ 43| |fn main() {
+ 44| | executor::block_on(test());
+ 45| |}
+ 46| |
+ 47| |mod executor {
+ 48| | use core::{
+ 49| | future::Future,
+ 50| | pin::Pin,
+ 51| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ 52| | };
+ 53| |
+ 54| | #[no_coverage]
+ 55| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ 56| | let mut future = unsafe { Pin::new_unchecked(&mut future) };
+ 57| | use std::hint::unreachable_unchecked;
+ 58| | static VTABLE: RawWakerVTable = RawWakerVTable::new(
+ 59| |
+ 60| | #[no_coverage]
+ 61| | |_| unsafe { unreachable_unchecked() }, // clone
+ 62| |
+ 63| | #[no_coverage]
+ 64| | |_| unsafe { unreachable_unchecked() }, // wake
+ 65| |
+ 66| | #[no_coverage]
+ 67| | |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+ 68| |
+ 69| | #[no_coverage]
+ 70| | |_| (),
+ 71| | );
+ 72| | let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+ 73| | let mut context = Context::from_waker(&waker);
+ 74| |
+ 75| | loop {
+ 76| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ 77| | break val;
+ 78| | }
+ 79| | }
+ 80| | }
+ 81| |}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| let mut countdown = 0;
+ 5| 1| if true {
+ 6| 1| countdown = 10;
+ 7| 1| }
+ ^0
+ 8| |
+ 9| | const B: u32 = 100;
+ 10| 1| let x = if countdown > 7 {
+ 11| 1| countdown -= 4;
+ 12| 1| B
+ 13| 0| } else if countdown > 2 {
+ 14| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 15| 0| countdown = 0;
+ 16| 0| }
+ 17| 0| countdown -= 5;
+ 18| 0| countdown
+ 19| | } else {
+ 20| 0| return;
+ 21| | };
+ 22| |
+ 23| 1| let mut countdown = 0;
+ 24| 1| if true {
+ 25| 1| countdown = 10;
+ 26| 1| }
+ ^0
+ 27| |
+ 28| 1| if countdown > 7 {
+ 29| 1| countdown -= 4;
+ 30| 1| } else if countdown > 2 {
+ ^0
+ 31| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 32| 0| countdown = 0;
+ 33| 0| }
+ 34| 0| countdown -= 5;
+ 35| | } else {
+ 36| 0| return;
+ 37| | }
+ 38| |
+ 39| 1| if true {
+ 40| 1| let mut countdown = 0;
+ 41| 1| if true {
+ 42| 1| countdown = 10;
+ 43| 1| }
+ ^0
+ 44| |
+ 45| 1| if countdown > 7 {
+ 46| 1| countdown -= 4;
+ 47| 1| }
+ 48| 0| else if countdown > 2 {
+ 49| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 50| 0| countdown = 0;
+ 51| 0| }
+ 52| 0| countdown -= 5;
+ 53| | } else {
+ 54| 0| return;
+ 55| | }
+ 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
+ 65| 0| countdown -= 4;
+ 66| 1| } else if countdown > 2 {
+ 67| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 68| 0| countdown = 0;
+ 69| 0| }
+ 70| 0| countdown -= 5;
+ 71| | } else {
+ 72| 1| let should_be_reachable = countdown;
+ 73| 1| println!("reached");
+ 74| 1| return;
+ 75| | };
+ 76| |
+ 77| 0| let w = if countdown > 7 {
+ 78| 0| countdown -= 4;
+ 79| 0| } else if countdown > 2 {
+ 80| 0| if countdown < 1 || countdown > 5 || countdown != 9 {
+ 81| 0| countdown = 0;
+ 82| 0| }
+ 83| 0| countdown -= 5;
+ 84| | } else {
+ 85| 0| return;
+ 86| | };
+ 87| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| let is_true = std::env::args().len() == 1;
+ 5| 1|
+ 6| 1| let mut x = 0;
+ 7| 11| for _ in 0..10 {
+ 8| 10| match is_true {
+ 9| | true => {
+ 10| 10| continue;
+ 11| | }
+ 12| 0| _ => {
+ 13| 0| x = 1;
+ 14| 0| }
+ 15| 0| }
+ 16| 0| x = 3;
+ 17| | }
+ 18| 11| for _ in 0..10 {
+ 19| 10| match is_true {
+ 20| 0| false => {
+ 21| 0| x = 1;
+ 22| 0| }
+ 23| | _ => {
+ 24| 10| continue;
+ 25| | }
+ 26| | }
+ 27| 0| x = 3;
+ 28| | }
+ 29| 11| for _ in 0..10 {
+ 30| 10| match is_true {
+ 31| 10| true => {
+ 32| 10| x = 1;
+ 33| 10| }
+ 34| | _ => {
+ 35| 0| continue;
+ 36| | }
+ 37| | }
+ 38| 10| x = 3;
+ 39| | }
+ 40| 11| for _ in 0..10 {
+ 41| 10| if is_true {
+ 42| 10| continue;
+ 43| 0| }
+ 44| 0| x = 3;
+ 45| | }
+ 46| 11| for _ in 0..10 {
+ 47| 10| match is_true {
+ 48| 0| false => {
+ 49| 0| x = 1;
+ 50| 0| }
+ 51| 10| _ => {
+ 52| 10| let _ = x;
+ 53| 10| }
+ 54| | }
+ 55| 10| x = 3;
+ 56| | }
+ 57| 1| for _ in 0..10 {
+ 58| 1| match is_true {
+ 59| 0| false => {
+ 60| 0| x = 1;
+ 61| 0| }
+ 62| | _ => {
+ 63| 1| break;
+ 64| | }
+ 65| | }
+ 66| 0| x = 3;
+ 67| | }
+ 68| | let _ = x;
+ 69| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 0|pub fn unused_pub_fn_not_in_library() {
+ 4| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 0| // dependent conditions.
+ 7| 0| let is_true = std::env::args().len() == 1;
+ 8| 0|
+ 9| 0| let mut countdown = 0;
+ 10| 0| if is_true {
+ 11| 0| countdown = 10;
+ 12| 0| }
+ 13| 0|}
+ 14| |
+ 15| 0|fn unused_fn() {
+ 16| 0| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 17| 0| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 18| 0| // dependent conditions.
+ 19| 0| let is_true = std::env::args().len() == 1;
+ 20| 0|
+ 21| 0| let mut countdown = 0;
+ 22| 0| if is_true {
+ 23| 0| countdown = 10;
+ 24| 0| }
+ 25| 0|}
+ 26| |
+ 27| 1|fn main() {
+ 28| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 29| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 30| 1| // dependent conditions.
+ 31| 1| let is_true = std::env::args().len() == 1;
+ 32| 1|
+ 33| 1| let mut countdown = 0;
+ 34| 1| if is_true {
+ 35| 1| countdown = 10;
+ 36| 1| }
+ ^0
+ 37| 1|}
+
--- /dev/null
+../coverage/doctest.rs:
+ 1| |//! This test ensures that code from doctests is properly re-mapped.
+ 2| |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+ 3| |//!
+ 4| |//! Just some random code:
+ 5| 1|//! ```
+ 6| 1|//! if true {
+ 7| |//! // this is executed!
+ 8| 1|//! assert_eq!(1, 1);
+ 9| |//! } else {
+ 10| |//! // this is not!
+ 11| 0|//! assert_eq!(1, 2);
+ 12| |//! }
+ 13| 1|//! ```
+ 14| |//!
+ 15| |//! doctest testing external code:
+ 16| |//! ```
+ 17| 1|//! extern crate doctest_crate;
+ 18| 1|//! doctest_crate::fn_run_in_doctests(1);
+ 19| 1|//! ```
+ 20| |//!
+ 21| |//! doctest returning a result:
+ 22| 1|//! ```
+ 23| 2|//! #[derive(Debug, PartialEq)]
+ ^1
+ ------------------
+ | Unexecuted instantiation: <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::ne
+ ------------------
+ | <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::eq:
+ | 23| 2|//! #[derive(Debug, PartialEq)]
+ ------------------
+ 24| 1|//! struct SomeError {
+ 25| 1|//! msg: String,
+ 26| 1|//! }
+ 27| 1|//! let mut res = Err(SomeError { msg: String::from("a message") });
+ 28| 1|//! if res.is_ok() {
+ 29| 0|//! res?;
+ 30| |//! } else {
+ 31| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+ 32| 1|//! println!("{:?}", res);
+ 33| 1|//! }
+ ^0
+ 34| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+ 35| 1|//! res = Ok(1);
+ 36| 1|//! }
+ ^0
+ 37| 1|//! res = Ok(0);
+ 38| |//! }
+ 39| |//! // need to be explicit because rustdoc cant infer the return type
+ 40| 1|//! Ok::<(), SomeError>(())
+ 41| 1|//! ```
+ 42| |//!
+ 43| |//! doctest with custom main:
+ 44| |//! ```
+ 45| 1|//! fn some_func() {
+ 46| 1|//! println!("called some_func()");
+ 47| 1|//! }
+ 48| |//!
+ 49| 0|//! #[derive(Debug)]
+ 50| |//! struct SomeError;
+ 51| |//!
+ 52| |//! extern crate doctest_crate;
+ 53| |//!
+ 54| 1|//! fn doctest_main() -> Result<(), SomeError> {
+ 55| 1|//! some_func();
+ 56| 1|//! doctest_crate::fn_run_in_doctests(2);
+ 57| 1|//! Ok(())
+ 58| 1|//! }
+ 59| |//!
+ 60| |//! // this `main` is not shown as covered, as it clashes with all the other
+ 61| |//! // `main` functions that were automatically generated for doctests
+ 62| |//! fn main() -> Result<(), SomeError> {
+ 63| |//! doctest_main()
+ 64| |//! }
+ 65| |//! ```
+ 66| |
+ 67| |/// doctest attached to fn testing external code:
+ 68| |/// ```
+ 69| 1|/// extern crate doctest_crate;
+ 70| 1|/// doctest_crate::fn_run_in_doctests(3);
+ 71| 1|/// ```
+ 72| |///
+ 73| 1|fn main() {
+ 74| 1| if true {
+ 75| 1| assert_eq!(1, 1);
+ 76| | } else {
+ 77| 0| assert_eq!(1, 2);
+ 78| | }
+ 79| 1|}
+ 80| |
+ 81| |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+ 82| |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+ 83| |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+ 84| |//
+ 85| |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+ 86| |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+ 87| |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+ 88| |// one character past, the `if` block's closing brace. In both cases, these are most likely off
+ 89| |// by the number of characters stripped from the beginning of each doc comment line: indent
+ 90| |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+ 91| |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+ 92| |// more pronounced, and show up in more places, with background color used to show some distinct
+ 93| |// code regions with different coverage counts.
+ 94| |//
+ 95| |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+ 96| |// character stripped from the beginning of doc comment lines with a space. This will give coverage
+ 97| |// results the correct column offsets, and I think it should compile correctly, but I don't know
+ 98| |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+ 99| |// if the indentation changed. I don't know if there is a more viable solution.
+
+../coverage/lib/doctest_crate.rs:
+ 1| |/// A function run only from within doctests
+ 2| 3|pub fn fn_run_in_doctests(conditional: usize) {
+ 3| 3| match conditional {
+ 4| 1| 1 => assert_eq!(1, 1), // this is run,
+ 5| 1| 2 => assert_eq!(1, 1), // this,
+ 6| 1| 3 => assert_eq!(1, 1), // and this too
+ 7| 0| _ => assert_eq!(1, 2), // however this is not
+ 8| | }
+ 9| 3|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| |struct Firework {
+ 5| | strength: i32,
+ 6| |}
+ 7| |
+ 8| |impl Drop for Firework {
+ 9| 2| fn drop(&mut self) {
+ 10| 2| println!("BOOM times {}!!!", self.strength);
+ 11| 2| }
+ 12| |}
+ 13| |
+ 14| 1|fn main() -> Result<(),u8> {
+ 15| 1| let _firecracker = Firework { strength: 1 };
+ 16| 1|
+ 17| 1| let _tnt = Firework { strength: 100 };
+ 18| 1|
+ 19| 1| if true {
+ 20| 1| println!("Exiting with error...");
+ 21| 1| return Err(1);
+ 22| 0| }
+ 23| 0|
+ 24| 0| let _ = Firework { strength: 1000 };
+ 25| 0|
+ 26| 0| Ok(())
+ 27| 1|}
+ 28| |
+ 29| |// Expected program output:
+ 30| |// Exiting with error...
+ 31| |// BOOM times 100!!!
+ 32| |// BOOM times 1!!!
+ 33| |// Error: 1
+
--- /dev/null
+ 1| |#![feature(generators, generator_trait)]
+ 2| |
+ 3| |use std::ops::{Generator, GeneratorState};
+ 4| |use std::pin::Pin;
+ 5| |
+ 6| |// The following implementation of a function called from a `yield` statement
+ 7| |// (apparently requiring the Result and the `String` type or constructor)
+ 8| |// creates conditions where the `generator::StateTransform` MIR transform will
+ 9| |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+ 10| |// to handle this condition, and still report dead block coverage.
+ 11| 1|fn get_u32(val: bool) -> Result<u32, String> {
+ 12| 1| if val { Ok(1) } else { Err(String::from("some error")) }
+ ^0
+ 13| 1|}
+ 14| |
+ 15| 1|fn main() {
+ 16| 1| let is_true = std::env::args().len() == 1;
+ 17| 1| let mut generator = || {
+ 18| 1| yield get_u32(is_true);
+ 19| 1| return "foo";
+ 20| | };
+ 21| |
+ 22| 1| match Pin::new(&mut generator).resume(()) {
+ 23| 1| GeneratorState::Yielded(Ok(1)) => {}
+ 24| 0| _ => panic!("unexpected return from resume"),
+ 25| | }
+ 26| 1| match Pin::new(&mut generator).resume(()) {
+ 27| 1| GeneratorState::Complete("foo") => {}
+ 28| 0| _ => panic!("unexpected return from resume"),
+ 29| | }
+ 30| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| |struct Firework<T> where T: Copy + std::fmt::Display {
+ 5| | strength: T,
+ 6| |}
+ 7| |
+ 8| |impl<T> Firework<T> where T: Copy + std::fmt::Display {
+ 9| | #[inline(always)]
+ 10| 3| fn set_strength(&mut self, new_strength: T) {
+ 11| 3| self.strength = new_strength;
+ 12| 3| }
+ ------------------
+ | <generics::Firework<i32>>::set_strength:
+ | 10| 1| fn set_strength(&mut self, new_strength: T) {
+ | 11| 1| self.strength = new_strength;
+ | 12| 1| }
+ ------------------
+ | <generics::Firework<f64>>::set_strength:
+ | 10| 2| fn set_strength(&mut self, new_strength: T) {
+ | 11| 2| self.strength = new_strength;
+ | 12| 2| }
+ ------------------
+ 13| |}
+ 14| |
+ 15| |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+ 16| | #[inline(always)]
+ 17| 2| fn drop(&mut self) {
+ 18| 2| println!("BOOM times {}!!!", self.strength);
+ 19| 2| }
+ ------------------
+ | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
+ | 17| 1| fn drop(&mut self) {
+ | 18| 1| println!("BOOM times {}!!!", self.strength);
+ | 19| 1| }
+ ------------------
+ | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
+ | 17| 1| fn drop(&mut self) {
+ | 18| 1| println!("BOOM times {}!!!", self.strength);
+ | 19| 1| }
+ ------------------
+ 20| |}
+ 21| |
+ 22| 1|fn main() -> Result<(),u8> {
+ 23| 1| let mut firecracker = Firework { strength: 1 };
+ 24| 1| firecracker.set_strength(2);
+ 25| 1|
+ 26| 1| let mut tnt = Firework { strength: 100.1 };
+ 27| 1| tnt.set_strength(200.1);
+ 28| 1| tnt.set_strength(300.3);
+ 29| 1|
+ 30| 1| if true {
+ 31| 1| println!("Exiting with error...");
+ 32| 1| return Err(1);
+ 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:
+ 45| |// Exiting with error...
+ 46| |// BOOM times 100!!!
+ 47| |// BOOM times 1!!!
+ 48| |// Error: 1
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let
+ 8| 1| is_true
+ 9| 1| =
+ 10| 1| std::env::args().len()
+ 11| 1| ==
+ 12| 1| 1
+ 13| 1| ;
+ 14| 1| let
+ 15| 1| mut
+ 16| 1| countdown
+ 17| 1| =
+ 18| 1| 0
+ 19| 1| ;
+ 20| 1| if
+ 21| 1| is_true
+ 22| 1| {
+ 23| 1| countdown
+ 24| 1| =
+ 25| 1| 10
+ 26| 1| ;
+ 27| 1| }
+ ^0
+ 28| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 0;
+ 10| 1| if
+ 11| 1| is_true
+ 12| 1| {
+ 13| 1| countdown
+ 14| 1| =
+ 15| 1| 10
+ 16| 1| ;
+ 17| 1| }
+ 18| | else // Note coverage region difference without semicolon
+ 19| | {
+ 20| 0| countdown
+ 21| 0| =
+ 22| 0| 100
+ 23| | }
+ 24| |
+ 25| | if
+ 26| 1| is_true
+ 27| 1| {
+ 28| 1| countdown
+ 29| 1| =
+ 30| 1| 10
+ 31| 1| ;
+ 32| 1| }
+ 33| | else
+ 34| 0| {
+ 35| 0| countdown
+ 36| 0| =
+ 37| 0| 100
+ 38| 0| ;
+ 39| 0| }
+ 40| 1|}
+
--- /dev/null
+ 1| |// Regression test for issue #98833.
+ 2| |// compile-flags: -Zinline-mir -Cdebug-assertions=off
+ 3| |
+ 4| 1|fn main() {
+ 5| 1| println!("{}", live::<false>());
+ 6| 1|
+ 7| 1| let f = |x: bool| {
+ 8| | debug_assert!(
+ 9| | x
+ 10| | );
+ 11| 1| };
+ 12| 1| f(false);
+ 13| 1|}
+ 14| |
+ 15| |#[inline]
+ 16| 1|fn live<const B: bool>() -> u32 {
+ 17| 1| if B {
+ 18| 0| dead()
+ 19| | } else {
+ 20| 1| 0
+ 21| | }
+ 22| 1|}
+ 23| |
+ 24| |#[inline]
+ 25| 0|fn dead() -> u32 {
+ 26| 0| 42
+ 27| 0|}
+
--- /dev/null
+ 1| |// compile-flags: -Zinline-mir
+ 2| |
+ 3| |use std::fmt::Display;
+ 4| |
+ 5| 1|fn main() {
+ 6| 1| permutations(&['a', 'b', 'c']);
+ 7| 1|}
+ 8| |
+ 9| |#[inline(always)]
+ 10| 1|fn permutations<T: Copy + Display>(xs: &[T]) {
+ 11| 1| let mut ys = xs.to_owned();
+ 12| 1| permutate(&mut ys, 0);
+ 13| 1|}
+ 14| |
+ 15| 16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+ 16| 16| let n = length(xs);
+ 17| 16| if k == n {
+ 18| 6| display(xs);
+ 19| 10| } else if k < n {
+ 20| 15| for i in k..n {
+ ^10
+ 21| 15| swap(xs, i, k);
+ 22| 15| permutate(xs, k + 1);
+ 23| 15| swap(xs, i, k);
+ 24| 15| }
+ 25| 0| } else {
+ 26| 0| error();
+ 27| 0| }
+ 28| 16|}
+ 29| |
+ 30| 16|fn length<T>(xs: &[T]) -> usize {
+ 31| 16| xs.len()
+ 32| 16|}
+ 33| |
+ 34| |#[inline]
+ 35| 30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+ 36| 30| let t = xs[i];
+ 37| 30| xs[i] = xs[j];
+ 38| 30| xs[j] = t;
+ 39| 30|}
+ 40| |
+ 41| 6|fn display<T: Display>(xs: &[T]) {
+ 42| 24| for x in xs {
+ ^18
+ 43| 18| print!("{}", x);
+ 44| 18| }
+ 45| 6| println!();
+ 46| 6|}
+ 47| |
+ 48| |#[inline(always)]
+ 49| 0|fn error() {
+ 50| 0| panic!("error");
+ 51| 0|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables, dead_code)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 0;
+ 10| 1| if is_true {
+ 11| 1| countdown = 10;
+ 12| 1| }
+ ^0
+ 13| |
+ 14| | mod in_mod {
+ 15| | const IN_MOD_CONST: u32 = 1000;
+ 16| | }
+ 17| |
+ 18| 3| fn in_func(a: u32) {
+ 19| 3| let b = 1;
+ 20| 3| let c = a + b;
+ 21| 3| println!("c = {}", c)
+ 22| 3| }
+ 23| |
+ 24| | struct InStruct {
+ 25| | in_struct_field: u32,
+ 26| | }
+ 27| |
+ 28| | const IN_CONST: u32 = 1234;
+ 29| |
+ 30| | trait InTrait {
+ 31| | fn trait_func(&mut self, incr: u32);
+ 32| |
+ 33| 1| fn default_trait_func(&mut self) {
+ 34| 1| in_func(IN_CONST);
+ 35| 1| self.trait_func(IN_CONST);
+ 36| 1| }
+ 37| | }
+ 38| |
+ 39| | impl InTrait for InStruct {
+ 40| 1| fn trait_func(&mut self, incr: u32) {
+ 41| 1| self.in_struct_field += incr;
+ 42| 1| in_func(self.in_struct_field);
+ 43| 1| }
+ 44| | }
+ 45| |
+ 46| | type InType = String;
+ 47| |
+ 48| 1| if is_true {
+ 49| 1| in_func(countdown);
+ 50| 1| }
+ ^0
+ 51| |
+ 52| 1| let mut val = InStruct {
+ 53| 1| in_struct_field: 101,
+ 54| 1| };
+ 55| 1|
+ 56| 1| val.default_trait_func();
+ 57| 1|}
+
--- /dev/null
+ 1| |// Shows that rust-lang/rust/83601 is resolved
+ 2| |
+ 3| 3|#[derive(Debug, PartialEq, Eq)]
+ ^2
+ ------------------
+ | <issue_83601::Foo as core::cmp::PartialEq>::eq:
+ | 3| 2|#[derive(Debug, PartialEq, Eq)]
+ ------------------
+ | Unexecuted instantiation: <issue_83601::Foo as core::cmp::PartialEq>::ne
+ ------------------
+ 4| |struct Foo(u32);
+ 5| |
+ 6| 1|fn main() {
+ 7| 1| let bar = Foo(1);
+ 8| 1| assert_eq!(bar, Foo(1));
+ 9| 1| let baz = Foo(0);
+ 10| 1| assert_ne!(baz, Foo(1));
+ 11| 1| println!("{:?}", Foo(1));
+ 12| 1| println!("{:?}", bar);
+ 13| 1| println!("{:?}", baz);
+ 14| 1|}
+
--- /dev/null
+ 1| |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+ 2| |
+ 3| |// expect-exit-status-101
+ 4| 21|#[derive(PartialEq, Eq)]
+ ------------------
+ | <issue_84561::Foo as core::cmp::PartialEq>::eq:
+ | 4| 21|#[derive(PartialEq, Eq)]
+ ------------------
+ | Unexecuted instantiation: <issue_84561::Foo as core::cmp::PartialEq>::ne
+ ------------------
+ 5| |struct Foo(u32);
+ 6| 1|fn test3() {
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1| let bar = Foo(1);
+ 9| 1| assert_eq!(bar, Foo(1));
+ 10| 1| let baz = Foo(0);
+ 11| 1| assert_ne!(baz, Foo(1));
+ 12| 1| println!("{:?}", Foo(1));
+ 13| 1| println!("{:?}", bar);
+ 14| 1| println!("{:?}", baz);
+ 15| 1|
+ 16| 1| assert_eq!(Foo(1), Foo(1));
+ 17| 1| assert_ne!(Foo(0), Foo(1));
+ 18| 1| assert_eq!(Foo(2), Foo(2));
+ 19| 1| let bar = Foo(0);
+ 20| 1| assert_ne!(bar, Foo(3));
+ 21| 1| assert_ne!(Foo(0), Foo(4));
+ 22| 1| assert_eq!(Foo(3), Foo(3), "with a message");
+ ^0
+ 23| 1| println!("{:?}", bar);
+ 24| 1| println!("{:?}", Foo(1));
+ 25| 1|
+ 26| 1| assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+ ^0 ^0 ^0
+ 27| 1| assert_ne!(
+ 28| | Foo(0)
+ 29| | ,
+ 30| | Foo(5)
+ 31| | ,
+ 32| 0| "{}"
+ 33| 0| ,
+ 34| 0| if
+ 35| 0| is_true
+ 36| | {
+ 37| 0| "true message"
+ 38| | } else {
+ 39| 0| "false message"
+ 40| | }
+ 41| | );
+ 42| |
+ 43| 1| let is_true = std::env::args().len() == 1;
+ 44| 1|
+ 45| 1| assert_eq!(
+ 46| 1| Foo(1),
+ 47| 1| Foo(1)
+ 48| 1| );
+ 49| 1| assert_ne!(
+ 50| 1| Foo(0),
+ 51| 1| Foo(1)
+ 52| 1| );
+ 53| 1| assert_eq!(
+ 54| 1| Foo(2),
+ 55| 1| Foo(2)
+ 56| 1| );
+ 57| 1| let bar = Foo(1);
+ 58| 1| assert_ne!(
+ 59| 1| bar,
+ 60| 1| Foo(3)
+ 61| 1| );
+ 62| 1| if is_true {
+ 63| 1| assert_ne!(
+ 64| 1| Foo(0),
+ 65| 1| Foo(4)
+ 66| 1| );
+ 67| | } else {
+ 68| 0| assert_eq!(
+ 69| 0| Foo(3),
+ 70| 0| Foo(3)
+ 71| 0| );
+ 72| | }
+ 73| 1| if is_true {
+ 74| 1| assert_ne!(
+ 75| | Foo(0),
+ 76| | Foo(4),
+ 77| 0| "with a message"
+ 78| | );
+ 79| | } else {
+ 80| 0| assert_eq!(
+ 81| | Foo(3),
+ 82| | Foo(3),
+ 83| 0| "with a message"
+ 84| | );
+ 85| | }
+ 86| 1| assert_ne!(
+ 87| 1| if is_true {
+ 88| 1| Foo(0)
+ 89| | } else {
+ 90| 0| Foo(1)
+ 91| | },
+ 92| | Foo(5)
+ 93| | );
+ 94| 1| assert_ne!(
+ 95| 1| Foo(5),
+ 96| 1| if is_true {
+ 97| 1| Foo(0)
+ 98| | } else {
+ 99| 0| Foo(1)
+ 100| | }
+ 101| | );
+ 102| 1| assert_ne!(
+ 103| 1| if is_true {
+ 104| 1| assert_eq!(
+ 105| 1| Foo(3),
+ 106| 1| Foo(3)
+ 107| 1| );
+ 108| 1| Foo(0)
+ 109| | } else {
+ 110| 0| assert_ne!(
+ 111| 0| if is_true {
+ 112| 0| Foo(0)
+ 113| | } else {
+ 114| 0| Foo(1)
+ 115| | },
+ 116| | Foo(5)
+ 117| | );
+ 118| 0| Foo(1)
+ 119| | },
+ 120| | Foo(5),
+ 121| 0| "with a message"
+ 122| | );
+ 123| 1| assert_eq!(
+ 124| | Foo(1),
+ 125| | Foo(3),
+ 126| 1| "this assert should fail"
+ 127| | );
+ 128| 0| assert_eq!(
+ 129| | Foo(3),
+ 130| | Foo(3),
+ 131| 0| "this assert should not be reached"
+ 132| | );
+ 133| 0|}
+ 134| |
+ 135| |impl std::fmt::Debug for Foo {
+ 136| | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ 137| 7| write!(f, "try and succeed")?;
+ ^0
+ 138| 7| Ok(())
+ 139| 7| }
+ 140| |}
+ 141| |
+ 142| |static mut DEBUG_LEVEL_ENABLED: bool = false;
+ 143| |
+ 144| |macro_rules! debug {
+ 145| | ($($arg:tt)+) => (
+ 146| | if unsafe { DEBUG_LEVEL_ENABLED } {
+ 147| | println!($($arg)+);
+ 148| | }
+ 149| | );
+ 150| |}
+ 151| |
+ 152| 1|fn test1() {
+ 153| 1| debug!("debug is enabled");
+ ^0
+ 154| 1| debug!("debug is enabled");
+ ^0
+ 155| 1| let _ = 0;
+ 156| 1| debug!("debug is enabled");
+ ^0
+ 157| 1| unsafe {
+ 158| 1| DEBUG_LEVEL_ENABLED = true;
+ 159| 1| }
+ 160| 1| debug!("debug is enabled");
+ 161| 1|}
+ 162| |
+ 163| |macro_rules! call_debug {
+ 164| | ($($arg:tt)+) => (
+ 165| 1| fn call_print(s: &str) {
+ 166| 1| print!("{}", s);
+ 167| 1| }
+ 168| |
+ 169| | call_print("called from call_debug: ");
+ 170| | debug!($($arg)+);
+ 171| | );
+ 172| |}
+ 173| |
+ 174| 1|fn test2() {
+ 175| 1| call_debug!("debug is enabled");
+ 176| 1|}
+ 177| |
+ 178| 1|fn main() {
+ 179| 1| test1();
+ 180| 1| test2();
+ 181| 1| test3();
+ 182| 1|}
+
--- /dev/null
+../coverage/issue-85461.rs:
+ 1| |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+ 2| |
+ 3| |extern crate inline_always_with_dead_code;
+ 4| |
+ 5| |use inline_always_with_dead_code::{bar, baz};
+ 6| |
+ 7| 1|fn main() {
+ 8| 1| bar::call_me();
+ 9| 1| baz::call_me();
+ 10| 1|}
+
+../coverage/lib/inline_always_with_dead_code.rs:
+ 1| |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+ 2| |
+ 3| |#![allow(dead_code)]
+ 4| |
+ 5| |mod foo {
+ 6| | #[inline(always)]
+ 7| 2| pub fn called() { }
+ 8| |
+ 9| 0| fn uncalled() { }
+ 10| |}
+ 11| |
+ 12| |pub mod bar {
+ 13| 1| pub fn call_me() {
+ 14| 1| super::foo::called();
+ 15| 1| }
+ 16| |}
+ 17| |
+ 18| |pub mod baz {
+ 19| 1| pub fn call_me() {
+ 20| 1| super::foo::called();
+ 21| 1| }
+ 22| |}
+
--- /dev/null
+ 1| |// Regression test for #93054: Functions using uninhabited types often only have a single,
+ 2| |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+ 3| |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+ 4| |
+ 5| |// compile-flags: --edition=2021
+ 6| |
+ 7| |enum Never { }
+ 8| |
+ 9| |impl Never {
+ 10| | fn foo(self) {
+ 11| | match self { }
+ 12| | make().map(|never| match never { });
+ 13| | }
+ 14| |
+ 15| | fn bar(&self) {
+ 16| | match *self { }
+ 17| | }
+ 18| |}
+ 19| |
+ 20| 0|async fn foo2(never: Never) {
+ 21| | match never { }
+ 22| |}
+ 23| |
+ 24| 0|fn make() -> Option<Never> {
+ 25| 0| None
+ 26| 0|}
+ 27| |
+ 28| 1|fn main() { }
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let (mut a, mut b, mut c) = (0, 0, 0);
+ 10| 1| if is_true {
+ 11| 1| a = 1;
+ 12| 1| b = 10;
+ 13| 1| c = 100;
+ 14| 1| }
+ ^0
+ 15| | let
+ 16| 1| somebool
+ 17| | =
+ 18| 1| a < b
+ 19| | ||
+ 20| 0| b < c
+ 21| | ;
+ 22| | let
+ 23| 1| somebool
+ 24| | =
+ 25| 1| b < a
+ 26| | ||
+ 27| 1| b < c
+ 28| | ;
+ 29| 1| let somebool = a < b && b < c;
+ 30| 1| let somebool = b < a && b < c;
+ ^0
+ 31| |
+ 32| | if
+ 33| 1| !
+ 34| 1| is_true
+ 35| 0| {
+ 36| 0| a = 2
+ 37| 0| ;
+ 38| 1| }
+ 39| |
+ 40| | if
+ 41| 1| is_true
+ 42| 1| {
+ 43| 1| b = 30
+ 44| 1| ;
+ 45| 1| }
+ 46| | else
+ 47| 0| {
+ 48| 0| c = 400
+ 49| 0| ;
+ 50| 0| }
+ 51| |
+ 52| 1| if !is_true {
+ 53| 0| a = 2;
+ 54| 1| }
+ 55| |
+ 56| 1| if is_true {
+ 57| 1| b = 30;
+ 58| 1| } else {
+ 59| 0| c = 400;
+ 60| 0| }
+ 61| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| let result
+ 5| 1| =
+ 6| 1| loop
+ 7| 1| {
+ 8| 1| break
+ 9| 1| 10
+ 10| 1| ;
+ 11| 1| }
+ 12| 1| ;
+ 13| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables, while_true)]
+ 2| |
+ 3| |// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+ 4| |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+ 5| |
+ 6| |struct DebugTest;
+ 7| |
+ 8| |impl std::fmt::Debug for DebugTest {
+ 9| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ 10| 1| if true {
+ 11| 1| if false {
+ 12| 0| while true {
+ 13| 0| }
+ 14| 1| }
+ 15| 1| write!(f, "cool")?;
+ ^0
+ 16| 0| } else {
+ 17| 0| }
+ 18| |
+ 19| 11| for i in 0..10 {
+ ^10
+ 20| 10| if true {
+ 21| 10| if false {
+ 22| 0| while true {}
+ 23| 10| }
+ 24| 10| write!(f, "cool")?;
+ ^0
+ 25| 0| } else {
+ 26| 0| }
+ 27| | }
+ 28| 1| Ok(())
+ 29| 1| }
+ 30| |}
+ 31| |
+ 32| |struct DisplayTest;
+ 33| |
+ 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| 0| } else {
+ 38| 1| if false {
+ 39| 0| while true {}
+ 40| 1| }
+ 41| 1| write!(f, "cool")?;
+ ^0
+ 42| | }
+ 43| 11| for i in 0..10 {
+ ^10
+ 44| 10| if false {
+ 45| 0| } else {
+ 46| 10| if false {
+ 47| 0| while true {}
+ 48| 10| }
+ 49| 10| write!(f, "cool")?;
+ ^0
+ 50| | }
+ 51| | }
+ 52| 1| Ok(())
+ 53| 1| }
+ 54| |}
+ 55| |
+ 56| 1|fn main() {
+ 57| 1| let debug_test = DebugTest;
+ 58| 1| println!("{:?}", debug_test);
+ 59| 1| let display_test = DisplayTest;
+ 60| 1| println!("{}", display_test);
+ 61| 1|}
+
--- /dev/null
+ 1| |#![feature(or_patterns)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut a: u8 = 0;
+ 10| 1| let mut b: u8 = 0;
+ 11| 1| if is_true {
+ 12| 1| a = 2;
+ 13| 1| b = 0;
+ 14| 1| }
+ ^0
+ 15| 1| match (a, b) {
+ 16| | // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+ 17| | // This test confirms a fix for Issue #79569.
+ 18| 0| (0 | 1, 2 | 3) => {}
+ 19| 1| _ => {}
+ 20| | }
+ 21| 1| if is_true {
+ 22| 1| a = 0;
+ 23| 1| b = 0;
+ 24| 1| }
+ ^0
+ 25| 1| match (a, b) {
+ 26| 0| (0 | 1, 2 | 3) => {}
+ 27| 1| _ => {}
+ 28| | }
+ 29| 1| if is_true {
+ 30| 1| a = 2;
+ 31| 1| b = 2;
+ 32| 1| }
+ ^0
+ 33| 1| match (a, b) {
+ 34| 0| (0 | 1, 2 | 3) => {}
+ 35| 1| _ => {}
+ 36| | }
+ 37| 1| if is_true {
+ 38| 1| a = 0;
+ 39| 1| b = 2;
+ 40| 1| }
+ ^0
+ 41| 1| match (a, b) {
+ 42| 1| (0 | 1, 2 | 3) => {}
+ 43| 0| _ => {}
+ 44| | }
+ 45| 1|}
+
--- /dev/null
+ 1| 1|fn main() {
+ 2| 1| let is_true = std::env::args().len() == 1;
+ 3| 1| let mut countdown = 10;
+ 4| |
+ 5| 1| 'outer: while countdown > 0 {
+ 6| 1| let mut a = 100;
+ 7| 1| let mut b = 100;
+ 8| 3| for _ in 0..50 {
+ 9| 3| if a < 30 {
+ 10| 0| break;
+ 11| 3| }
+ 12| 3| a -= 5;
+ 13| 3| b -= 5;
+ 14| 3| if b < 90 {
+ 15| 1| a -= 10;
+ 16| 1| if is_true {
+ 17| 1| break 'outer;
+ 18| 0| } else {
+ 19| 0| a -= 2;
+ 20| 0| }
+ 21| 2| }
+ 22| | }
+ 23| 0| countdown -= 1;
+ 24| | }
+ 25| 1|}
+
--- /dev/null
+ 1| |// Enables `no_coverage` on the entire crate
+ 2| |#![feature(no_coverage)]
+ 3| |
+ 4| |#[no_coverage]
+ 5| |fn do_not_add_coverage_1() {
+ 6| | println!("called but not covered");
+ 7| |}
+ 8| |
+ 9| |fn do_not_add_coverage_2() {
+ 10| | #![no_coverage]
+ 11| | println!("called but not covered");
+ 12| |}
+ 13| |
+ 14| |#[no_coverage]
+ 15| |fn do_not_add_coverage_not_called() {
+ 16| | println!("not called and not covered");
+ 17| |}
+ 18| |
+ 19| 1|fn add_coverage_1() {
+ 20| 1| println!("called and covered");
+ 21| 1|}
+ 22| |
+ 23| 1|fn add_coverage_2() {
+ 24| 1| println!("called and covered");
+ 25| 1|}
+ 26| |
+ 27| 0|fn add_coverage_not_called() {
+ 28| 0| println!("not called but covered");
+ 29| 0|}
+ 30| |
+ 31| |// FIXME: These test-cases illustrate confusing results of nested functions.
+ 32| |// See https://github.com/rust-lang/rust/issues/93319
+ 33| |mod nested_fns {
+ 34| | #[no_coverage]
+ 35| | pub fn outer_not_covered(is_true: bool) {
+ 36| 1| fn inner(is_true: bool) {
+ 37| 1| if is_true {
+ 38| 1| println!("called and covered");
+ 39| 1| } else {
+ 40| 0| println!("absolutely not covered");
+ 41| 0| }
+ 42| 1| }
+ 43| | println!("called but not covered");
+ 44| | inner(is_true);
+ 45| | }
+ 46| |
+ 47| 1| pub fn outer(is_true: bool) {
+ 48| 1| println!("called and covered");
+ 49| 1| inner_not_covered(is_true);
+ 50| 1|
+ 51| 1| #[no_coverage]
+ 52| 1| fn inner_not_covered(is_true: bool) {
+ 53| 1| if is_true {
+ 54| 1| println!("called but not covered");
+ 55| 1| } else {
+ 56| 1| println!("absolutely not covered");
+ 57| 1| }
+ 58| 1| }
+ 59| 1| }
+ 60| |
+ 61| 1| pub fn outer_both_covered(is_true: bool) {
+ 62| 1| println!("called and covered");
+ 63| 1| inner(is_true);
+ 64| 1|
+ 65| 1| fn inner(is_true: bool) {
+ 66| 1| if is_true {
+ 67| 1| println!("called and covered");
+ 68| 1| } else {
+ 69| 0| println!("absolutely not covered");
+ 70| 0| }
+ 71| 1| }
+ 72| 1| }
+ 73| |}
+ 74| |
+ 75| 1|fn main() {
+ 76| 1| let is_true = std::env::args().len() == 1;
+ 77| 1|
+ 78| 1| do_not_add_coverage_1();
+ 79| 1| do_not_add_coverage_2();
+ 80| 1| add_coverage_1();
+ 81| 1| add_coverage_2();
+ 82| 1|
+ 83| 1| nested_fns::outer_not_covered(is_true);
+ 84| 1| nested_fns::outer(is_true);
+ 85| 1| nested_fns::outer_both_covered(is_true);
+ 86| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-101
+ 3| |
+ 4| 4|fn might_overflow(to_add: u32) -> u32 {
+ 5| 4| if to_add > 5 {
+ 6| 1| println!("this will probably overflow");
+ 7| 3| }
+ 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|}
+ 14| |
+ 15| 1|fn main() -> Result<(),u8> {
+ 16| 1| let mut countdown = 10;
+ 17| 11| while countdown > 0 {
+ 18| 11| if countdown == 1 {
+ 19| 1| let result = might_overflow(10);
+ 20| 1| println!("Result: {}", result);
+ 21| 10| } else if countdown < 5 {
+ 22| 3| let result = might_overflow(1);
+ 23| 3| println!("Result: {}", result);
+ 24| 6| }
+ 25| 10| countdown -= 1;
+ 26| | }
+ 27| 0| Ok(())
+ 28| 0|}
+ 29| |
+ 30| |// Notes:
+ 31| |// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+ 32| |// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+ 33| |// 2. This test confirms the coverage generated when a program passes or fails a
+ 34| |// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+ 35| |// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+ 36| |// compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+ 37| |// expected behavior. To simplify the coverage graphs and keep instrumented programs as
+ 38| |// small and fast as possible, `Assert` terminators are assumed to always succeed, and
+ 39| |// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+ 40| |// get its own coverage counter.
+ 41| |// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+ 42| |// In this test, the final count for the statements after the `if` block in `might_overflow()`
+ 43| |// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+ 44| |// on the MIR graph and the structure of the code, this count could have been 3 (which might
+ 45| |// have been valid for the overflowed add `+`, but should have been 4 for the lines before
+ 46| |// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+ 47| |// via StatementKind::Counter at the end of the block, but (as in the case in this test),
+ 48| |// a CounterKind::Expression is always evaluated. In this case, the expression was based on
+ 49| |// a `Counter` incremented as part of the evaluation of the `if` expression, which was
+ 50| |// executed, and counted, 4 times, before reaching the overflow add.
+ 51| |
+ 52| |// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+ 53| |//
+ 54| |// 4| |fn might_overflow(to_add: u32) -> u32 {
+ 55| |// 5| 4| if to_add > 5 {
+ 56| |// 6| 0| println!("this will probably overflow");
+ 57| |// 7| 4| }
+ 58| |// 8| 4| let add_to = u32::MAX - 5;
+ 59| |// 9| 4| println!("does {} + {} overflow?", add_to, to_add);
+ 60| |// 10| 4| let result = to_add + add_to;
+ 61| |// 11| 4| println!("continuing after overflow check");
+ 62| |// 12| 4| result
+ 63| |// 13| 4|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-101
+ 3| |
+ 4| 4|fn might_panic(should_panic: bool) {
+ 5| 4| if should_panic {
+ 6| 1| println!("panicking...");
+ 7| 1| panic!("panics");
+ 8| 3| } else {
+ 9| 3| println!("Don't Panic");
+ 10| 3| }
+ 11| 3|}
+ 12| |
+ 13| 1|fn main() -> Result<(), u8> {
+ 14| 1| let mut countdown = 10;
+ 15| 11| while countdown > 0 {
+ 16| 11| if countdown == 1 {
+ 17| 1| might_panic(true);
+ 18| 10| } else if countdown < 5 {
+ 19| 3| might_panic(false);
+ 20| 6| }
+ 21| 10| countdown -= 1;
+ 22| | }
+ 23| 0| Ok(())
+ 24| 0|}
+ 25| |
+ 26| |// Notes:
+ 27| |// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+ 28| |// `try_error_result.rs`.
+ 29| |// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+ 30| |// normal program exit cleanup, including writing out the current values of the coverage
+ 31| |// counters.
+
--- /dev/null
+ 1| |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+ 2| |// structure of this test.
+ 3| |
+ 4| 2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+ ^0 ^0 ^0 ^1 ^1 ^0^0
+ ------------------
+ | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::ne
+ ------------------
+ | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::eq
+ ------------------
+ 5| |pub struct Version {
+ 6| | major: usize,
+ 7| | minor: usize,
+ 8| | patch: usize,
+ 9| |}
+ 10| |
+ 11| |impl Version {
+ 12| 2| pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+ 13| 2| Self {
+ 14| 2| major,
+ 15| 2| minor,
+ 16| 2| patch,
+ 17| 2| }
+ 18| 2| }
+ 19| |}
+ 20| |
+ 21| 1|fn main() {
+ 22| 1| let version_3_2_1 = Version::new(3, 2, 1);
+ 23| 1| let version_3_3_0 = Version::new(3, 3, 0);
+ 24| 1|
+ 25| 1| println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+ 26| 1|}
+ 27| |
+ 28| |/*
+ 29| |
+ 30| |This test verifies a bug was fixed that otherwise generated this error:
+ 31| |
+ 32| |thread 'rustc' panicked at 'No counters provided the source_hash for function:
+ 33| | Instance {
+ 34| | def: Item(WithOptConstParam {
+ 35| | did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+ 36| | const_param_did: None
+ 37| | }),
+ 38| | substs: []
+ 39| | }'
+ 40| |The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+ 41| |without a code region associated with any `Counter`. Code regions were associated with at least
+ 42| |one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+ 43| |(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+ 44| |`function_source_hash` without a code region, if necessary.
+ 45| |
+ 46| |*/
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 0;
+ 10| 1|
+ 11| 1| if
+ 12| 1| is_true
+ 13| 1| {
+ 14| 1| countdown
+ 15| 1| =
+ 16| 1| 10
+ 17| 1| ;
+ 18| 1| }
+ ^0
+ 19| |
+ 20| | loop
+ 21| | {
+ 22| | if
+ 23| 11| countdown
+ 24| 11| ==
+ 25| 11| 0
+ 26| | {
+ 27| 1| break
+ 28| | ;
+ 29| 10| }
+ 30| 10| countdown
+ 31| 10| -=
+ 32| 10| 1
+ 33| | ;
+ 34| | }
+ 35| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| 1|fn main() {
+ 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 6| 1| // dependent conditions.
+ 7| 1| let is_true = std::env::args().len() == 1;
+ 8| 1|
+ 9| 1| let mut countdown = 1;
+ 10| 1| if is_true {
+ 11| 1| countdown = 0;
+ 12| 1| }
+ ^0
+ 13| |
+ 14| | for
+ 15| | _
+ 16| | in
+ 17| 3| 0..2
+ 18| | {
+ 19| | let z
+ 20| | ;
+ 21| | match
+ 22| 2| countdown
+ 23| | {
+ 24| 1| x
+ 25| | if
+ 26| 2| x
+ 27| 2| <
+ 28| 2| 1
+ 29| | =>
+ 30| 1| {
+ 31| 1| z = countdown
+ 32| 1| ;
+ 33| 1| let y = countdown
+ 34| 1| ;
+ 35| 1| countdown = 10
+ 36| 1| ;
+ 37| 1| }
+ 38| | _
+ 39| | =>
+ 40| 1| {}
+ 41| | }
+ 42| | }
+ 43| 1|}
+
--- /dev/null
+ 1| 1|fn main() {
+ 2| 1| if false {
+ 3| 0| loop {}
+ 4| 1| }
+ 5| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| 6|fn call(return_error: bool) -> Result<(),()> {
+ 5| 6| if return_error {
+ 6| 1| Err(())
+ 7| | } else {
+ 8| 5| Ok(())
+ 9| | }
+ 10| 6|}
+ 11| |
+ 12| 1|fn test1() -> Result<(),()> {
+ 13| 1| let mut
+ 14| 1| countdown = 10
+ 15| | ;
+ 16| | for
+ 17| | _
+ 18| | in
+ 19| 6| 0..10
+ 20| | {
+ 21| 6| countdown
+ 22| 6| -= 1
+ 23| 6| ;
+ 24| 6| if
+ 25| 6| countdown < 5
+ 26| | {
+ 27| 1| call(/*return_error=*/ true)?;
+ 28| 0| call(/*return_error=*/ false)?;
+ 29| | }
+ 30| | else
+ 31| | {
+ 32| 5| call(/*return_error=*/ false)?;
+ ^0
+ 33| | }
+ 34| | }
+ 35| 0| Ok(())
+ 36| 1|}
+ 37| |
+ 38| |struct Thing1;
+ 39| |impl Thing1 {
+ 40| 18| fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+ 41| 18| if return_error {
+ 42| 1| Err(())
+ 43| | } else {
+ 44| 17| Ok(Thing2{})
+ 45| | }
+ 46| 18| }
+ 47| |}
+ 48| |
+ 49| |struct Thing2;
+ 50| |impl Thing2 {
+ 51| 17| fn call(&self, return_error: bool) -> Result<u32,()> {
+ 52| 17| if return_error {
+ 53| 2| Err(())
+ 54| | } else {
+ 55| 15| Ok(57)
+ 56| | }
+ 57| 17| }
+ 58| |}
+ 59| |
+ 60| 1|fn test2() -> Result<(),()> {
+ 61| 1| let thing1 = Thing1{};
+ 62| 1| let mut
+ 63| 1| countdown = 10
+ 64| | ;
+ 65| | for
+ 66| | _
+ 67| | in
+ 68| 6| 0..10
+ 69| | {
+ 70| 6| countdown
+ 71| 6| -= 1
+ 72| 6| ;
+ 73| 6| if
+ 74| 6| countdown < 5
+ 75| | {
+ 76| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+ ^0
+ 77| 1| thing1
+ 78| 1| .
+ 79| 1| get_thing_2(/*return_error=*/ false)
+ 80| 0| ?
+ 81| | .
+ 82| 1| call(/*return_error=*/ true)
+ 83| 1| .
+ 84| 1| expect_err(
+ 85| 1| "call should fail"
+ 86| 1| );
+ 87| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+ ^0 ^0 ^0
+ 88| 0| assert_eq!(val, 57);
+ 89| 0| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+ 90| 0| assert_eq!(val, 57);
+ 91| | }
+ 92| | else
+ 93| | {
+ 94| 5| let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+ ^0 ^0
+ 95| 5| assert_eq!(val, 57);
+ 96| 5| let val = thing1
+ 97| 5| .get_thing_2(/*return_error=*/ false)?
+ ^0
+ 98| 5| .call(/*return_error=*/ false)?;
+ ^0
+ 99| 5| assert_eq!(val, 57);
+ 100| 5| let val = thing1
+ 101| 5| .get_thing_2(/*return_error=*/ false)
+ 102| 0| ?
+ 103| 5| .call(/*return_error=*/ false)
+ 104| 0| ?
+ 105| | ;
+ 106| 5| assert_eq!(val, 57);
+ 107| | }
+ 108| | }
+ 109| 0| Ok(())
+ 110| 1|}
+ 111| |
+ 112| 1|fn main() -> Result<(),()> {
+ 113| 1| test1().expect_err("test1 should fail");
+ 114| 1| test2()
+ 115| 1| ?
+ 116| | ;
+ 117| 0| Ok(())
+ 118| 1|}
+
--- /dev/null
+ 1| 2|fn foo<T>(x: T) {
+ 2| 2| let mut i = 0;
+ 3| 22| while i < 10 {
+ 4| 20| i != 0 || i != 0;
+ ^2
+ 5| 20| i += 1;
+ 6| | }
+ 7| 2|}
+ ------------------
+ | unused::foo::<f32>:
+ | 1| 1|fn foo<T>(x: T) {
+ | 2| 1| let mut i = 0;
+ | 3| 11| while i < 10 {
+ | 4| 10| i != 0 || i != 0;
+ | ^1
+ | 5| 10| i += 1;
+ | 6| | }
+ | 7| 1|}
+ ------------------
+ | unused::foo::<u32>:
+ | 1| 1|fn foo<T>(x: T) {
+ | 2| 1| let mut i = 0;
+ | 3| 11| while i < 10 {
+ | 4| 10| i != 0 || i != 0;
+ | ^1
+ | 5| 10| i += 1;
+ | 6| | }
+ | 7| 1|}
+ ------------------
+ 8| |
+ 9| 0|fn unused_template_func<T>(x: T) {
+ 10| 0| let mut i = 0;
+ 11| 0| while i < 10 {
+ 12| 0| i != 0 || i != 0;
+ 13| 0| i += 1;
+ 14| | }
+ 15| 0|}
+ 16| |
+ 17| 0|fn unused_func(mut a: u32) {
+ 18| 0| if a != 0 {
+ 19| 0| a += 1;
+ 20| 0| }
+ 21| 0|}
+ 22| |
+ 23| 0|fn unused_func2(mut a: u32) {
+ 24| 0| if a != 0 {
+ 25| 0| a += 1;
+ 26| 0| }
+ 27| 0|}
+ 28| |
+ 29| 0|fn unused_func3(mut a: u32) {
+ 30| 0| if a != 0 {
+ 31| 0| a += 1;
+ 32| 0| }
+ 33| 0|}
+ 34| |
+ 35| 1|fn main() -> Result<(), u8> {
+ 36| 1| foo::<u32>(0);
+ 37| 1| foo::<f32>(0.0);
+ 38| 1| Ok(())
+ 39| 1|}
+
--- /dev/null
+ 1| 0|pub fn never_called_function() {
+ 2| 0| println!("I am never called");
+ 3| 0|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+ 3| |use std::fmt::Debug;
+ 4| |
+ 5| 1|pub fn used_function() {
+ 6| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 7| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 8| 1| // dependent conditions.
+ 9| 1| let is_true = std::env::args().len() == 1;
+ 10| 1| let mut countdown = 0;
+ 11| 1| if is_true {
+ 12| 1| countdown = 10;
+ 13| 1| }
+ ^0
+ 14| 1| use_this_lib_crate();
+ 15| 1|}
+ 16| |
+ 17| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ 18| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ 19| 2|}
+ ------------------
+ | used_crate::used_only_from_bin_crate_generic_function::<&str>:
+ | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 19| 1|}
+ ------------------
+ | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+ | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 19| 1|}
+ ------------------
+ | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+ ------------------
+ 20| |// Expect for above function: `Unexecuted instantiation` (see below)
+ 21| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ 22| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ 23| 2|}
+ ------------------
+ | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 23| 1|}
+ ------------------
+ | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+ | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 23| 1|}
+ ------------------
+ 24| |
+ 25| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 26| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 27| 2|}
+ ------------------
+ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 25| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 26| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 27| 1|}
+ ------------------
+ | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 25| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 26| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 27| 1|}
+ ------------------
+ 28| |
+ 29| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 30| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 31| 2|}
+ ------------------
+ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 31| 1|}
+ ------------------
+ | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 31| 1|}
+ ------------------
+ 32| |
+ 33| 0|pub fn unused_generic_function<T: Debug>(arg: T) {
+ 34| 0| println!("unused_generic_function with {:?}", arg);
+ 35| 0|}
+ 36| |
+ 37| 0|pub fn unused_function() {
+ 38| 0| let is_true = std::env::args().len() == 1;
+ 39| 0| let mut countdown = 2;
+ 40| 0| if !is_true {
+ 41| 0| countdown = 20;
+ 42| 0| }
+ 43| 0|}
+ 44| |
+ 45| 0|fn unused_private_function() {
+ 46| 0| let is_true = std::env::args().len() == 1;
+ 47| 0| let mut countdown = 2;
+ 48| 0| if !is_true {
+ 49| 0| countdown = 20;
+ 50| 0| }
+ 51| 0|}
+ 52| |
+ 53| 1|fn use_this_lib_crate() {
+ 54| 1| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+ 55| 1| used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+ 56| 1| "used from library used_crate.rs",
+ 57| 1| );
+ 58| 1| let some_vec = vec![5, 6, 7, 8];
+ 59| 1| used_only_from_this_lib_crate_generic_function(some_vec);
+ 60| 1| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+ 61| 1|}
+ 62| |
+ 63| |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+ 64| |// for example:
+ 65| |//
+ 66| |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+ 67| |//
+ 68| |// These notices appear when `llvm-cov` shows instantiations. This may be a
+ 69| |// default option, but it can be suppressed with:
+ 70| |//
+ 71| |// ```shell
+ 72| |// $ `llvm-cov show --show-instantiations=0 ...`
+ 73| |// ```
+ 74| |//
+ 75| |// The notice is triggered because the function is unused by the library itself,
+ 76| |// and when the library is compiled, a synthetic function is generated, so
+ 77| |// unused function coverage can be reported. Coverage can be skipped for unused
+ 78| |// generic functions with:
+ 79| |//
+ 80| |// ```shell
+ 81| |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+ 82| |// ```
+ 83| |//
+ 84| |// Even though this function is used by `uses_crate.rs` (and
+ 85| |// counted), with substitutions for `T`, those instantiations are only generated
+ 86| |// when the generic function is actually used (from the binary, not from this
+ 87| |// library crate). So the test result shows coverage for all instantiated
+ 88| |// versions and their generic type substitutions, plus the `Unexecuted
+ 89| |// instantiation` message for the non-substituted version. This is valid, but
+ 90| |// unfortunately a little confusing.
+ 91| |//
+ 92| |// The library crate has its own coverage map, and the only way to show unused
+ 93| |// coverage of a generic function is to include the generic function in the
+ 94| |// coverage map, marked as an "unused function". If the library were used by
+ 95| |// another binary that never used this generic function, then it would be valid
+ 96| |// to show the unused generic, with unknown substitution (`_`).
+ 97| |//
+ 98| |// The alternative is to exclude all generics from being included in the "unused
+ 99| |// functions" list, which would then omit coverage results for
+ 100| |// `unused_generic_function<T>()`, below.
+
--- /dev/null
+ 1| |#![allow(unused_assignments, unused_variables)]
+ 2| |
+ 3| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+ 4| |
+ 5| |use std::fmt::Debug;
+ 6| |
+ 7| 1|pub fn used_function() {
+ 8| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 9| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 10| 1| // dependent conditions.
+ 11| 1| let is_true = std::env::args().len() == 1;
+ 12| 1| let mut countdown = 0;
+ 13| 1| if is_true {
+ 14| 1| countdown = 10;
+ 15| 1| }
+ ^0
+ 16| 1| use_this_lib_crate();
+ 17| 1|}
+ 18| |
+ 19| |#[inline(always)]
+ 20| 1|pub fn used_inline_function() {
+ 21| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ 22| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ 23| 1| // dependent conditions.
+ 24| 1| let is_true = std::env::args().len() == 1;
+ 25| 1| let mut countdown = 0;
+ 26| 1| if is_true {
+ 27| 1| countdown = 10;
+ 28| 1| }
+ ^0
+ 29| 1| use_this_lib_crate();
+ 30| 1|}
+ 31| |
+ 32| |
+ 33| |
+ 34| |
+ 35| |
+ 36| |
+ 37| |
+ 38| |#[inline(always)]
+ 39| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ 40| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ 41| 2|}
+ ------------------
+ | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+ | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 41| 1|}
+ ------------------
+ | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
+ | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+ | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+ | 41| 1|}
+ ------------------
+ | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
+ ------------------
+ 42| |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+ 43| |
+ 44| |#[inline(always)]
+ 45| 4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ 46| 4| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ 47| 4|}
+ ------------------
+ | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 47| 2|}
+ ------------------
+ | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+ | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+ | 47| 2|}
+ ------------------
+ 48| |
+ 49| |#[inline(always)]
+ 50| 3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 51| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 52| 3|}
+ ------------------
+ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+ | 50| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 51| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 52| 1|}
+ ------------------
+ | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 50| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 51| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 52| 2|}
+ ------------------
+ 53| |
+ 54| |#[inline(always)]
+ 55| 3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ 56| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ 57| 3|}
+ ------------------
+ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 55| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 56| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 57| 1|}
+ ------------------
+ | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
+ | 55| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+ | 56| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+ | 57| 2|}
+ ------------------
+ 58| |
+ 59| |#[inline(always)]
+ 60| 0|pub fn unused_generic_function<T: Debug>(arg: T) {
+ 61| 0| println!("unused_generic_function with {:?}", arg);
+ 62| 0|}
+ 63| |
+ 64| |#[inline(always)]
+ 65| 0|pub fn unused_function() {
+ 66| 0| let is_true = std::env::args().len() == 1;
+ 67| 0| let mut countdown = 2;
+ 68| 0| if !is_true {
+ 69| 0| countdown = 20;
+ 70| 0| }
+ 71| 0|}
+ 72| |
+ 73| |#[inline(always)]
+ 74| 0|fn unused_private_function() {
+ 75| 0| let is_true = std::env::args().len() == 1;
+ 76| 0| let mut countdown = 2;
+ 77| 0| if !is_true {
+ 78| 0| countdown = 20;
+ 79| 0| }
+ 80| 0|}
+ 81| |
+ 82| 2|fn use_this_lib_crate() {
+ 83| 2| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+ 84| 2| used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+ 85| 2| "used from library used_crate.rs",
+ 86| 2| );
+ 87| 2| let some_vec = vec![5, 6, 7, 8];
+ 88| 2| used_only_from_this_lib_crate_generic_function(some_vec);
+ 89| 2| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+ 90| 2|}
+
--- /dev/null
+ 1| 1|fn main() {
+ 2| 1| let num = 9;
+ 3| 1| while num >= 10 {
+ 4| 0| }
+ 5| 1|}
+
--- /dev/null
+ 1| |#![allow(unused_assignments)]
+ 2| |// expect-exit-status-1
+ 3| |
+ 4| 1|fn main() -> Result<(),u8> {
+ 5| 1| let mut countdown = 10;
+ 6| | while
+ 7| 7| countdown
+ 8| 7| >
+ 9| 7| 0
+ 10| | {
+ 11| | if
+ 12| 7| countdown
+ 13| 7| <
+ 14| 7| 5
+ 15| | {
+ 16| | return
+ 17| | if
+ 18| 1| countdown
+ 19| 1| >
+ 20| 1| 8
+ 21| | {
+ 22| 0| Ok(())
+ 23| | }
+ 24| | else
+ 25| | {
+ 26| 1| Err(1)
+ 27| | }
+ 28| | ;
+ 29| 6| }
+ 30| 6| countdown
+ 31| 6| -=
+ 32| 6| 1
+ 33| | ;
+ 34| | }
+ 35| 0| Ok(())
+ 36| 1|}
+ 37| |
+ 38| |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+ 39| |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+ 40| |// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+ 41| |// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+ 42| |// to the coverage test for early returns, but this is a limitation that should be fixed.
+
--- /dev/null
+ 1| |#![feature(generators, generator_trait)]
+ 2| |#![allow(unused_assignments)]
+ 3| |
+ 4| |use std::ops::{Generator, GeneratorState};
+ 5| |use std::pin::Pin;
+ 6| |
+ 7| 1|fn main() {
+ 8| 1| let mut generator = || {
+ 9| 1| yield 1;
+ 10| 1| return "foo"
+ 11| | };
+ 12| |
+ 13| 1| match Pin::new(&mut generator).resume(()) {
+ 14| 1| GeneratorState::Yielded(1) => {}
+ 15| 0| _ => panic!("unexpected value from resume"),
+ 16| | }
+ 17| 1| match Pin::new(&mut generator).resume(()) {
+ 18| 1| GeneratorState::Complete("foo") => {}
+ 19| 0| _ => panic!("unexpected value from resume"),
+ 20| | }
+ 21| |
+ 22| 1| let mut generator = || {
+ 23| 1| yield 1;
+ 24| 1| yield 2;
+ 25| 0| yield 3;
+ 26| 0| return "foo"
+ 27| | };
+ 28| |
+ 29| 1| match Pin::new(&mut generator).resume(()) {
+ 30| 1| GeneratorState::Yielded(1) => {}
+ 31| 0| _ => panic!("unexpected value from resume"),
+ 32| | }
+ 33| 1| match Pin::new(&mut generator).resume(()) {
+ 34| 1| GeneratorState::Yielded(2) => {}
+ 35| 0| _ => panic!("unexpected value from resume"),
+ 36| | }
+ 37| 1|}
+
--- /dev/null
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import sys
+
+# Normalize file paths in output
+for line in sys.stdin:
+ if line.startswith("..") and line.rstrip().endswith(".rs:"):
+ print(line.replace("\\", "/"), end='')
+ else:
+ print(line, end='')
--- /dev/null
+IMPORTANT: The Rust test programs in this directory generate various output
+files in the `../coverage*` directories (`expected` and `actual` files).
+
+Microsoft Windows has a relatively short limit on file paths (not individual
+path components, but the entire path). The files generated by these
+`../coverage*` tests typically have file paths that include the program
+source file name plus function and type names (depending on the program).
+
+Keep the test file names short, and keep function names and other symbols
+short as well, to avoid hitting the Windows limits.
--- /dev/null
+#![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 `TerminatorKind::Abort`.
+// 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.
+*/
--- /dev/null
+#![allow(unused_assignments)]
+// expect-exit-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.
--- /dev/null
+#![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 funciton 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;
+ }
+ }
+ }
+}
--- /dev/null
+// compile-flags: --edition=2018
+
+use core::{
+ future::Future,
+ marker::Send,
+ pin::Pin,
+};
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
+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);
+}
--- /dev/null
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+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(())
+}
--- /dev/null
+// compile-flags: --edition=2018
+#![feature(no_coverage)]
+
+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(())
+}
+
+#[no_coverage]
+fn main() {
+ executor::block_on(test());
+}
+
+mod executor {
+ use core::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ };
+
+ #[no_coverage]
+ 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(
+
+ #[no_coverage]
+ |_| unsafe { unreachable_unchecked() }, // clone
+
+ #[no_coverage]
+ |_| unsafe { unreachable_unchecked() }, // wake
+
+ #[no_coverage]
+ |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+
+ #[no_coverage]
+ |_| (),
+ );
+ 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;
+ }
+ }
+ }
+}
--- /dev/null
+# Directory "coverage" supports the tests at prefix ../coverage-*
+
+# Use ./x.py [options] test src/test/run-make/coverage to run all related tests.
--- /dev/null
+#![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;
+ };
+}
--- /dev/null
+#![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;
+}
--- /dev/null
+# Common Makefile include for Rust `run-make/coverage-* tests. Include this
+# file with the line:
+#
+# -include ../coverage/coverage_tools.mk
+
+-include ../tools.mk
--- /dev/null
+#![allow(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;
+ }
+}
--- /dev/null
+//! This test ensures that code from doctests is properly re-mapped.
+//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+//!
+//! Just some random code:
+//! ```
+//! if true {
+//! // this is executed!
+//! assert_eq!(1, 1);
+//! } else {
+//! // this is not!
+//! assert_eq!(1, 2);
+//! }
+//! ```
+//!
+//! doctest testing external code:
+//! ```
+//! extern crate doctest_crate;
+//! doctest_crate::fn_run_in_doctests(1);
+//! ```
+//!
+//! doctest returning a result:
+//! ```
+//! #[derive(Debug, PartialEq)]
+//! struct SomeError {
+//! msg: String,
+//! }
+//! let mut res = Err(SomeError { msg: String::from("a message") });
+//! if res.is_ok() {
+//! res?;
+//! } else {
+//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//! println!("{:?}", res);
+//! }
+//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//! res = Ok(1);
+//! }
+//! res = Ok(0);
+//! }
+//! // need to be explicit because rustdoc cant infer the return type
+//! Ok::<(), SomeError>(())
+//! ```
+//!
+//! doctest with custom main:
+//! ```
+//! fn some_func() {
+//! println!("called some_func()");
+//! }
+//!
+//! #[derive(Debug)]
+//! struct SomeError;
+//!
+//! extern crate doctest_crate;
+//!
+//! fn doctest_main() -> Result<(), SomeError> {
+//! some_func();
+//! doctest_crate::fn_run_in_doctests(2);
+//! Ok(())
+//! }
+//!
+//! // this `main` is not shown as covered, as it clashes with all the other
+//! // `main` functions that were automatically generated for doctests
+//! fn main() -> Result<(), SomeError> {
+//! doctest_main()
+//! }
+//! ```
+
+/// doctest attached to fn testing external code:
+/// ```
+/// extern crate doctest_crate;
+/// doctest_crate::fn_run_in_doctests(3);
+/// ```
+///
+fn main() {
+ if true {
+ assert_eq!(1, 1);
+ } else {
+ assert_eq!(1, 2);
+ }
+}
+
+// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+//
+// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+// one character past, the `if` block's closing brace. In both cases, these are most likely off
+// by the number of characters stripped from the beginning of each doc comment line: indent
+// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+// more pronounced, and show up in more places, with background color used to show some distinct
+// code regions with different coverage counts.
+//
+// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+// character stripped from the beginning of doc comment lines with a space. This will give coverage
+// results the correct column offsets, and I think it should compile correctly, but I don't know
+// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+// if the indentation changed. I don't know if there is a more viable solution.
--- /dev/null
+#![allow(unused_assignments)]
+// expect-exit-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
--- /dev/null
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+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 `generator::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 generator = || {
+ yield get_u32(is_true);
+ return "foo";
+ };
+
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(Ok(1)) => {}
+ _ => panic!("unexpected return from resume"),
+ }
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Complete("foo") => {}
+ _ => panic!("unexpected return from resume"),
+ }
+}
--- /dev/null
+#![allow(unused_assignments)]
+// expect-exit-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
--- /dev/null
+#![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
+ ;
+ }
+}
--- /dev/null
+#![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
+ ;
+ }
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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");
+}
--- /dev/null
+#![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();
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+
+// expect-exit-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();
+}
--- /dev/null
+// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+
+extern crate inline_always_with_dead_code;
+
+use inline_always_with_dead_code::{bar, baz};
+
+fn main() {
+ bar::call_me();
+ baz::call_me();
+}
--- /dev/null
+// 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() { }
--- /dev/null
+#![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;
+ }
+}
--- /dev/null
+/// A function run only from within doctests
+pub fn fn_run_in_doctests(conditional: usize) {
+ match conditional {
+ 1 => assert_eq!(1, 1), // this is run,
+ 2 => assert_eq!(1, 1), // this,
+ 3 => assert_eq!(1, 1), // and this too
+ _ => assert_eq!(1, 2), // however this is not
+ }
+}
--- /dev/null
+// 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();
+ }
+}
--- /dev/null
+pub fn never_called_function() {
+ println!("I am never called");
+}
--- /dev/null
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+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;
+ }
+}
+
+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.
--- /dev/null
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+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)]
+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");
+}
--- /dev/null
+#![allow(unused_assignments, unused_variables)]
+
+fn main() {
+ let result
+ =
+ loop
+ {
+ break
+ 10
+ ;
+ }
+ ;
+}
--- /dev/null
+#![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);
+}
--- /dev/null
+#![feature(or_patterns)]
+
+fn main() {
+ // Initialize test constants in a way that cannot be determined at compile time, to ensure
+ // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+ // dependent conditions.
+ let is_true = std::env::args().len() == 1;
+
+ let mut a: u8 = 0;
+ let mut b: u8 = 0;
+ if is_true {
+ a = 2;
+ b = 0;
+ }
+ match (a, b) {
+ // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+ // This test confirms a fix for Issue #79569.
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+ if is_true {
+ a = 0;
+ b = 0;
+ }
+ match (a, b) {
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+ if is_true {
+ a = 2;
+ b = 2;
+ }
+ match (a, b) {
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+ if is_true {
+ a = 0;
+ b = 2;
+ }
+ match (a, b) {
+ (0 | 1, 2 | 3) => {}
+ _ => {}
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+// Enables `no_coverage` on the entire crate
+#![feature(no_coverage)]
+
+#[no_coverage]
+fn do_not_add_coverage_1() {
+ println!("called but not covered");
+}
+
+fn do_not_add_coverage_2() {
+ #![no_coverage]
+ println!("called but not covered");
+}
+
+#[no_coverage]
+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");
+}
+
+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 {
+ #[no_coverage]
+ 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);
+
+ #[no_coverage]
+ 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);
+}
--- /dev/null
+#![allow(unused_assignments)]
+// expect-exit-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|}
--- /dev/null
+#![allow(unused_assignments)]
+// expect-exit-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.
--- /dev/null
+// 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
+ }),
+ substs: []
+ }'
+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.
+
+*/
--- /dev/null
+#![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
+ ;
+ }
+}
--- /dev/null
+#![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
+ ;
+ }
+ _
+ =>
+ {}
+ }
+ }
+}
--- /dev/null
+fn main() {
+ if false {
+ loop {}
+ }
+}
--- /dev/null
+#![allow(unused_assignments)]
+// expect-exit-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(())
+}
--- /dev/null
+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(())
+}
--- /dev/null
+#[path = "lib/unused_mod_helper.rs"]
+mod unused_module;
+
+fn main() {
+ println!("hello world!");
+}
--- /dev/null
+#![allow(unused_assignments, unused_variables)]
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+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?");
+}
--- /dev/null
+#![allow(unused_assignments, unused_variables)]
+
+// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+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?",
+ );
+}
--- /dev/null
+fn main() {
+ let num = 9;
+ while num >= 10 {
+ }
+}
--- /dev/null
+#![allow(unused_assignments)]
+// expect-exit-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.
--- /dev/null
+#![feature(generators, generator_trait)]
+#![allow(unused_assignments)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+fn main() {
+ let mut generator = || {
+ yield 1;
+ return "foo"
+ };
+
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(1) => {}
+ _ => panic!("unexpected value from resume"),
+ }
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Complete("foo") => {}
+ _ => panic!("unexpected value from resume"),
+ }
+
+ let mut generator = || {
+ yield 1;
+ yield 2;
+ yield 3;
+ return "foo"
+ };
+
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(1) => {}
+ _ => panic!("unexpected value from resume"),
+ }
+ match Pin::new(&mut generator).resume(()) {
+ GeneratorState::Yielded(2) => {}
+ _ => panic!("unexpected value from resume"),
+ }
+}