about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2025-07-29 10:29:32 +1000
committerZalathar <Zalathar@users.noreply.github.com>2025-07-29 11:36:43 +1000
commit7ca4d1f6a155e802b31cfc1f0971f3916aa8e02d (patch)
tree25b249c19d65744537e4f3186edda5948cd7aaa7
parent498ae9fed2e7d90821d70a048f3770f91af08957 (diff)
downloadrust-7ca4d1f6a155e802b31cfc1f0971f3916aa8e02d.tar.gz
rust-7ca4d1f6a155e802b31cfc1f0971f3916aa8e02d.zip
coverage: Regression test for "function name is empty" bug
The bug was triggered by a particular usage of the `?` try operator in a
proc-macro expansion.

Thanks to lqd for the minimization.

Co-authored-by: Rémy Rakic <remy.rakic+github@gmail.com>
-rw-r--r--tests/coverage/auxiliary/try_in_macro_helper.rs31
-rw-r--r--tests/coverage/try-in-macro.attr.cov-map20
-rw-r--r--tests/coverage/try-in-macro.attr.coverage44
-rw-r--r--tests/coverage/try-in-macro.bang.cov-map20
-rw-r--r--tests/coverage/try-in-macro.bang.coverage44
-rw-r--r--tests/coverage/try-in-macro.derive.cov-map20
-rw-r--r--tests/coverage/try-in-macro.derive.coverage44
-rw-r--r--tests/coverage/try-in-macro.rs43
8 files changed, 266 insertions, 0 deletions
diff --git a/tests/coverage/auxiliary/try_in_macro_helper.rs b/tests/coverage/auxiliary/try_in_macro_helper.rs
new file mode 100644
index 00000000000..27d2af15b05
--- /dev/null
+++ b/tests/coverage/auxiliary/try_in_macro_helper.rs
@@ -0,0 +1,31 @@
+//@ edition: 2024
+// (The proc-macro crate doesn't need to be instrumented.)
+//@ compile-flags: -Cinstrument-coverage=off
+
+use proc_macro::TokenStream;
+
+/// Minimized form of `#[derive(arbitrary::Arbitrary)]` that still triggers
+/// the original bug.
+const CODE: &str = "
+    impl Arbitrary for MyEnum {
+        fn try_size_hint() -> Option<usize> {
+            Some(0)?;
+            None
+        }
+    }
+";
+
+#[proc_macro_attribute]
+pub fn attr(_attr: TokenStream, _item: TokenStream) -> TokenStream {
+    CODE.parse().unwrap()
+}
+
+#[proc_macro]
+pub fn bang(_item: TokenStream) -> TokenStream {
+    CODE.parse().unwrap()
+}
+
+#[proc_macro_derive(Arbitrary)]
+pub fn derive_arbitrary(_item: TokenStream) -> TokenStream {
+    CODE.parse().unwrap()
+}
diff --git a/tests/coverage/try-in-macro.attr.cov-map b/tests/coverage/try-in-macro.attr.cov-map
new file mode 100644
index 00000000000..7111e89637c
--- /dev/null
+++ b/tests/coverage/try-in-macro.attr.cov-map
@@ -0,0 +1,20 @@
+Function name: <try_in_macro::MyEnum as try_in_macro::Arbitrary>::try_size_hint
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 2a, 00, 2b]
+Number of files: 1
+- file 0 => $DIR/try-in-macro.rs
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Zero) at (prev + 30, 42) to (start + 0, 43)
+Highest counter ID seen: (none)
+
+Function name: try_in_macro::main
+Raw bytes (19): 0x[01, 01, 00, 03, 01, 29, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02]
+Number of files: 1
+- file 0 => $DIR/try-in-macro.rs
+Number of expressions: 0
+Number of file 0 mappings: 3
+- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 10)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26)
+- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
+Highest counter ID seen: c0
+
diff --git a/tests/coverage/try-in-macro.attr.coverage b/tests/coverage/try-in-macro.attr.coverage
new file mode 100644
index 00000000000..457a161f3c7
--- /dev/null
+++ b/tests/coverage/try-in-macro.attr.coverage
@@ -0,0 +1,44 @@
+   LL|       |//! Regression test for <https://github.com/rust-lang/rust/issues/141577>.
+   LL|       |//!
+   LL|       |//! The changes in <https://github.com/rust-lang/rust/pull/144298> exposed a
+   LL|       |//! latent bug that would sometimes cause the compiler to emit a covfun record
+   LL|       |//! for a function, but not emit a corresponding PGO symbol name entry, because
+   LL|       |//! the function did not have any physical coverage counters. The `llvm-cov`
+   LL|       |//! tool would then fail to resolve the covfun record's function name hash,
+   LL|       |//! and exit with the cryptic error:
+   LL|       |//!
+   LL|       |//! ```text
+   LL|       |//!    malformed instrumentation profile data: function name is empty
+   LL|       |//! ```
+   LL|       |//!
+   LL|       |//! The bug was then triggered in the wild by the macro-expansion of
+   LL|       |//! `#[derive(arbitrary::Arbitrary)]`.
+   LL|       |//!
+   LL|       |//! This test uses a minimized form of the `Arbitrary` derive macro that was
+   LL|       |//! found to still trigger the original bug. The bug could also be triggered
+   LL|       |//! by a bang proc-macro or an attribute proc-macro.
+   LL|       |
+   LL|       |//@ edition: 2024
+   LL|       |//@ revisions: attr bang derive
+   LL|       |//@ proc-macro: try_in_macro_helper.rs
+   LL|       |
+   LL|       |trait Arbitrary {
+   LL|       |    fn try_size_hint() -> Option<usize>;
+   LL|       |}
+   LL|       |
+   LL|       |// Expand via an attribute proc-macro.
+   LL|       |#[cfg_attr(attr, try_in_macro_helper::attr)]
+   LL|       |const _: () = ();
+   LL|       |
+   LL|       |// Expand via a regular bang-style proc-macro.
+   LL|       |#[cfg(bang)]
+   LL|       |try_in_macro_helper::bang!();
+   LL|       |
+   LL|       |// Expand via a derive proc-macro.
+   LL|       |#[cfg_attr(derive, derive(try_in_macro_helper::Arbitrary))]
+   LL|       |enum MyEnum {}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    MyEnum::try_size_hint();
+   LL|      1|}
+
diff --git a/tests/coverage/try-in-macro.bang.cov-map b/tests/coverage/try-in-macro.bang.cov-map
new file mode 100644
index 00000000000..80bd91a993c
--- /dev/null
+++ b/tests/coverage/try-in-macro.bang.cov-map
@@ -0,0 +1,20 @@
+Function name: <try_in_macro::MyEnum as try_in_macro::Arbitrary>::try_size_hint
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 23, 1c, 00, 1d]
+Number of files: 1
+- file 0 => $DIR/try-in-macro.rs
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Zero) at (prev + 35, 28) to (start + 0, 29)
+Highest counter ID seen: (none)
+
+Function name: try_in_macro::main
+Raw bytes (19): 0x[01, 01, 00, 03, 01, 29, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02]
+Number of files: 1
+- file 0 => $DIR/try-in-macro.rs
+Number of expressions: 0
+Number of file 0 mappings: 3
+- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 10)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26)
+- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
+Highest counter ID seen: c0
+
diff --git a/tests/coverage/try-in-macro.bang.coverage b/tests/coverage/try-in-macro.bang.coverage
new file mode 100644
index 00000000000..457a161f3c7
--- /dev/null
+++ b/tests/coverage/try-in-macro.bang.coverage
@@ -0,0 +1,44 @@
+   LL|       |//! Regression test for <https://github.com/rust-lang/rust/issues/141577>.
+   LL|       |//!
+   LL|       |//! The changes in <https://github.com/rust-lang/rust/pull/144298> exposed a
+   LL|       |//! latent bug that would sometimes cause the compiler to emit a covfun record
+   LL|       |//! for a function, but not emit a corresponding PGO symbol name entry, because
+   LL|       |//! the function did not have any physical coverage counters. The `llvm-cov`
+   LL|       |//! tool would then fail to resolve the covfun record's function name hash,
+   LL|       |//! and exit with the cryptic error:
+   LL|       |//!
+   LL|       |//! ```text
+   LL|       |//!    malformed instrumentation profile data: function name is empty
+   LL|       |//! ```
+   LL|       |//!
+   LL|       |//! The bug was then triggered in the wild by the macro-expansion of
+   LL|       |//! `#[derive(arbitrary::Arbitrary)]`.
+   LL|       |//!
+   LL|       |//! This test uses a minimized form of the `Arbitrary` derive macro that was
+   LL|       |//! found to still trigger the original bug. The bug could also be triggered
+   LL|       |//! by a bang proc-macro or an attribute proc-macro.
+   LL|       |
+   LL|       |//@ edition: 2024
+   LL|       |//@ revisions: attr bang derive
+   LL|       |//@ proc-macro: try_in_macro_helper.rs
+   LL|       |
+   LL|       |trait Arbitrary {
+   LL|       |    fn try_size_hint() -> Option<usize>;
+   LL|       |}
+   LL|       |
+   LL|       |// Expand via an attribute proc-macro.
+   LL|       |#[cfg_attr(attr, try_in_macro_helper::attr)]
+   LL|       |const _: () = ();
+   LL|       |
+   LL|       |// Expand via a regular bang-style proc-macro.
+   LL|       |#[cfg(bang)]
+   LL|       |try_in_macro_helper::bang!();
+   LL|       |
+   LL|       |// Expand via a derive proc-macro.
+   LL|       |#[cfg_attr(derive, derive(try_in_macro_helper::Arbitrary))]
+   LL|       |enum MyEnum {}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    MyEnum::try_size_hint();
+   LL|      1|}
+
diff --git a/tests/coverage/try-in-macro.derive.cov-map b/tests/coverage/try-in-macro.derive.cov-map
new file mode 100644
index 00000000000..6646b6693ba
--- /dev/null
+++ b/tests/coverage/try-in-macro.derive.cov-map
@@ -0,0 +1,20 @@
+Function name: <try_in_macro::MyEnum as try_in_macro::Arbitrary>::try_size_hint
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 26, 38, 00, 39]
+Number of files: 1
+- file 0 => $DIR/try-in-macro.rs
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Zero) at (prev + 38, 56) to (start + 0, 57)
+Highest counter ID seen: (none)
+
+Function name: try_in_macro::main
+Raw bytes (19): 0x[01, 01, 00, 03, 01, 29, 01, 00, 0a, 01, 01, 05, 00, 1a, 01, 01, 01, 00, 02]
+Number of files: 1
+- file 0 => $DIR/try-in-macro.rs
+Number of expressions: 0
+Number of file 0 mappings: 3
+- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 10)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 26)
+- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
+Highest counter ID seen: c0
+
diff --git a/tests/coverage/try-in-macro.derive.coverage b/tests/coverage/try-in-macro.derive.coverage
new file mode 100644
index 00000000000..457a161f3c7
--- /dev/null
+++ b/tests/coverage/try-in-macro.derive.coverage
@@ -0,0 +1,44 @@
+   LL|       |//! Regression test for <https://github.com/rust-lang/rust/issues/141577>.
+   LL|       |//!
+   LL|       |//! The changes in <https://github.com/rust-lang/rust/pull/144298> exposed a
+   LL|       |//! latent bug that would sometimes cause the compiler to emit a covfun record
+   LL|       |//! for a function, but not emit a corresponding PGO symbol name entry, because
+   LL|       |//! the function did not have any physical coverage counters. The `llvm-cov`
+   LL|       |//! tool would then fail to resolve the covfun record's function name hash,
+   LL|       |//! and exit with the cryptic error:
+   LL|       |//!
+   LL|       |//! ```text
+   LL|       |//!    malformed instrumentation profile data: function name is empty
+   LL|       |//! ```
+   LL|       |//!
+   LL|       |//! The bug was then triggered in the wild by the macro-expansion of
+   LL|       |//! `#[derive(arbitrary::Arbitrary)]`.
+   LL|       |//!
+   LL|       |//! This test uses a minimized form of the `Arbitrary` derive macro that was
+   LL|       |//! found to still trigger the original bug. The bug could also be triggered
+   LL|       |//! by a bang proc-macro or an attribute proc-macro.
+   LL|       |
+   LL|       |//@ edition: 2024
+   LL|       |//@ revisions: attr bang derive
+   LL|       |//@ proc-macro: try_in_macro_helper.rs
+   LL|       |
+   LL|       |trait Arbitrary {
+   LL|       |    fn try_size_hint() -> Option<usize>;
+   LL|       |}
+   LL|       |
+   LL|       |// Expand via an attribute proc-macro.
+   LL|       |#[cfg_attr(attr, try_in_macro_helper::attr)]
+   LL|       |const _: () = ();
+   LL|       |
+   LL|       |// Expand via a regular bang-style proc-macro.
+   LL|       |#[cfg(bang)]
+   LL|       |try_in_macro_helper::bang!();
+   LL|       |
+   LL|       |// Expand via a derive proc-macro.
+   LL|       |#[cfg_attr(derive, derive(try_in_macro_helper::Arbitrary))]
+   LL|       |enum MyEnum {}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    MyEnum::try_size_hint();
+   LL|      1|}
+
diff --git a/tests/coverage/try-in-macro.rs b/tests/coverage/try-in-macro.rs
new file mode 100644
index 00000000000..ab9d6675418
--- /dev/null
+++ b/tests/coverage/try-in-macro.rs
@@ -0,0 +1,43 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/141577>.
+//!
+//! The changes in <https://github.com/rust-lang/rust/pull/144298> exposed a
+//! latent bug that would sometimes cause the compiler to emit a covfun record
+//! for a function, but not emit a corresponding PGO symbol name entry, because
+//! the function did not have any physical coverage counters. The `llvm-cov`
+//! tool would then fail to resolve the covfun record's function name hash,
+//! and exit with the cryptic error:
+//!
+//! ```text
+//!    malformed instrumentation profile data: function name is empty
+//! ```
+//!
+//! The bug was then triggered in the wild by the macro-expansion of
+//! `#[derive(arbitrary::Arbitrary)]`.
+//!
+//! This test uses a minimized form of the `Arbitrary` derive macro that was
+//! found to still trigger the original bug. The bug could also be triggered
+//! by a bang proc-macro or an attribute proc-macro.
+
+//@ edition: 2024
+//@ revisions: attr bang derive
+//@ proc-macro: try_in_macro_helper.rs
+
+trait Arbitrary {
+    fn try_size_hint() -> Option<usize>;
+}
+
+// Expand via an attribute proc-macro.
+#[cfg_attr(attr, try_in_macro_helper::attr)]
+const _: () = ();
+
+// Expand via a regular bang-style proc-macro.
+#[cfg(bang)]
+try_in_macro_helper::bang!();
+
+// Expand via a derive proc-macro.
+#[cfg_attr(derive, derive(try_in_macro_helper::Arbitrary))]
+enum MyEnum {}
+
+fn main() {
+    MyEnum::try_size_hint();
+}