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 { + 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 { + None +} + +fn main() { }