about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/bootstrap/test.rs20
-rw-r--r--src/tools/compiletest/src/common.rs3
-rw-r--r--src/tools/compiletest/src/header.rs48
-rw-r--r--src/tools/compiletest/src/header/needs.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs347
-rw-r--r--tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs (renamed from tests/run-make/coverage/lib/doctest_crate.rs)0
-rw-r--r--tests/run-coverage-rustdoc/doctest.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.doctest.txt)26
-rw-r--r--tests/run-coverage-rustdoc/doctest.rs (renamed from tests/run-make/coverage/doctest.rs)2
-rw-r--r--tests/run-coverage/abort.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.abort.txt)0
-rw-r--r--tests/run-coverage/abort.rs (renamed from tests/run-make/coverage/abort.rs)0
-rw-r--r--tests/run-coverage/assert.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.assert.txt)2
-rw-r--r--tests/run-coverage/assert.rs (renamed from tests/run-make/coverage/assert.rs)2
-rw-r--r--tests/run-coverage/async.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.async.txt)0
-rw-r--r--tests/run-coverage/async.rs (renamed from tests/run-make/coverage/async.rs)0
-rw-r--r--tests/run-coverage/async2.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.async2.txt)0
-rw-r--r--tests/run-coverage/async2.rs (renamed from tests/run-make/coverage/async2.rs)0
-rw-r--r--tests/run-coverage/auxiliary/inline_always_with_dead_code.rs (renamed from tests/run-make/coverage/lib/inline_always_with_dead_code.rs)0
-rw-r--r--tests/run-coverage/auxiliary/unused_mod_helper.rs (renamed from tests/run-make/coverage/lib/unused_mod_helper.rs)0
-rw-r--r--tests/run-coverage/auxiliary/used_crate.rs (renamed from tests/run-make/coverage/lib/used_crate.rs)4
-rw-r--r--tests/run-coverage/auxiliary/used_inline_crate.rs (renamed from tests/run-make/coverage/lib/used_inline_crate.rs)4
-rw-r--r--tests/run-coverage/closure.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.closure.txt)4
-rw-r--r--tests/run-coverage/closure.rs (renamed from tests/run-make/coverage/closure.rs)4
-rw-r--r--tests/run-coverage/closure_macro.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt)0
-rw-r--r--tests/run-coverage/closure_macro.rs (renamed from tests/run-make/coverage/closure_macro.rs)0
-rw-r--r--tests/run-coverage/closure_macro_async.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt)0
-rw-r--r--tests/run-coverage/closure_macro_async.rs (renamed from tests/run-make/coverage/closure_macro_async.rs)0
-rw-r--r--tests/run-coverage/conditions.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.conditions.txt)0
-rw-r--r--tests/run-coverage/conditions.rs (renamed from tests/run-make/coverage/conditions.rs)0
-rw-r--r--tests/run-coverage/continue.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.continue.txt)0
-rw-r--r--tests/run-coverage/continue.rs (renamed from tests/run-make/coverage/continue.rs)0
-rw-r--r--tests/run-coverage/dead_code.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt)0
-rw-r--r--tests/run-coverage/dead_code.rs (renamed from tests/run-make/coverage/dead_code.rs)0
-rw-r--r--tests/run-coverage/drop_trait.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt)2
-rw-r--r--tests/run-coverage/drop_trait.rs (renamed from tests/run-make/coverage/drop_trait.rs)2
-rw-r--r--tests/run-coverage/generator.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.generator.txt)0
-rw-r--r--tests/run-coverage/generator.rs (renamed from tests/run-make/coverage/generator.rs)0
-rw-r--r--tests/run-coverage/generics.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.generics.txt)2
-rw-r--r--tests/run-coverage/generics.rs (renamed from tests/run-make/coverage/generics.rs)2
-rw-r--r--tests/run-coverage/if.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.if.txt)0
-rw-r--r--tests/run-coverage/if.rs (renamed from tests/run-make/coverage/if.rs)0
-rw-r--r--tests/run-coverage/if_else.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.if_else.txt)0
-rw-r--r--tests/run-coverage/if_else.rs (renamed from tests/run-make/coverage/if_else.rs)0
-rw-r--r--tests/run-coverage/inline-dead.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt)0
-rw-r--r--tests/run-coverage/inline-dead.rs (renamed from tests/run-make/coverage/inline-dead.rs)0
-rw-r--r--tests/run-coverage/inline.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.inline.txt)0
-rw-r--r--tests/run-coverage/inline.rs (renamed from tests/run-make/coverage/inline.rs)0
-rw-r--r--tests/run-coverage/inner_items.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt)0
-rw-r--r--tests/run-coverage/inner_items.rs (renamed from tests/run-make/coverage/inner_items.rs)0
-rw-r--r--tests/run-coverage/issue-83601.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt)0
-rw-r--r--tests/run-coverage/issue-83601.rs (renamed from tests/run-make/coverage/issue-83601.rs)0
-rw-r--r--tests/run-coverage/issue-84561.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt)2
-rw-r--r--tests/run-coverage/issue-84561.rs (renamed from tests/run-make/coverage/issue-84561.rs)2
-rw-r--r--tests/run-coverage/issue-85461.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt)26
-rw-r--r--tests/run-coverage/issue-85461.rs (renamed from tests/run-make/coverage/issue-85461.rs)2
-rw-r--r--tests/run-coverage/issue-93054.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt)0
-rw-r--r--tests/run-coverage/issue-93054.rs (renamed from tests/run-make/coverage/issue-93054.rs)0
-rw-r--r--tests/run-coverage/lazy_boolean.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt)0
-rw-r--r--tests/run-coverage/lazy_boolean.rs (renamed from tests/run-make/coverage/lazy_boolean.rs)0
-rw-r--r--tests/run-coverage/loop_break_value.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt)0
-rw-r--r--tests/run-coverage/loop_break_value.rs (renamed from tests/run-make/coverage/loop_break_value.rs)0
-rw-r--r--tests/run-coverage/loops_branches.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt)0
-rw-r--r--tests/run-coverage/loops_branches.rs (renamed from tests/run-make/coverage/loops_branches.rs)0
-rw-r--r--tests/run-coverage/match_or_pattern.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt)0
-rw-r--r--tests/run-coverage/match_or_pattern.rs (renamed from tests/run-make/coverage/match_or_pattern.rs)0
-rw-r--r--tests/run-coverage/nested_loops.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt)0
-rw-r--r--tests/run-coverage/nested_loops.rs (renamed from tests/run-make/coverage/nested_loops.rs)0
-rw-r--r--tests/run-coverage/no_cov_crate.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt)0
-rw-r--r--tests/run-coverage/no_cov_crate.rs (renamed from tests/run-make/coverage/no_cov_crate.rs)0
-rw-r--r--tests/run-coverage/overflow.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.overflow.txt)2
-rw-r--r--tests/run-coverage/overflow.rs (renamed from tests/run-make/coverage/overflow.rs)2
-rw-r--r--tests/run-coverage/panic_unwind.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt)2
-rw-r--r--tests/run-coverage/panic_unwind.rs (renamed from tests/run-make/coverage/panic_unwind.rs)2
-rw-r--r--tests/run-coverage/partial_eq.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt)0
-rw-r--r--tests/run-coverage/partial_eq.rs (renamed from tests/run-make/coverage/partial_eq.rs)0
-rw-r--r--tests/run-coverage/simple_loop.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt)0
-rw-r--r--tests/run-coverage/simple_loop.rs (renamed from tests/run-make/coverage/simple_loop.rs)0
-rw-r--r--tests/run-coverage/simple_match.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt)0
-rw-r--r--tests/run-coverage/simple_match.rs (renamed from tests/run-make/coverage/simple_match.rs)0
-rw-r--r--tests/run-coverage/sort_groups.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt)0
-rw-r--r--tests/run-coverage/sort_groups.rs (renamed from tests/run-make/coverage/sort_groups.rs)0
-rw-r--r--tests/run-coverage/test_harness.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt)0
-rw-r--r--tests/run-coverage/test_harness.rs (renamed from tests/run-make/coverage/test_harness.rs)0
-rw-r--r--tests/run-coverage/tight_inf_loop.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt)0
-rw-r--r--tests/run-coverage/tight_inf_loop.rs (renamed from tests/run-make/coverage/tight_inf_loop.rs)0
-rw-r--r--tests/run-coverage/try_error_result.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt)2
-rw-r--r--tests/run-coverage/try_error_result.rs (renamed from tests/run-make/coverage/try_error_result.rs)2
-rw-r--r--tests/run-coverage/unused.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.unused.txt)0
-rw-r--r--tests/run-coverage/unused.rs (renamed from tests/run-make/coverage/unused.rs)0
-rw-r--r--tests/run-coverage/unused_mod.coverage13
-rw-r--r--tests/run-coverage/unused_mod.rs (renamed from tests/run-make/coverage/unused_mod.rs)2
-rw-r--r--tests/run-coverage/uses_crate.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt)26
-rw-r--r--tests/run-coverage/uses_crate.rs (renamed from tests/run-make/coverage/uses_crate.rs)8
-rw-r--r--tests/run-coverage/uses_inline_crate.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt)29
-rw-r--r--tests/run-coverage/uses_inline_crate.rs (renamed from tests/run-make/coverage/uses_inline_crate.rs)8
-rw-r--r--tests/run-coverage/while.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.while.txt)0
-rw-r--r--tests/run-coverage/while.rs (renamed from tests/run-make/coverage/while.rs)0
-rw-r--r--tests/run-coverage/while_early_ret.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt)2
-rw-r--r--tests/run-coverage/while_early_ret.rs (renamed from tests/run-make/coverage/while_early_ret.rs)2
-rw-r--r--tests/run-coverage/yield.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.yield.txt)0
-rw-r--r--tests/run-coverage/yield.rs (renamed from tests/run-make/coverage/yield.rs)0
-rw-r--r--tests/run-make/coverage-llvmir/Makefile2
-rw-r--r--tests/run-make/coverage-reports/Makefile178
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt4
-rwxr-xr-xtests/run-make/coverage-reports/normalize_paths.py12
-rwxr-xr-xtests/run-make/coverage-reports/sort_subviews.py50
-rw-r--r--tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt10
-rw-r--r--tests/run-make/coverage/compiletest-ignore-dir3
-rw-r--r--tests/run-make/coverage/coverage_tools.mk6
109 files changed, 523 insertions, 356 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 7c8e3536df5..a1d3453377a 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -686,6 +686,7 @@ impl<'a> Builder<'a> {
                 test::Tidy,
                 test::Ui,
                 test::RunPassValgrind,
+                test::RunCoverage,
                 test::MirOpt,
                 test::Codegen,
                 test::CodegenUnits,
@@ -694,6 +695,7 @@ impl<'a> Builder<'a> {
                 test::Debuginfo,
                 test::UiFullDeps,
                 test::Rustdoc,
+                test::RunCoverageRustdoc,
                 test::Pretty,
                 test::Crate,
                 test::CrateLibrustc,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index ec447a1cd73..2c1f612e39f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1319,6 +1319,13 @@ host_test!(RunMakeFullDeps {
 
 default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" });
 
+host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" });
+host_test!(RunCoverageRustdoc {
+    path: "tests/run-coverage-rustdoc",
+    mode: "run-coverage",
+    suite: "run-coverage-rustdoc"
+});
+
 // For the mir-opt suite we do not use macros, as we need custom behavior when blessing.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct MirOpt {
@@ -1503,6 +1510,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             || (mode == "ui" && is_rustdoc)
             || mode == "js-doc-test"
             || mode == "rustdoc-json"
+            || suite == "run-coverage-rustdoc"
         {
             cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
         }
@@ -1516,7 +1524,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 .arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }));
         }
 
