Rollup merge of #131802 - compiler-errors:fnonce-coverage, r=Zalathar
Dont ICE when computing coverage of synthetic async closure body I'm not totally certain if this is *right*, but at least it doesn't ICE. The issue is that we end up generating two MIR bodies for each async closure, since the `FnOnce` and `Fn`/`FnMut` implementations have different borrowing behavior of their captured variables. They should ideally both contribute to the coverage, since those MIR bodies are (*to the user*) the same code and should have no behavioral differences. This PR at least suppresses the ICEs, and then I guess worst case we can fix this the right way later. r? Zalathar or re-roll Fixes #131190
This commit is contained in:
commit
aae4730c78
@ -570,6 +570,7 @@
|
||||
/// either `#[coverage(on)]` or no coverage attribute was found.
|
||||
query coverage_attr_on(key: LocalDefId) -> bool {
|
||||
desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) }
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass
|
||||
|
@ -223,6 +223,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
|
||||
|
||||
// Inherited from the by-ref coroutine.
|
||||
body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
|
||||
body_def.coverage_attr_on(tcx.coverage_attr_on(coroutine_def_id));
|
||||
body_def.constness(tcx.constness(coroutine_def_id));
|
||||
body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id));
|
||||
body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id));
|
||||
|
@ -524,6 +524,11 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir
|
||||
// FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
|
||||
// to HIR for it.
|
||||
|
||||
// HACK: For synthetic MIR bodies (async closures), use the def id of the HIR body.
|
||||
if tcx.is_synthetic_mir(def_id) {
|
||||
return extract_hir_info(tcx, tcx.local_parent(def_id));
|
||||
}
|
||||
|
||||
let hir_node = tcx.hir_node_by_def_id(def_id);
|
||||
let fn_body_id = hir_node.body_id().expect("HIR node is a function with body");
|
||||
let hir_body = tcx.hir().body(fn_body_id);
|
||||
|
56
tests/coverage/async_closure.cov-map
Normal file
56
tests/coverage/async_closure.cov-map
Normal file
@ -0,0 +1,56 @@
|
||||
Function name: async_closure::call_once::<async_closure::main::{closure#0}>
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44)
|
||||
Highest counter ID seen: c0
|
||||
|
||||
Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0}
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 2
|
||||
- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14)
|
||||
- Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2)
|
||||
Highest counter ID seen: c1
|
||||
|
||||
Function name: async_closure::main
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 01, 01, 16, 01, 02, 05, 02, 02]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 2
|
||||
- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 22)
|
||||
- Code(Counter(0)) at (prev + 2, 5) to (start + 2, 2)
|
||||
Highest counter ID seen: c0
|
||||
|
||||
Function name: async_closure::main::{closure#0}
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 23, 00, 24]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 12, 35) to (start + 0, 36)
|
||||
Highest counter ID seen: c0
|
||||
|
||||
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 22, 00, 24]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 12, 34) to (start + 0, 36)
|
||||
Highest counter ID seen: c0
|
||||
|
||||
Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 23, 00, 24]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 12, 35) to (start + 0, 36)
|
||||
Highest counter ID seen: c0
|
||||
|
24
tests/coverage/async_closure.coverage
Normal file
24
tests/coverage/async_closure.coverage
Normal file
@ -0,0 +1,24 @@
|
||||
LL| |#![feature(async_closure)]
|
||||
LL| |//@ edition: 2021
|
||||
LL| |
|
||||
LL| |//@ aux-build: executor.rs
|
||||
LL| |extern crate executor;
|
||||
LL| |
|
||||
LL| 1|async fn call_once(f: impl async FnOnce()) {
|
||||
LL| 1| f().await;
|
||||
LL| 1|}
|
||||
LL| |
|
||||
LL| 1|pub fn main() {
|
||||
LL| 2| let async_closure = async || {};
|
||||
^1
|
||||
------------------
|
||||
| async_closure::main::{closure#0}:
|
||||
| LL| 1| let async_closure = async || {};
|
||||
------------------
|
||||
| async_closure::main::{closure#0}::{closure#1}::<i32>:
|
||||
| LL| 1| let async_closure = async || {};
|
||||
------------------
|
||||
LL| 1| executor::block_on(async_closure());
|
||||
LL| 1| executor::block_on(call_once(async_closure));
|
||||
LL| 1|}
|
||||
|
15
tests/coverage/async_closure.rs
Normal file
15
tests/coverage/async_closure.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#![feature(async_closure)]
|
||||
//@ edition: 2021
|
||||
|
||||
//@ aux-build: executor.rs
|
||||
extern crate executor;
|
||||
|
||||
async fn call_once(f: impl async FnOnce()) {
|
||||
f().await;
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let async_closure = async || {};
|
||||
executor::block_on(async_closure());
|
||||
executor::block_on(call_once(async_closure));
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
//@ known-bug: #131190
|
||||
//@ compile-flags: -Cinstrument-coverage --edition=2018
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
pub fn block_on<T>(fut: impl Future<Output = T>) -> T {}
|
||||
|
||||
async fn call_once(f: impl async FnOnce(DropMe)) {
|
||||
f(DropMe("world")).await;
|
||||
}
|
||||
|
||||
struct DropMe(&'static str);
|
||||
|
||||
pub fn main() {
|
||||
block_on(async {
|
||||
let async_closure = async move |a: DropMe| {};
|
||||
call_once(async_closure).await;
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user