Skip to content

coverage: Run-make regression test for #[derive(arbitrary::Arbitrary)] #144571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Zalathar
Copy link
Contributor

@Zalathar Zalathar commented Jul 28, 2025

This is a regression test for #141577 (comment), which resulted in llvm-cov producing the cryptic error message:

malformed instrumentation profile data: function name is empty

The repro we have is triggered by #[derive(arbitrary::Arbitrary)], and is difficult to minimize beyond that point. So instead of a coverage test, this PR adds a run-make test that builds against the real arbitrary crate, and then runs llvm-cov to verify that it doesn't crash.


I have manually verified that this would have caught the regression introduced by #144298.

r? compiler

@Zalathar Zalathar added the A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) label Jul 28, 2025
@rustbot rustbot added A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 28, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jul 28, 2025

This PR modifies run-make tests.

cc @jieyouxu

The run-make-support library was changed

cc @jieyouxu

@Zalathar
Copy link
Contributor Author

Ah, this will probably want needs-profiler-runtime.

@lqd
Copy link
Member

lqd commented Jul 28, 2025

It's quite uncommon to have tests with external dependencies. Is this only because it's still difficult to minimize? If so, I will minimize it.

Comment on lines +8 to +9
[dependencies]
arbitrary = { version = "1.4.1", features = ["derive"] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remark: this is subject to the same consideration as #128733. Maybe at least pin this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering how the other run-make cargo tests deal with these concerns, but I guess the answer is that they don't. 😱

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, unfortunately...

@folkertdev
Copy link
Contributor

can't you run cargo expand on the input file to just expand the derive macro? Then the dependency is no longer needed.

@rust-log-analyzer

This comment has been minimized.

@Zalathar
Copy link
Contributor Author

can't you run cargo expand on the input file to just expand the derive macro? Then the dependency is no longer needed.

cargo expand doesn't preserve the authentic macro-expansion span hierarchy, which is a key part of what triggers the issue.

The expanded code would become plain Rust code, which would almost certainly not reproduce the problem.

@Zalathar
Copy link
Contributor Author

Zalathar commented Jul 28, 2025

It's quite uncommon to have tests with external dependencies. Is this only because it's still difficult to minimize? If so, I will minimize it.

Partly because it's difficult to minimize, and partly because I fear that a smaller repro would not actually be a very useful regression test if it ends up being overfitted to quirks of the current implementation.

The (coverage) test suite currently has approximately no coverage of real-world proc-macro usage, which is very often what encounters these obscure regressions. And it's not possible to capture real-world usage without dependencies like syn and quote.

I mainly wrote this test because #144530 (comment) made me worried about not being able to re-land #144298 without a test.

@lqd
Copy link
Member

lqd commented Jul 28, 2025

I fear that a smaller repro would not actually be a very useful regression test if it ends up being overfitted to quirks of the current implementation

That's the usual problem with all regression tests, and it's absolutely fine. We can't predict future changes and issues, so we try to prevent known ones. If it they reappear under slightly different conditions so be it, we'll fix that different issue. It happens all the time, and it's all good.

I mainly wrote this test because I didn't want #144530 (comment) threatening to hold up all future coverage work

We have tests for all issues where we can, that's unrelated to any future coverage work which I'm actually excited to see land sooner rather than later. That is why I r+ed the PR and didn't consider the lack of test blocking.

Big thanks for removing the annoying fuzzing setup in the original repro. I will make you a minimization ASAP.

@Zalathar
Copy link
Contributor Author

It's quite uncommon to have tests with external dependencies. Is this only because it's still difficult to minimize? If so, I will minimize it.

Here's another tip that could help with minimization: after reapplying #144298, go to the bottom of fn coverage_ids_info, and assert !phys_counter_for_node.is_empty().

That will cause the buggy case to ICE the compiler, instead of having to do the extra steps with llvm-profdata and llvm-cov to see whether llvm-cov fails or not.

(Of course, it would be wise to verify the MCVE against llvm-cov to make sure it still reproduces the issue properly.)

@Zalathar
Copy link
Contributor Author

@rustbot blocked

Waiting for an MCVE that could make this PR mostly obsolete.

@rustbot rustbot added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 28, 2025
@lqd
Copy link
Member

lqd commented Jul 28, 2025

proc macro:

#[proc_macro_derive(Arbitrary, attributes(arbitrary))]
pub fn derive_arbitrary(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
   "impl Arbitrary for MyEnum {
        fn try_size_hint() -> Option<usize> {
            Some(0)?;
            None
        }
    }".parse().unwrap()
}

repro:

#[derive(derive_dependency::Arbitrary)]
enum MyEnum {}

fn main() {
    MyEnum::try_size_hint();
}

trait Arbitrary {
    fn try_size_hint() -> Option<usize>;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) A-run-make Area: port run-make Makefiles to rmake.rs S-blocked Status: Blocked on something else such as an RFC or other implementation work. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants