about summary refs log tree commit diff
path: root/tests/run-coverage
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2023-06-12 18:07:04 +1000
committerZalathar <Zalathar@users.noreply.github.com>2023-06-28 11:09:19 +1000
commita2c0b388970c95e9ccb088e2abc2cb4f02ed90ae (patch)
tree481333e971402d7239b3cad765e9ab3a188b4773 /tests/run-coverage
parent9d2564a1102bf20f5310c872582518302e5f049b (diff)
Migrate the remaining `run-make/coverage-reports` tests over to `run-coverage`
To make it easier to verify that the output snapshots have been migrated
faithfully, this change adds some temporary helper code that lets us avoid
having to completely re-bless the existing snapshots.

A later change in this PR will then re-bless the tests and remove the temporary
helper code.
Diffstat (limited to 'tests/run-coverage')
-rw-r--r--tests/run-coverage/auxiliary/inline_always_with_dead_code.rs22
-rw-r--r--tests/run-coverage/auxiliary/unused_mod_helper.rs3
-rw-r--r--tests/run-coverage/auxiliary/used_crate.rs100
-rw-r--r--tests/run-coverage/auxiliary/used_inline_crate.rs90
-rw-r--r--tests/run-coverage/issue-85461.coverage36
-rw-r--r--tests/run-coverage/issue-85461.rs10
-rw-r--r--tests/run-coverage/unused_mod.coverage4
-rw-r--r--tests/run-coverage/unused_mod.rs6
-rw-r--r--tests/run-coverage/uses_crate.coverage148
-rw-r--r--tests/run-coverage/uses_crate.rs19
-rw-r--r--tests/run-coverage/uses_inline_crate.coverage139
-rw-r--r--tests/run-coverage/uses_inline_crate.rs22
12 files changed, 599 insertions, 0 deletions
diff --git a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
new file mode 100644
index 00000000000..2b21dee6ccf
--- /dev/null
+++ b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
@@ -0,0 +1,22 @@
+// 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();
+    }
+}
diff --git a/tests/run-coverage/auxiliary/unused_mod_helper.rs b/tests/run-coverage/auxiliary/unused_mod_helper.rs
new file mode 100644
index 00000000000..ae1cc1531ed
--- /dev/null
+++ b/tests/run-coverage/auxiliary/unused_mod_helper.rs
@@ -0,0 +1,3 @@
+pub fn never_called_function() {
+    println!("I am never called");
+}
diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/run-coverage/auxiliary/used_crate.rs
new file mode 100644
index 00000000000..16592d48dda
--- /dev/null
+++ b/tests/run-coverage/auxiliary/used_crate.rs
@@ -0,0 +1,100 @@
+#![allow(unused_assignments, unused_variables)]
+// 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
+    // 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.
diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs
new file mode 100644
index 00000000000..8b8e9d5483f
--- /dev/null
+++ b/tests/run-coverage/auxiliary/used_inline_crate.rs
@@ -0,0 +1,90 @@
+#![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");
+}
diff --git a/tests/run-coverage/issue-85461.coverage b/tests/run-coverage/issue-85461.coverage
new file mode 100644
index 00000000000..0f11a69bd7a
--- /dev/null
+++ b/tests/run-coverage/issue-85461.coverage
@@ -0,0 +1,36 @@
+$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|}
+
+$DIR/auxiliary/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|       |}
+
diff --git a/tests/run-coverage/issue-85461.rs b/tests/run-coverage/issue-85461.rs
new file mode 100644
index 00000000000..6f626b4a65b
--- /dev/null
+++ b/tests/run-coverage/issue-85461.rs
@@ -0,0 +1,10 @@
+// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+// aux-build:inline_always_with_dead_code.rs
+extern crate inline_always_with_dead_code;
+
+use inline_always_with_dead_code::{bar, baz};
+
+fn main() {
+    bar::call_me();
+    baz::call_me();
+}
diff --git a/tests/run-coverage/unused_mod.coverage b/tests/run-coverage/unused_mod.coverage
new file mode 100644
index 00000000000..82d6fccc271
--- /dev/null
+++ b/tests/run-coverage/unused_mod.coverage
@@ -0,0 +1,4 @@
+    1|      0|pub fn never_called_function() {
+    2|      0|    println!("I am never called");
+    3|      0|}
+
diff --git a/tests/run-coverage/unused_mod.rs b/tests/run-coverage/unused_mod.rs
new file mode 100644
index 00000000000..6e62839c998
--- /dev/null
+++ b/tests/run-coverage/unused_mod.rs
@@ -0,0 +1,6 @@
+#[path = "auxiliary/unused_mod_helper.rs"]
+mod unused_module;
+
+fn main() {
+    println!("hello world!");
+}
diff --git a/tests/run-coverage/uses_crate.coverage b/tests/run-coverage/uses_crate.coverage
new file mode 100644
index 00000000000..5eb6d2667be
--- /dev/null
+++ b/tests/run-coverage/uses_crate.coverage
@@ -0,0 +1,148 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    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
+    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|}
+  ------------------
+  | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+  | 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|}
+  ------------------
+  | 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|}
+  ------------------
+   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::<&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|}
+  ------------------
+  | 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|}
+  ------------------
+   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::<&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|}
+  ------------------
+  | 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|}
+  ------------------
+   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.
+
diff --git a/tests/run-coverage/uses_crate.rs b/tests/run-coverage/uses_crate.rs
new file mode 100644
index 00000000000..ab466970f8e
--- /dev/null
+++ b/tests/run-coverage/uses_crate.rs
@@ -0,0 +1,19 @@
+// FIXME #110395
+// ignore-linux
+
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
+
+#![allow(unused_assignments, unused_variables)]
+
+// aux-build:used_crate.rs
+extern crate used_crate;
+
+fn main() {
+    used_crate::used_function();
+    let some_vec = vec![1, 2, 3, 4];
+    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+}
diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage
new file mode 100644
index 00000000000..9ba7177ef35
--- /dev/null
+++ b/tests/run-coverage/uses_inline_crate.coverage
@@ -0,0 +1,139 @@
+    1|       |#![allow(unused_assignments, unused_variables)]
+    2|       |
+    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() {
+    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|}
+  ------------------
+  | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+  | 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|}
+  ------------------
+   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::<&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|}
+  ------------------
+  | 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|}
+  ------------------
+   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::<&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|}
+  ------------------
+  | 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|}
+  ------------------
+   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|}
+
diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/run-coverage/uses_inline_crate.rs
new file mode 100644
index 00000000000..4bd66d2f89c
--- /dev/null
+++ b/tests/run-coverage/uses_inline_crate.rs
@@ -0,0 +1,22 @@
+// FIXME #110395
+// ignore-linux
+
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
+
+#![allow(unused_assignments, unused_variables)]
+
+// aux-build:used_inline_crate.rs
+extern crate used_inline_crate;
+
+fn main() {
+    used_inline_crate::used_function();
+    used_inline_crate::used_inline_function();
+    let some_vec = vec![1, 2, 3, 4];
+    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+        "interesting?",
+    );
+}