about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-10-16 16:09:41 -0400
committerZalathar <Zalathar@users.noreply.github.com>2024-10-18 20:14:02 +1100
commitcdbf28af7694e0037d2ed8f78c40f60e5aef6de2 (patch)
treefbe1b240f4a6386c71c9abcf8c443761b6c33f6e
parente7c0d2750726c1f08b1de6956248ec78c4a97af6 (diff)
downloadrust-cdbf28af7694e0037d2ed8f78c40f60e5aef6de2.tar.gz
rust-cdbf28af7694e0037d2ed8f78c40f60e5aef6de2.zip
Dont ICE when computing coverage of synthetic async closure body
-rw-r--r--compiler/rustc_middle/src/query/mod.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs5
-rw-r--r--tests/coverage/async_closure.cov-map56
-rw-r--r--tests/coverage/async_closure.coverage24
-rw-r--r--tests/coverage/async_closure.rs15
-rw-r--r--tests/crashes/131190.rs19
7 files changed, 102 insertions, 19 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f0be70e00df..97fc347d482 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -569,6 +569,7 @@ rustc_queries! {
     /// 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
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index cc4b7689d40..2c622b1927e 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -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));
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index d0f30314e79..2e4c503f3ce 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -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);
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
new file mode 100644
index 00000000000..4d00f0d9b33
--- /dev/null
+++ b/tests/coverage/async_closure.cov-map
@@ -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
+
diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage
new file mode 100644
index 00000000000..fd6edf7c29e
--- /dev/null
+++ b/tests/coverage/async_closure.coverage
@@ -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|}
+
diff --git a/tests/coverage/async_closure.rs b/tests/coverage/async_closure.rs
new file mode 100644
index 00000000000..c076d03eef4
--- /dev/null
+++ b/tests/coverage/async_closure.rs
@@ -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));
+}
diff --git a/tests/crashes/131190.rs b/tests/crashes/131190.rs
deleted file mode 100644
index 3a0e64c69d5..00000000000
--- a/tests/crashes/131190.rs
+++ /dev/null
@@ -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;
-    });
-}