-        if mode == "run-make" {
+        if mode == "run-make" || mode == "run-coverage" {
             let rust_demangler = builder
                 .ensure(tool::RustDemangler {
                     compiler,
@@ -1703,17 +1711,21 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cmd);
             }
 
-            // Only pass correct values for these flags for the `run-make` suite as it
-            // requires that a C++ compiler was configured which isn't always the case.
-            if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") {
+            if !builder.config.dry_run()
+                && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "run-coverage")
+            {
                 // The llvm/bin directory contains many useful cross-platform
                 // tools. Pass the path to run-make tests so they can use them.
+                // (The run-coverage tests also need these tools to process
+                // coverage reports.)
                 let llvm_bin_path = llvm_config
                     .parent()
                     .expect("Expected llvm-config to be contained in directory");
                 assert!(llvm_bin_path.is_dir());
                 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
+            }
 
+            if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") {
                 // If LLD is available, add it to the PATH
                 if builder.config.lld_enabled {
                     let lld_install_root =
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 85a8fbcffbe..81684c6f9f9 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -66,6 +66,7 @@ string_enum! {
         JsDocTest => "js-doc-test",
         MirOpt => "mir-opt",
         Assembly => "assembly",
+        RunCoverage => "run-coverage",
     }
 }
 
@@ -626,6 +627,7 @@ pub const UI_EXTENSIONS: &[&str] = &[
     UI_STDERR_64,
     UI_STDERR_32,
     UI_STDERR_16,
+    UI_COVERAGE,
 ];
 pub const UI_STDERR: &str = "stderr";
 pub const UI_STDOUT: &str = "stdout";
@@ -635,6 +637,7 @@ pub const UI_RUN_STDOUT: &str = "run.stdout";
 pub const UI_STDERR_64: &str = "64bit.stderr";
 pub const UI_STDERR_32: &str = "32bit.stderr";
 pub const UI_STDERR_16: &str = "16bit.stderr";
+pub const UI_COVERAGE: &str = "coverage";
 
 /// Absolute path to the directory where all output for all tests in the given
 /// `relative_dir` group should reside. Example:
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 8cc935e54d1..c835962ad12 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -161,7 +161,7 @@ pub struct TestProps {
     // customized normalization rules
     pub normalize_stdout: Vec<(String, String)>,
     pub normalize_stderr: Vec<(String, String)>,
-    pub failure_status: i32,
+    pub failure_status: Option<i32>,
     // For UI tests, allows compiler to exit with arbitrary failure status
     pub dont_check_failure_status: bool,
     // Whether or not `rustfix` should apply the `CodeSuggestion`s of this test and compile the
@@ -257,7 +257,7 @@ impl TestProps {
             check_test_line_numbers_match: false,
             normalize_stdout: vec![],
             normalize_stderr: vec![],
-            failure_status: -1,
+            failure_status: None,
             dont_check_failure_status: false,
             run_rustfix: false,
             rustfix_only_machine_applicable: false,
@@ -428,7 +428,7 @@ impl TestProps {
                     .parse_name_value_directive(ln, FAILURE_STATUS)
                     .and_then(|code| code.trim().parse::<i32>().ok())
                 {
-                    self.failure_status = code;
+                    self.failure_status = Some(code);
                 }
 
                 config.set_name_directive(
@@ -491,11 +491,8 @@ impl TestProps {
             });
         }
 
-        if self.failure_status == -1 {
-            self.failure_status = 1;
-        }
         if self.should_ice {
-            self.failure_status = 101;
+            self.failure_status = Some(101);
         }
 
         if config.mode == Mode::Incremental {
@@ -615,10 +612,25 @@ pub fn line_directive<'line>(
 }
 
 fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str, usize)) {
+    iter_header_extra(testfile, rdr, &[], it)
+}
+
+fn iter_header_extra(
+    testfile: &Path,
+    rdr: impl Read,
+    extra_directives: &[&str],
+    it: &mut dyn FnMut(Option<&str>, &str, usize),
+) {
     if testfile.is_dir() {
         return;
     }
 
+    // Process any extra directives supplied by the caller (e.g. because they
+    // are implied by the test mode), with a dummy line number of 0.
+    for directive in extra_directives {
+        it(None, directive, 0);
+    }
+
     let comment = if testfile.extension().map(|e| e == "rs") == Some(true) { "//" } else { "#" };
 
     let mut rdr = BufReader::new(rdr);
@@ -897,7 +909,27 @@ pub fn make_test_description<R: Read>(
     let mut ignore_message = None;
     let mut should_fail = false;
 
-    iter_header(path, src, &mut |revision, ln, line_number| {
+    let extra_directives: &[&str] = match config.mode {
+        // The run-coverage tests are treated as having these extra directives,
+        // without needing to specify them manually in every test file.
+        // (Some of the comments below have been copied over from
+        // `tests/run-make/coverage-reports/Makefile`, which no longer exists.)
+        Mode::RunCoverage => {
+            &[
+                "needs-profiler-support",
+                // 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.
+                "ignore-windows-gnu",
+                // FIXME(pietroalbini): this test currently does not work on cross-compiled
+                // targets because remote-test is not capable of sending back the *.profraw
+                // files generated by the LLVM instrumentation.
+                "ignore-cross-compile",
+            ]
+        }
+        _ => &[],
+    };
+
+    iter_header_extra(path, src, extra_directives, &mut |revision, ln, line_number| {
         if revision.is_some() && revision != cfg {
             return;
         }
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 0e306696a90..62364ede47b 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -87,7 +87,7 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-profiler-support",
-            condition: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
+            condition: cache.profiler_support,
             ignore_reason: "ignored when profiler support is disabled",
         },
         Need {
@@ -195,6 +195,7 @@ pub(super) struct CachedNeedsConditions {
     sanitizer_memtag: bool,
     sanitizer_shadow_call_stack: bool,
     sanitizer_safestack: bool,
+    profiler_support: bool,
     xray: bool,
     rust_lld: bool,
     i686_dlltool: bool,
@@ -232,6 +233,7 @@ impl CachedNeedsConditions {
             sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target),
             sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target),
             sanitizer_safestack: util::SAFESTACK_SUPPORTED_TARGETS.contains(target),
+            profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
             xray: util::XRAY_SUPPORTED_TARGETS.contains(target),
 
             // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 5c8ee7895d3..8bdc2d65d27 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -6,8 +6,8 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs
 use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
 use crate::common::{CompareMode, FailMode, PassMode};
 use crate::common::{Config, TestPaths};
-use crate::common::{Pretty, RunPassValgrind};
-use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
+use crate::common::{Pretty, RunCoverage, RunPassValgrind};
+use crate::common::{UI_COVERAGE, UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::compute_diff::{write_diff, write_filtered_diff};
 use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
@@ -253,6 +253,7 @@ impl<'test> TestCx<'test> {
             MirOpt => self.run_mir_opt_test(),
             Assembly => self.run_assembly_test(),
             JsDocTest => self.run_js_doc_test(),
+            RunCoverage => self.run_coverage_test(),
         }
     }
 
@@ -384,7 +385,7 @@ impl<'test> TestCx<'test> {
     }
 
     fn check_correct_failure_status(&self, proc_res: &ProcRes) {
-        let expected_status = Some(self.props.failure_status);
+        let expected_status = Some(self.props.failure_status.unwrap_or(1));
         let received_status = proc_res.status.code();
 
         if expected_status != received_status {
@@ -465,6 +466,296 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    fn run_coverage_test(&self) {
+        let should_run = self.run_if_enabled();
+        let proc_res = self.compile_test(should_run, Emit::None);
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+        drop(proc_res);
+
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let profraw_path = self.output_base_dir().join("default.profraw");
+        let profdata_path = self.output_base_dir().join("default.profdata");
+
+        // Delete any existing profraw/profdata files to rule out unintended
+        // interference between repeated test runs.
+        if profraw_path.exists() {
+            std::fs::remove_file(&profraw_path).unwrap();
+        }
+        if profdata_path.exists() {
+            std::fs::remove_file(&profdata_path).unwrap();
+        }
+
+        let proc_res = self.exec_compiled_test_general(
+            &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())],
+            false,
+        );
+        if self.props.failure_status.is_some() {
+            self.check_correct_failure_status(&proc_res);
+        } else if !proc_res.status.success() {
+            self.fatal_proc_rec("test run failed!", &proc_res);
+        }
+        drop(proc_res);
+
+        let mut profraw_paths = vec![profraw_path];
+        let mut bin_paths = vec![self.make_exe_name()];
+
+        if self.config.suite == "run-coverage-rustdoc" {
+            self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths);
+        }
+
+        // Run `llvm-profdata merge` to index the raw coverage output.
+        let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| {
+            cmd.args(["merge", "--sparse", "--output"]);
+            cmd.arg(&profdata_path);
+            cmd.args(&profraw_paths);
+        });
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res);
+        }
+        drop(proc_res);
+
+        // Run `llvm-cov show` to produce a coverage report in text format.
+        let proc_res = self.run_llvm_tool("llvm-cov", |cmd| {
+            cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]);
+
+            cmd.arg("--Xdemangler");
+            cmd.arg(self.config.rust_demangler_path.as_ref().unwrap());
+
+            cmd.arg("--instr-profile");
+            cmd.arg(&profdata_path);
+
+            for bin in &bin_paths {
+                cmd.arg("--object");
+                cmd.arg(bin);
+            }
+        });
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("llvm-cov show failed!", &proc_res);
+        }
+
+        let kind = UI_COVERAGE;
+
+        let expected_coverage = self.load_expected_output(kind);
+        let normalized_actual_coverage =
+            self.normalize_coverage_output(&proc_res.stdout).unwrap_or_else(|err| {
+                self.fatal_proc_rec(&err, &proc_res);
+            });
+
+        let coverage_errors = self.compare_output(
+            kind,
+            &normalized_actual_coverage,
+            &expected_coverage,
+            self.props.compare_output_lines_by_subset,
+        );
+
+        if coverage_errors > 0 {
+            self.fatal_proc_rec(
+                &format!("{} errors occurred comparing coverage output.", coverage_errors),
+                &proc_res,
+            );
+        }
+    }
+
+    /// Run any doctests embedded in this test file, and add any resulting
+    /// `.profraw` files and doctest executables to the given vectors.
+    fn run_doctests_for_coverage(
+        &self,
+        profraw_paths: &mut Vec<PathBuf>,
+        bin_paths: &mut Vec<PathBuf>,
+    ) {
+        // Put .profraw files and doctest executables in dedicated directories,
+        // to make it easier to glob them all later.
+        let profraws_dir = self.output_base_dir().join("doc_profraws");
+        let bins_dir = self.output_base_dir().join("doc_bins");
+
+        // Remove existing directories to prevent cross-run interference.
+        if profraws_dir.try_exists().unwrap() {
+            std::fs::remove_dir_all(&profraws_dir).unwrap();
+        }
+        if bins_dir.try_exists().unwrap() {
+            std::fs::remove_dir_all(&bins_dir).unwrap();
+        }
+
+        let mut rustdoc_cmd =
+            Command::new(self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed"));
+
+        // In general there will be multiple doctest binaries running, so we
+        // tell the profiler runtime to write their coverage data into separate
+        // profraw files.
+        rustdoc_cmd.env("LLVM_PROFILE_FILE", profraws_dir.join("%p-%m.profraw"));
+
+        rustdoc_cmd.args(["--test", "-Cinstrument-coverage"]);
+
+        // Without this, the doctests complain about not being able to find
+        // their enclosing file's crate for some reason.
+        rustdoc_cmd.args(["--crate-name", "workaround_for_79771"]);
+
+        // Persist the doctest binaries so that `llvm-cov show` can read their
+        // embedded coverage mappings later.
+        rustdoc_cmd.arg("-Zunstable-options");
+        rustdoc_cmd.arg("--persist-doctests");
+        rustdoc_cmd.arg(&bins_dir);
+
+        rustdoc_cmd.arg("-L");
+        rustdoc_cmd.arg(self.aux_output_dir_name());
+
+        rustdoc_cmd.arg(&self.testpaths.file);
+
+        let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("rustdoc --test failed!", &proc_res)
+        }
+
+        fn glob_iter(path: impl AsRef<Path>) -> impl Iterator<Item = PathBuf> {
+            let path_str = path.as_ref().to_str().unwrap();
+            let iter = glob(path_str).unwrap();
+            iter.map(Result::unwrap)
+        }
+
+        // Find all profraw files in the profraw directory.
+        for p in glob_iter(profraws_dir.join("*.profraw")) {
+            profraw_paths.push(p);
+        }
+        // Find all executables in the `--persist-doctests` directory, while
+        // avoiding other file types (e.g. `.pdb` on Windows). This doesn't
+        // need to be perfect, as long as it can handle the files actually
+        // produced by `rustdoc --test`.
+        for p in glob_iter(bins_dir.join("**/*")) {
+            let is_bin = p.is_file()
+                && match p.extension() {
+                    None => true,
+                    Some(ext) => ext == OsStr::new("exe"),
+                };
+            if is_bin {
+                bin_paths.push(p);
+            }
+        }
+    }
+
+    fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes {
+        let tool_path = self
+            .config
+            .llvm_bin_dir
+            .as_ref()
+            .expect("this test expects the LLVM bin dir to be available")
+            .join(name);
+
+        let mut cmd = Command::new(tool_path);
+        configure_cmd_fn(&mut cmd);
+
+        let output = cmd.output().unwrap_or_else(|_| panic!("failed to exec `{cmd:?}`"));
+
+        let proc_res = ProcRes {
+            status: output.status,
+            stdout: String::from_utf8(output.stdout).unwrap(),
+            stderr: String::from_utf8(output.stderr).unwrap(),
+            cmdline: format!("{cmd:?}"),
+        };
+        self.dump_output(&proc_res.stdout, &proc_res.stderr);
+
+        proc_res
+    }
+
+    fn normalize_coverage_output(&self, coverage: &str) -> Result<String, String> {
+        let normalized = self.normalize_output(coverage, &[]);
+
+        let mut lines = normalized.lines().collect::<Vec<_>>();
+
+        Self::sort_coverage_file_sections(&mut lines)?;
+        Self::sort_coverage_subviews(&mut lines)?;
+
+        let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::<String>();
+        Ok(joined_lines)
+    }
+
+    /// Coverage reports can describe multiple source files, separated by
+    /// blank lines. The order of these files is unpredictable (since it
+    /// depends on implementation details), so we need to sort the file
+    /// sections into a consistent order before comparing against a snapshot.
+    fn sort_coverage_file_sections(coverage_lines: &mut Vec<&str>) -> Result<(), String> {
+        // Group the lines into file sections, separated by blank lines.
+        let mut sections = coverage_lines.split(|line| line.is_empty()).collect::<Vec<_>>();
+
+        // The last section should be empty, representing an extra trailing blank line.
+        if !sections.last().is_some_and(|last| last.is_empty()) {
+            return Err("coverage report should end with an extra blank line".to_owned());
+        }
+
+        // Sort the file sections (not including the final empty "section").
+        let except_last = sections.len() - 1;
+        (&mut sections[..except_last]).sort();
+
+        // Join the file sections back into a flat list of lines, with
+        // sections separated by blank lines.
+        let joined = sections.join(&[""] as &[_]);
+        assert_eq!(joined.len(), coverage_lines.len());
+        *coverage_lines = joined;
+
+        Ok(())
+    }
+
+    fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> {
+        let mut output_lines = Vec::new();
+
+        // We accumulate a list of zero or more "subviews", where each
+        // subview is a list of one or more lines.
+        let mut subviews: Vec<Vec<&str>> = Vec::new();
+
+        fn flush<'a>(subviews: &mut Vec<Vec<&'a str>>, output_lines: &mut Vec<&'a str>) {
+            if subviews.is_empty() {
+                return;
+            }
+
+            // Take and clear the list of accumulated subviews.
+            let mut subviews = std::mem::take(subviews);
+
+            // The last "subview" should be just a boundary line on its own,
+            // so exclude it when sorting the other subviews.
+            let except_last = subviews.len() - 1;
+            (&mut subviews[..except_last]).sort();
+
+            for view in subviews {
+                for line in view {
+                    output_lines.push(line);
+                }
+            }
+        }
+
+        for (line, line_num) in coverage_lines.iter().zip(1..) {
+            if line.starts_with("  ------------------") {
+                // This is a subview boundary line, so start a new subview.
+                subviews.push(vec![line]);
+            } else if line.starts_with("  |") {
+                // Add this line to the current subview.
+                subviews
+                    .last_mut()
+                    .ok_or(format!(
+                        "unexpected subview line outside of a subview on line {line_num}"
+                    ))?
+                    .push(line);
+            } else {
+                // This line is not part of a subview, so sort and print any
+                // accumulated subviews, and then print the line as-is.
+                flush(&mut subviews, &mut output_lines);
+                output_lines.push(line);
+            }
+        }
+
+        flush(&mut subviews, &mut output_lines);
+        assert!(subviews.is_empty());
+
+        assert_eq!(output_lines.len(), coverage_lines.len());
+        *coverage_lines = output_lines;
+
+        Ok(())
+    }
+
     fn run_pretty_test(&self) {
         if self.props.pp_exact.is_some() {
             logv(self.config, "testing for exact pretty-printing".to_owned());
@@ -1598,7 +1889,26 @@ impl<'test> TestCx<'test> {
     }
 
     fn exec_compiled_test(&self) -> ProcRes {
-        let env = &self.props.exec_env;
+        self.exec_compiled_test_general(&[], true)
+    }
+
+    fn exec_compiled_test_general(
+        &self,
+        env_extra: &[(&str, &str)],
+        delete_after_success: bool,
+    ) -> ProcRes {
+        let prepare_env = |cmd: &mut Command| {
+            for key in &self.props.unset_exec_env {
+                cmd.env_remove(key);
+            }
+
+            for (key, val) in &self.props.exec_env {
+                cmd.env(key, val);
+            }
+            for (key, val) in env_extra {
+                cmd.env(key, val);
+            }
+        };
 
         let proc_res = match &*self.config.target {
             // This is pretty similar to below, we're transforming:
@@ -1635,10 +1945,7 @@ impl<'test> TestCx<'test> {
                     .args(support_libs)
                     .args(args);
 
-                for key in &self.props.unset_exec_env {
-                    test_client.env_remove(key);
-                }
-                test_client.envs(env.clone());
+                prepare_env(&mut test_client);
 
                 self.compose_and_run(
                     test_client,
@@ -1653,10 +1960,7 @@ impl<'test> TestCx<'test> {
                 let mut wr_run = Command::new("wr-run");
                 wr_run.args(&[&prog]).args(args);
 
-                for key in &self.props.unset_exec_env {
-                    wr_run.env_remove(key);
-                }
-                wr_run.envs(env.clone());
+                prepare_env(&mut wr_run);
 
                 self.compose_and_run(
                     wr_run,
@@ -1671,10 +1975,7 @@ impl<'test> TestCx<'test> {
                 let mut program = Command::new(&prog);
                 program.args(args).current_dir(&self.output_base_dir());
 
-                for key in &self.props.unset_exec_env {
-                    program.env_remove(key);
-                }
-                program.envs(env.clone());
+                prepare_env(&mut program);
 
                 self.compose_and_run(
                     program,
@@ -1685,7 +1986,7 @@ impl<'test> TestCx<'test> {
             }
         };
 
-        if proc_res.status.success() {
+        if delete_after_success && proc_res.status.success() {
             // delete the executable after running it to save space.
             // it is ok if the deletion failed.
             let _ = fs::remove_file(self.make_exe_name());
@@ -1812,6 +2113,7 @@ impl<'test> TestCx<'test> {
             || self.is_vxworks_pure_static()
             || self.config.target.contains("bpf")
             || !self.config.target_cfg().dynamic_linking
+            || self.config.mode == RunCoverage
         {
             // We primarily compile all auxiliary libraries as dynamic libraries
             // to avoid code size bloat and large binaries as much as possible
@@ -1822,6 +2124,10 @@ impl<'test> TestCx<'test> {
             // dynamic libraries so we just go back to building a normal library. Note,
             // however, that for MUSL if the library is built with `force_host` then
             // it's ok to be a dylib as the host should always support dylibs.
+            //
+            // Coverage tests want static linking by default so that coverage
+            // mappings in auxiliary libraries can be merged into the final
+            // executable.
             (false, Some("lib"))
         } else {
             (true, Some("dylib"))
@@ -1999,6 +2305,10 @@ impl<'test> TestCx<'test> {
                     }
                 }
                 DebugInfo => { /* debuginfo tests must be unoptimized */ }
+                RunCoverage => {
+                    // Coverage reports are affected by optimization level, and
+                    // the current snapshots assume no optimization by default.
+                }
                 _ => {
                     rustc.arg("-O");
                 }
@@ -2065,6 +2375,9 @@ impl<'test> TestCx<'test> {
 
                 rustc.arg(dir_opt);
             }
+            RunCoverage => {
+                rustc.arg("-Cinstrument-coverage");
+            }
             RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake
             | CodegenUnits | JsDocTest | Assembly => {
                 // do not use JSON output
diff --git a/tests/run-make/coverage/lib/doctest_crate.rs b/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs
index c3210146d69..c3210146d69 100644
--- a/tests/run-make/coverage/lib/doctest_crate.rs
+++ b/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt b/tests/run-coverage-rustdoc/doctest.coverage
index 732de652627..0fce73a6048 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt
+++ b/tests/run-coverage-rustdoc/doctest.coverage
@@ -1,4 +1,15 @@
-../coverage/doctest.rs:
+$DIR/auxiliary/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|}
+
+$DIR/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|       |//!
@@ -67,7 +78,7 @@
    63|       |//!     doctest_main()
    64|       |//! }
    65|       |//! ```
-   66|       |
+   66|       |// aux-build:doctest_crate.rs
    67|       |/// doctest attached to fn testing external code:
    68|       |/// ```
    69|      1|/// extern crate doctest_crate;
@@ -102,14 +113,3 @@
    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|}
-
diff --git a/tests/run-make/coverage/doctest.rs b/tests/run-coverage-rustdoc/doctest.rs
index ec04ea57063..251b0c291e9 100644
--- a/tests/run-make/coverage/doctest.rs
+++ b/tests/run-coverage-rustdoc/doctest.rs
@@ -63,7 +63,7 @@
 //!     doctest_main()
 //! }
 //! ```
-
+// aux-build:doctest_crate.rs
 /// doctest attached to fn testing external code:
 /// ```
 /// extern crate doctest_crate;
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-coverage/abort.coverage
index a71c58d618d..a71c58d618d 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
+++ b/tests/run-coverage/abort.coverage
diff --git a/tests/run-make/coverage/abort.rs b/tests/run-coverage/abort.rs
index 98264bdc1af..98264bdc1af 100644
--- a/tests/run-make/coverage/abort.rs
+++ b/tests/run-coverage/abort.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.assert.txt b/tests/run-coverage/assert.coverage
index 405688806ea..a7134a149e2 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.assert.txt
+++ b/tests/run-coverage/assert.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-101
+    2|       |// failure-status: 101
     3|       |
     4|      4|fn might_fail_assert(one_plus_one: u32) {
     5|      4|    println!("does 1 + 1 = {}?", one_plus_one);
diff --git a/tests/run-make/coverage/assert.rs b/tests/run-coverage/assert.rs
index c85f2748eb9..d32a37e078e 100644
--- a/tests/run-make/coverage/assert.rs
+++ b/tests/run-coverage/assert.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-101
+// failure-status: 101
 
 fn might_fail_assert(one_plus_one: u32) {
     println!("does 1 + 1 = {}?", one_plus_one);
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async.txt b/tests/run-coverage/async.coverage
index 93c1535b06b..93c1535b06b 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.async.txt
+++ b/tests/run-coverage/async.coverage
diff --git a/tests/run-make/coverage/async.rs b/tests/run-coverage/async.rs
index efd9e62d64e..efd9e62d64e 100644
--- a/tests/run-make/coverage/async.rs
+++ b/tests/run-coverage/async.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async2.txt b/tests/run-coverage/async2.coverage
index 500dde1f269..500dde1f269 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.async2.txt
+++ b/tests/run-coverage/async2.coverage
diff --git a/tests/run-make/coverage/async2.rs b/tests/run-coverage/async2.rs
index 959d48ce9db..959d48ce9db 100644
--- a/tests/run-make/coverage/async2.rs
+++ b/tests/run-coverage/async2.rs
diff --git a/tests/run-make/coverage/lib/inline_always_with_dead_code.rs b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
index 2b21dee6ccf..2b21dee6ccf 100644
--- a/tests/run-make/coverage/lib/inline_always_with_dead_code.rs
+++ b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
diff --git a/tests/run-make/coverage/lib/unused_mod_helper.rs b/tests/run-coverage/auxiliary/unused_mod_helper.rs
index ae1cc1531ed..ae1cc1531ed 100644
--- a/tests/run-make/coverage/lib/unused_mod_helper.rs
+++ b/tests/run-coverage/auxiliary/unused_mod_helper.rs
diff --git a/tests/run-make/coverage/lib/used_crate.rs b/tests/run-coverage/auxiliary/used_crate.rs
index 8b8b1f7f351..16592d48dda 100644
--- a/tests/run-make/coverage/lib/used_crate.rs
+++ b/tests/run-coverage/auxiliary/used_crate.rs
@@ -1,6 +1,6 @@
 #![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-use std::fmt::Debug;
+// compile-flags: -C opt-level=3
+use std::fmt::Debug; // ^^ validates coverage now works with optimizations
 
 pub fn used_function() {
     // Initialize test constants in a way that cannot be determined at compile time, to ensure
diff --git a/tests/run-make/coverage/lib/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs
index 4a052756d4e..8b8e9d5483f 100644
--- a/tests/run-make/coverage/lib/used_inline_crate.rs
+++ b/tests/run-coverage/auxiliary/used_inline_crate.rs
@@ -1,7 +1,7 @@
 #![allow(unused_assignments, unused_variables)]
 
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-
+// compile-flags: -C opt-level=3
+// ^^ validates coverage now works with optimizations
 use std::fmt::Debug;
 
 pub fn used_function() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt b/tests/run-coverage/closure.coverage
index 002ecec3b91..45d36b72e3a 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt
+++ b/tests/run-coverage/closure.coverage
@@ -1,6 +1,6 @@
     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() {
+    2|       |// compile-flags: -C opt-level=2
+    3|      1|fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
     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.
diff --git a/tests/run-make/coverage/closure.rs b/tests/run-coverage/closure.rs
index 32ec0bcdf8c..eb3a1ebff88 100644
--- a/tests/run-make/coverage/closure.rs
+++ b/tests/run-coverage/closure.rs
@@ -1,6 +1,6 @@
 #![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
-fn main() {
+// compile-flags: -C opt-level=2
+fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
     // 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.
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt b/tests/run-coverage/closure_macro.coverage
index 87f7014760e..87f7014760e 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
+++ b/tests/run-coverage/closure_macro.coverage
diff --git a/tests/run-make/coverage/closure_macro.rs b/tests/run-coverage/closure_macro.rs
index 5e3b00d1ef5..5e3b00d1ef5 100644
--- a/tests/run-make/coverage/closure_macro.rs
+++ b/tests/run-coverage/closure_macro.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt b/tests/run-coverage/closure_macro_async.coverage
index 2b5418132c3..2b5418132c3 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
+++ b/tests/run-coverage/closure_macro_async.coverage
diff --git a/tests/run-make/coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs
index e3e89e9c8b3..e3e89e9c8b3 100644
--- a/tests/run-make/coverage/closure_macro_async.rs
+++ b/tests/run-coverage/closure_macro_async.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt b/tests/run-coverage/conditions.coverage
index 2d8a98a5d0c..2d8a98a5d0c 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt
+++ b/tests/run-coverage/conditions.coverage
diff --git a/tests/run-make/coverage/conditions.rs b/tests/run-coverage/conditions.rs
index 057599d1b47..057599d1b47 100644
--- a/tests/run-make/coverage/conditions.rs
+++ b/tests/run-coverage/conditions.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt b/tests/run-coverage/continue.coverage
index bf42924b191..bf42924b191 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt
+++ b/tests/run-coverage/continue.coverage
diff --git a/tests/run-make/coverage/continue.rs b/tests/run-coverage/continue.rs
index 624aa98341b..624aa98341b 100644
--- a/tests/run-make/coverage/continue.rs
+++ b/tests/run-coverage/continue.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt b/tests/run-coverage/dead_code.coverage
index 09ff14c6f27..09ff14c6f27 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt
+++ b/tests/run-coverage/dead_code.coverage
diff --git a/tests/run-make/coverage/dead_code.rs b/tests/run-coverage/dead_code.rs
index a1285df0ec6..a1285df0ec6 100644
--- a/tests/run-make/coverage/dead_code.rs
+++ b/tests/run-coverage/dead_code.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt b/tests/run-coverage/drop_trait.coverage
index fe6a9e93cbf..293001e9590 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
+++ b/tests/run-coverage/drop_trait.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|       |struct Firework {
     5|       |    strength: i32,
diff --git a/tests/run-make/coverage/drop_trait.rs b/tests/run-coverage/drop_trait.rs
index d15bfc0f877..a9b5d1d1e7f 100644
--- a/tests/run-make/coverage/drop_trait.rs
+++ b/tests/run-coverage/drop_trait.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 struct Firework {
     strength: i32,
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generator.txt b/tests/run-coverage/generator.coverage
index 0fb3808ff2e..0fb3808ff2e 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.generator.txt
+++ b/tests/run-coverage/generator.coverage
diff --git a/tests/run-make/coverage/generator.rs b/tests/run-coverage/generator.rs
index 4319991021e..4319991021e 100644
--- a/tests/run-make/coverage/generator.rs
+++ b/tests/run-coverage/generator.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generics.txt b/tests/run-coverage/generics.coverage
index 7eb33a29a92..7a7649674ca 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.generics.txt
+++ b/tests/run-coverage/generics.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|       |struct Firework<T> where T: Copy + std::fmt::Display {
     5|       |    strength: T,
diff --git a/tests/run-make/coverage/generics.rs b/tests/run-coverage/generics.rs
index 18b38868496..150ffb9db39 100644
--- a/tests/run-make/coverage/generics.rs
+++ b/tests/run-coverage/generics.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 struct Firework<T> where T: Copy + std::fmt::Display {
     strength: T,
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if.txt b/tests/run-coverage/if.coverage
index 0c9eff227ed..0c9eff227ed 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.if.txt
+++ b/tests/run-coverage/if.coverage
diff --git a/tests/run-make/coverage/if.rs b/tests/run-coverage/if.rs
index 8ad5042ff7b..8ad5042ff7b 100644
--- a/tests/run-make/coverage/if.rs
+++ b/tests/run-coverage/if.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt b/tests/run-coverage/if_else.coverage
index 4285d318686..4285d318686 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt
+++ b/tests/run-coverage/if_else.coverage
diff --git a/tests/run-make/coverage/if_else.rs b/tests/run-coverage/if_else.rs
index 3244e1e3afd..3244e1e3afd 100644
--- a/tests/run-make/coverage/if_else.rs
+++ b/tests/run-coverage/if_else.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt b/tests/run-coverage/inline-dead.coverage
index a59fe1146f4..a59fe1146f4 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
+++ b/tests/run-coverage/inline-dead.coverage
diff --git a/tests/run-make/coverage/inline-dead.rs b/tests/run-coverage/inline-dead.rs
index 854fa062967..854fa062967 100644
--- a/tests/run-make/coverage/inline-dead.rs
+++ b/tests/run-coverage/inline-dead.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline.txt b/tests/run-coverage/inline.coverage
index 6f5d1544fa0..6f5d1544fa0 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.inline.txt
+++ b/tests/run-coverage/inline.coverage
diff --git a/tests/run-make/coverage/inline.rs b/tests/run-coverage/inline.rs
index 9cfab9ddbad..9cfab9ddbad 100644
--- a/tests/run-make/coverage/inline.rs
+++ b/tests/run-coverage/inline.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt b/tests/run-coverage/inner_items.coverage
index 883254a09ba..883254a09ba 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt
+++ b/tests/run-coverage/inner_items.coverage
diff --git a/tests/run-make/coverage/inner_items.rs b/tests/run-coverage/inner_items.rs
index bcb62b3031c..bcb62b3031c 100644
--- a/tests/run-make/coverage/inner_items.rs
+++ b/tests/run-coverage/inner_items.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt b/tests/run-coverage/issue-83601.coverage
index 25c74ab2e70..25c74ab2e70 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
+++ b/tests/run-coverage/issue-83601.coverage
diff --git a/tests/run-make/coverage/issue-83601.rs b/tests/run-coverage/issue-83601.rs
index 0b72a81947c..0b72a81947c 100644
--- a/tests/run-make/coverage/issue-83601.rs
+++ b/tests/run-coverage/issue-83601.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/tests/run-coverage/issue-84561.coverage
index 4a60432c14c..7a97e353245 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
+++ b/tests/run-coverage/issue-84561.coverage
@@ -1,6 +1,6 @@
     1|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
     2|       |
-    3|       |// expect-exit-status-101
+    3|       |// failure-status: 101
     4|     21|#[derive(PartialEq, Eq)]
     5|       |struct Foo(u32);
     6|      1|fn test3() {
diff --git a/tests/run-make/coverage/issue-84561.rs b/tests/run-coverage/issue-84561.rs
index b39a289c45e..facf5b5b4cf 100644
--- a/tests/run-make/coverage/issue-84561.rs
+++ b/tests/run-coverage/issue-84561.rs
@@ -1,6 +1,6 @@
 // This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
 
-// expect-exit-status-101
+// failure-status: 101
 #[derive(PartialEq, Eq)]
 struct Foo(u32);
 fn test3() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt b/tests/run-coverage/issue-85461.coverage
index 1aa4a22c33e..d78a4a1129c 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
+++ b/tests/run-coverage/issue-85461.coverage
@@ -1,16 +1,4 @@
-../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:
+$DIR/auxiliary/inline_always_with_dead_code.rs:
     1|       |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
     2|       |
     3|       |#![allow(dead_code)]
@@ -34,3 +22,15 @@
    21|      1|    }
    22|       |}
 
+$DIR/issue-85461.rs:
+    1|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+    2|       |// aux-build:inline_always_with_dead_code.rs
+    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|}
+
diff --git a/tests/run-make/coverage/issue-85461.rs b/tests/run-coverage/issue-85461.rs
index a1b9ebb1ed3..6f626b4a65b 100644
--- a/tests/run-make/coverage/issue-85461.rs
+++ b/tests/run-coverage/issue-85461.rs
@@ -1,5 +1,5 @@
 // Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
-
+// aux-build:inline_always_with_dead_code.rs
 extern crate inline_always_with_dead_code;
 
 use inline_always_with_dead_code::{bar, baz};
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt b/tests/run-coverage/issue-93054.coverage
index a1655adedd4..a1655adedd4 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
+++ b/tests/run-coverage/issue-93054.coverage
diff --git a/tests/run-make/coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs
index c160b3db03f..c160b3db03f 100644
--- a/tests/run-make/coverage/issue-93054.rs
+++ b/tests/run-coverage/issue-93054.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt b/tests/run-coverage/lazy_boolean.coverage
index bd349df2fbc..bd349df2fbc 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
+++ b/tests/run-coverage/lazy_boolean.coverage
diff --git a/tests/run-make/coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs
index bb6219e851c..bb6219e851c 100644
--- a/tests/run-make/coverage/lazy_boolean.rs
+++ b/tests/run-coverage/lazy_boolean.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt b/tests/run-coverage/loop_break_value.coverage
index 022fe4c5962..022fe4c5962 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
+++ b/tests/run-coverage/loop_break_value.coverage
diff --git a/tests/run-make/coverage/loop_break_value.rs b/tests/run-coverage/loop_break_value.rs
index dbc4fad7a23..dbc4fad7a23 100644
--- a/tests/run-make/coverage/loop_break_value.rs
+++ b/tests/run-coverage/loop_break_value.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt b/tests/run-coverage/loops_branches.coverage
index b7ad79a2484..b7ad79a2484 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
+++ b/tests/run-coverage/loops_branches.coverage
diff --git a/tests/run-make/coverage/loops_branches.rs b/tests/run-coverage/loops_branches.rs
index 7116ce47f4b..7116ce47f4b 100644
--- a/tests/run-make/coverage/loops_branches.rs
+++ b/tests/run-coverage/loops_branches.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt b/tests/run-coverage/match_or_pattern.coverage
index a0fccb24f99..a0fccb24f99 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
+++ b/tests/run-coverage/match_or_pattern.coverage
diff --git a/tests/run-make/coverage/match_or_pattern.rs b/tests/run-coverage/match_or_pattern.rs
index 4c6a8a9b703..4c6a8a9b703 100644
--- a/tests/run-make/coverage/match_or_pattern.rs
+++ b/tests/run-coverage/match_or_pattern.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt b/tests/run-coverage/nested_loops.coverage
index 0dbd6bcf313..0dbd6bcf313 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
+++ b/tests/run-coverage/nested_loops.coverage
diff --git a/tests/run-make/coverage/nested_loops.rs b/tests/run-coverage/nested_loops.rs
index 4c7c7842796..4c7c7842796 100644
--- a/tests/run-make/coverage/nested_loops.rs
+++ b/tests/run-coverage/nested_loops.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt b/tests/run-coverage/no_cov_crate.coverage
index 83a9204136f..83a9204136f 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
+++ b/tests/run-coverage/no_cov_crate.coverage
diff --git a/tests/run-make/coverage/no_cov_crate.rs b/tests/run-coverage/no_cov_crate.rs
index 0bfbdda2cab..0bfbdda2cab 100644
--- a/tests/run-make/coverage/no_cov_crate.rs
+++ b/tests/run-coverage/no_cov_crate.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt b/tests/run-coverage/overflow.coverage
index 25e822bffd1..95043759166 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt
+++ b/tests/run-coverage/overflow.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-101
+    2|       |// failure-status: 101
     3|       |
     4|      4|fn might_overflow(to_add: u32) -> u32 {
     5|      4|    if to_add > 5 {
diff --git a/tests/run-make/coverage/overflow.rs b/tests/run-coverage/overflow.rs
index e537b0e95c3..7df8de6f3cd 100644
--- a/tests/run-make/coverage/overflow.rs
+++ b/tests/run-coverage/overflow.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-101
+// failure-status: 101
 
 fn might_overflow(to_add: u32) -> u32 {
     if to_add > 5 {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt b/tests/run-coverage/panic_unwind.coverage
index 114507dc9fd..58b9ba448ee 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
+++ b/tests/run-coverage/panic_unwind.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-101
+    2|       |// failure-status: 101
     3|       |
     4|      4|fn might_panic(should_panic: bool) {
     5|      4|    if should_panic {
diff --git a/tests/run-make/coverage/panic_unwind.rs b/tests/run-coverage/panic_unwind.rs
index 03128c2cce6..638d2eb6aaa 100644
--- a/tests/run-make/coverage/panic_unwind.rs
+++ b/tests/run-coverage/panic_unwind.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-101
+// failure-status: 101
 
 fn might_panic(should_panic: bool) {
     if should_panic {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt b/tests/run-coverage/partial_eq.coverage
index a77175af663..a77175af663 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
+++ b/tests/run-coverage/partial_eq.coverage
diff --git a/tests/run-make/coverage/partial_eq.rs b/tests/run-coverage/partial_eq.rs
index 4ceaba9b111..4ceaba9b111 100644
--- a/tests/run-make/coverage/partial_eq.rs
+++ b/tests/run-coverage/partial_eq.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt b/tests/run-coverage/simple_loop.coverage
index feb83bad674..feb83bad674 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
+++ b/tests/run-coverage/simple_loop.coverage
diff --git a/tests/run-make/coverage/simple_loop.rs b/tests/run-coverage/simple_loop.rs
index 6f7f23475b8..6f7f23475b8 100644
--- a/tests/run-make/coverage/simple_loop.rs
+++ b/tests/run-coverage/simple_loop.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt b/tests/run-coverage/simple_match.coverage
index b9298213111..b9298213111 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt
+++ b/tests/run-coverage/simple_match.coverage
diff --git a/tests/run-make/coverage/simple_match.rs b/tests/run-coverage/simple_match.rs
index be99e59a826..be99e59a826 100644
--- a/tests/run-make/coverage/simple_match.rs
+++ b/tests/run-coverage/simple_match.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt b/tests/run-coverage/sort_groups.coverage
index 81468cb35da..81468cb35da 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt
+++ b/tests/run-coverage/sort_groups.coverage
diff --git a/tests/run-make/coverage/sort_groups.rs b/tests/run-coverage/sort_groups.rs
index f89f9f3ec61..f89f9f3ec61 100644
--- a/tests/run-make/coverage/sort_groups.rs
+++ b/tests/run-coverage/sort_groups.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt b/tests/run-coverage/test_harness.coverage
index 93bd1cfcb48..93bd1cfcb48 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt
+++ b/tests/run-coverage/test_harness.coverage
diff --git a/tests/run-make/coverage/test_harness.rs b/tests/run-coverage/test_harness.rs
index 12a755734c1..12a755734c1 100644
--- a/tests/run-make/coverage/test_harness.rs
+++ b/tests/run-coverage/test_harness.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt b/tests/run-coverage/tight_inf_loop.coverage
index 2d4c57f451a..2d4c57f451a 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
+++ b/tests/run-coverage/tight_inf_loop.coverage
diff --git a/tests/run-make/coverage/tight_inf_loop.rs b/tests/run-coverage/tight_inf_loop.rs
index cef99027aaa..cef99027aaa 100644
--- a/tests/run-make/coverage/tight_inf_loop.rs
+++ b/tests/run-coverage/tight_inf_loop.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt b/tests/run-coverage/try_error_result.coverage
index 0ad0180b761..efe573a5607 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
+++ b/tests/run-coverage/try_error_result.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|      6|fn call(return_error: bool) -> Result<(),()> {
     5|      6|    if return_error {
diff --git a/tests/run-make/coverage/try_error_result.rs b/tests/run-coverage/try_error_result.rs
index cd0acf72302..9eb1d2db218 100644
--- a/tests/run-make/coverage/try_error_result.rs
+++ b/tests/run-coverage/try_error_result.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 fn call(return_error: bool) -> Result<(),()> {
     if return_error {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused.txt b/tests/run-coverage/unused.coverage
index 15fcf21c0ef..15fcf21c0ef 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.unused.txt
+++ b/tests/run-coverage/unused.coverage
diff --git a/tests/run-make/coverage/unused.rs b/tests/run-coverage/unused.rs
index fb6113eb01c..fb6113eb01c 100644
--- a/tests/run-make/coverage/unused.rs
+++ b/tests/run-coverage/unused.rs
diff --git a/tests/run-coverage/unused_mod.coverage b/tests/run-coverage/unused_mod.coverage
new file mode 100644
index 00000000000..e1d82f66f75
--- /dev/null
+++ b/tests/run-coverage/unused_mod.coverage
@@ -0,0 +1,13 @@
+$DIR/auxiliary/unused_mod_helper.rs:
+    1|      0|pub fn never_called_function() {
+    2|      0|    println!("I am never called");
+    3|      0|}
+
+$DIR/unused_mod.rs:
+    1|       |#[path = "auxiliary/unused_mod_helper.rs"]
+    2|       |mod unused_module;
+    3|       |
+    4|      1|fn main() {
+    5|      1|    println!("hello world!");
+    6|      1|}
+
diff --git a/tests/run-make/coverage/unused_mod.rs b/tests/run-coverage/unused_mod.rs
index 679b4e53188..6e62839c998 100644
--- a/tests/run-make/coverage/unused_mod.rs
+++ b/tests/run-coverage/unused_mod.rs
@@ -1,4 +1,4 @@
-#[path = "lib/unused_mod_helper.rs"]
+#[path = "auxiliary/unused_mod_helper.rs"]
 mod unused_module;
 
 fn main() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt b/tests/run-coverage/uses_crate.coverage
index 412f4a93b9c..a3b78e21405 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
+++ b/tests/run-coverage/uses_crate.coverage
@@ -1,6 +1,7 @@
+$DIR/auxiliary/used_crate.rs:
     1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-    3|       |use std::fmt::Debug;
+    2|       |// compile-flags: -C opt-level=3
+    3|       |use std::fmt::Debug; // ^^ validates coverage now works with optimizations
     4|       |
     5|      1|pub fn used_function() {
     6|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
@@ -146,3 +147,24 @@
    99|       |// functions" list, which would then omit coverage results for
   100|       |// `unused_generic_function<T>()`, below.
 
+$DIR/uses_crate.rs:
+    1|       |// FIXME #110395
+    2|       |// ignore-linux
+    3|       |
+    4|       |// Validates coverage now works with optimizations
+    5|       |// compile-flags: -C opt-level=3
+    6|       |
+    7|       |#![allow(unused_assignments, unused_variables)]
+    8|       |
+    9|       |// aux-build:used_crate.rs
+   10|       |extern crate used_crate;
+   11|       |
+   12|      1|fn main() {
+   13|      1|    used_crate::used_function();
+   14|      1|    let some_vec = vec![1, 2, 3, 4];
+   15|      1|    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   16|      1|    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   17|      1|    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   18|      1|    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+   19|      1|}
+
diff --git a/tests/run-make/coverage/uses_crate.rs b/tests/run-coverage/uses_crate.rs
index 1ee8037a1e7..ab466970f8e 100644
--- a/tests/run-make/coverage/uses_crate.rs
+++ b/tests/run-coverage/uses_crate.rs
@@ -1,8 +1,12 @@
 // FIXME #110395
-// ignore-llvm-cov-show-diffs
+// ignore-linux
+
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
 
 #![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+// aux-build:used_crate.rs
 extern crate used_crate;
 
 fn main() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/tests/run-coverage/uses_inline_crate.coverage
index 66ca9e80a32..f878d8107c5 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
+++ b/tests/run-coverage/uses_inline_crate.coverage
@@ -1,7 +1,8 @@
+$DIR/auxiliary/used_inline_crate.rs:
     1|       |#![allow(unused_assignments, unused_variables)]
     2|       |
-    3|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-    4|       |
+    3|       |// compile-flags: -C opt-level=3
+    4|       |// ^^ validates coverage now works with optimizations
     5|       |use std::fmt::Debug;
     6|       |
     7|      1|pub fn used_function() {
@@ -137,3 +138,27 @@
    89|      2|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
    90|      2|}
 
+$DIR/uses_inline_crate.rs:
+    1|       |// FIXME #110395
+    2|       |// ignore-linux
+    3|       |
+    4|       |// Validates coverage now works with optimizations
+    5|       |// compile-flags: -C opt-level=3
+    6|       |
+    7|       |#![allow(unused_assignments, unused_variables)]
+    8|       |
+    9|       |// aux-build:used_inline_crate.rs
+   10|       |extern crate used_inline_crate;
+   11|       |
+   12|      1|fn main() {
+   13|      1|    used_inline_crate::used_function();
+   14|      1|    used_inline_crate::used_inline_function();
+   15|      1|    let some_vec = vec![1, 2, 3, 4];
+   16|      1|    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   17|      1|    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   18|      1|    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   19|      1|    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   20|      1|        "interesting?",
+   21|      1|    );
+   22|      1|}
+
diff --git a/tests/run-make/coverage/uses_inline_crate.rs b/tests/run-coverage/uses_inline_crate.rs
index f7aff3c3f8a..4bd66d2f89c 100644
--- a/tests/run-make/coverage/uses_inline_crate.rs
+++ b/tests/run-coverage/uses_inline_crate.rs
@@ -1,10 +1,12 @@
 // FIXME #110395
-// ignore-llvm-cov-show-diffs
+// ignore-linux
 
-#![allow(unused_assignments, unused_variables)]
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
 
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+#![allow(unused_assignments, unused_variables)]
 
+// aux-build:used_inline_crate.rs
 extern crate used_inline_crate;
 
 fn main() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while.txt b/tests/run-coverage/while.coverage
index efa7d083f0c..efa7d083f0c 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.while.txt
+++ b/tests/run-coverage/while.coverage
diff --git a/tests/run-make/coverage/while.rs b/tests/run-coverage/while.rs
index 781b90b3566..781b90b3566 100644
--- a/tests/run-make/coverage/while.rs
+++ b/tests/run-coverage/while.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt b/tests/run-coverage/while_early_ret.coverage
index d19afc0de61..2ce94e0131d 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
+++ b/tests/run-coverage/while_early_ret.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|      1|fn main() -> Result<(),u8> {
     5|      1|    let mut countdown = 10;
diff --git a/tests/run-make/coverage/while_early_ret.rs b/tests/run-coverage/while_early_ret.rs
index 1fcea9c85c4..1c83c8fc7a8 100644
--- a/tests/run-make/coverage/while_early_ret.rs
+++ b/tests/run-coverage/while_early_ret.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 fn main() -> Result<(),u8> {
     let mut countdown = 10;
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.yield.txt b/tests/run-coverage/yield.coverage
index 6e2f23ee77b..6e2f23ee77b 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.yield.txt
+++ b/tests/run-coverage/yield.coverage
diff --git a/tests/run-make/coverage/yield.rs b/tests/run-coverage/yield.rs
index ff7616656ff..ff7616656ff 100644
--- a/tests/run-make/coverage/yield.rs
+++ b/tests/run-coverage/yield.rs
diff --git a/tests/run-make/coverage-llvmir/Makefile b/tests/run-make/coverage-llvmir/Makefile
index 7be65505332..be92f8ac8fc 100644
--- a/tests/run-make/coverage-llvmir/Makefile
+++ b/tests/run-make/coverage-llvmir/Makefile
@@ -6,7 +6,7 @@
 # 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
+include ../tools.mk
 
 BASEDIR=../coverage-llvmir
 
diff --git a/tests/run-make/coverage-reports/Makefile b/tests/run-make/coverage-reports/Makefile
deleted file mode 100644
index 0ae409c4119..00000000000
--- a/tests/run-make/coverage-reports/Makefile
+++ /dev/null
@@ -1,178 +0,0 @@
-# needs-profiler-support
-# ignore-windows-gnu
-
-# FIXME(pietroalbini): this test currently does not work on cross-compiled
-# targets because remote-test is not capable of sending back the *.profraw
-# files generated by the LLVM instrumentation.
-# ignore-cross-compile
-
-# 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 accommodated
-# 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 --target $(TARGET)
-
-%: $(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 --target $(TARGET)
-
-	# 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 \
-		| "$(PYTHON)" $(BASEDIR)/sort_subviews.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).
-	#
-	# `llvm-cov show` normally prints instantiation groups in an unpredictable
-	# order, but we have used `sort_subviews.py` to sort them, so we can still
-	# check the output directly with `diff`.
-	#
-	# Some of the test cases are currently not working (since #110393) and have
-	# been marked with `// ignore-llvm-cov-show-diffs` so that they don't fail
-	# the build.
-
-	$(DIFF) \
-		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
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt b/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
deleted file mode 100644
index 82d6fccc271..00000000000
--- a/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-    1|      0|pub fn never_called_function() {
-    2|      0|    println!("I am never called");
-    3|      0|}
-
diff --git a/tests/run-make/coverage-reports/normalize_paths.py b/tests/run-make/coverage-reports/normalize_paths.py
deleted file mode 100755
index e5777ad2512..00000000000
--- a/tests/run-make/coverage-reports/normalize_paths.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/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='')
diff --git a/tests/run-make/coverage-reports/sort_subviews.py b/tests/run-make/coverage-reports/sort_subviews.py
deleted file mode 100755
index 10cfc51d447..00000000000
--- a/tests/run-make/coverage-reports/sort_subviews.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python3
-
-# `llvm-cov show` prints grouped subviews (e.g. for generic functions) in an
-# unstable order, which is inconvenient when checking output snapshots with
-# `diff`. To work around that, this script detects consecutive subviews in its
-# piped input, and sorts them while preserving their contents.
-
-from __future__ import print_function
-
-import sys
-
-
-def main():
-    subviews = []
-
-    def flush_subviews():
-        if not subviews:
-            return
-
-        # The last "subview" should be just a boundary line on its own, so
-        # temporarily remove it before sorting the accumulated subviews.
-        terminator = subviews.pop()
-        subviews.sort()
-        subviews.append(terminator)
-
-        for view in subviews:
-            for line in view:
-                print(line, end="")
-
-        subviews.clear()
-
-    for line in sys.stdin:
-        if line.startswith("  ------------------"):
-            # This is a subview boundary line, so start a new subview.
-            subviews.append([line])
-        elif line.startswith("  |"):
-            # Add this line to the current subview.
-            subviews[-1].append(line)
-        else:
-            # This line is not part of a subview, so sort and print any
-            # accumulated subviews, and then print the line as-is.
-            flush_subviews()
-            print(line, end="")
-
-    flush_subviews()
-    assert not subviews
-
-
-if __name__ == "__main__":
-    main()
diff --git a/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt b/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
deleted file mode 100644
index 6a1403b8a00..00000000000
--- a/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-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.
diff --git a/tests/run-make/coverage/compiletest-ignore-dir b/tests/run-make/coverage/compiletest-ignore-dir
deleted file mode 100644
index 470ff996098..00000000000
--- a/tests/run-make/coverage/compiletest-ignore-dir
+++ /dev/null
@@ -1,3 +0,0 @@
-# Directory "coverage" supports the tests at prefix ../coverage-*
-
-# Use ./x.py [options] test tests/run-make/coverage to run all related tests.
diff --git a/tests/run-make/coverage/coverage_tools.mk b/tests/run-make/coverage/coverage_tools.mk
deleted file mode 100644
index 028c020a461..00000000000
--- a/tests/run-make/coverage/coverage_tools.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Common Makefile include for Rust `run-make/coverage-* tests. Include this
-# file with the line:
-#
-# include ../coverage/coverage_tools.mk
-
-include ../tools.mk