about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs17
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-93054.txt29
-rw-r--r--src/test/run-make-fulldeps/coverage/issue-93054.rs28
3 files changed, 70 insertions, 4 deletions
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 32f18419753..3014d2f1930 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -9,6 +9,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefIdSet;
 use rustc_llvm::RustString;
+use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::CodeRegion;
 use rustc_middle::ty::TyCtxt;
@@ -76,10 +77,18 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
         let coverage_mapping_buffer = llvm::build_byte_buffer(|coverage_mapping_buffer| {
             mapgen.write_coverage_mapping(expressions, counter_regions, coverage_mapping_buffer);
         });
-        debug_assert!(
-            !coverage_mapping_buffer.is_empty(),
-            "Every `FunctionCoverage` should have at least one counter"
-        );
+
+        if coverage_mapping_buffer.is_empty() {
+            if function_coverage.is_used() {
+                bug!(
+                    "A used function should have had coverage mapping data but did not: {}",
+                    mangled_function_name
+                );
+            } else {
+                debug!("unused function had no coverage mapping data: {}", mangled_function_name);
+                continue;
+            }
+        }
 
         function_data.push((mangled_function_name, source_hash, is_used, coverage_mapping_buffer));
     }
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-93054.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-93054.txt
new file mode 100644
index 00000000000..a1655adedd4
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-93054.txt
@@ -0,0 +1,29 @@
+    1|       |// Regression test for #93054: Functions using uninhabited types often only have a single,
+    2|       |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+    3|       |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+    4|       |
+    5|       |// compile-flags: --edition=2021
+    6|       |
+    7|       |enum Never { }
+    8|       |
+    9|       |impl Never {
+   10|       |    fn foo(self) {
+   11|       |        match self { }
+   12|       |        make().map(|never| match never { });
+   13|       |    }
+   14|       |
+   15|       |    fn bar(&self) {
+   16|       |        match *self { }
+   17|       |    }
+   18|       |}
+   19|       |
+   20|      0|async fn foo2(never: Never) {
+   21|       |    match never { }
+   22|       |}
+   23|       |
+   24|      0|fn make() -> Option<Never> {
+   25|      0|    None
+   26|      0|}
+   27|       |
+   28|      1|fn main() { }
+
diff --git a/src/test/run-make-fulldeps/coverage/issue-93054.rs b/src/test/run-make-fulldeps/coverage/issue-93054.rs
new file mode 100644
index 00000000000..c160b3db03f
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage/issue-93054.rs
@@ -0,0 +1,28 @@
+// Regression test for #93054: Functions using uninhabited types often only have a single,
+// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+
+// compile-flags: --edition=2021
+
+enum Never { }
+
+impl Never {
+    fn foo(self) {
+        match self { }
+        make().map(|never| match never { });
+    }
+
+    fn bar(&self) {
+        match *self { }
+    }
+}
+
+async fn foo2(never: Never) {
+    match never { }
+}
+
+fn make() -> Option<Never> {
+    None
+}
+
+fn main() { }