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:
许杰友 Jieyou Xu (Joe) 2024-10-18 12:00:51 +01:00 committed by GitHub
commit aae4730c78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 102 additions and 19 deletions

View File

@ -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

View File

@ -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));

View File

@ -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);

View 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

View 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|}

View 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));
}

View File

@ -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;
});
}