-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
-Z instrument-coverage
shows missing coverage for unbraced closures invoking only a macro
#84884
Comments
I suspect the problem is related to how the expansion is handled for the macro body. When defined without braces, it is (likely) "de-sugared" (adding braces perhaps?) in a way that confuses the macro expansion handling in |
@rustbot +A-code-coverage fyi: @tmandry @wesleywiser |
I looked into this (reviewing debug logs) and the issue it not exactly a macro problem, I think. The closure tests I used all call macro_rules! println {
() => ($crate::print!("\n"));
($($arg:tt)*) => ({
$crate::io::_print($crate::format_args_nl!($($arg)*));
})
} Note the expansion starts with
Since the opening brace comes from the macro, the closure MIR body source starts within the macro. Generating the coverage relative to the source that contains the first character of the function body is generally reasonable, and even in this case it might be hard to argue that it's wrong. But it's probably not right either. The issue is, where should coverage be generated? If the macro is more complex, instrumenting the macro is good. If the caller (which could be another macro, by the way) is more complex, instrumenting the caller source is often better. For example, intuitively we want the coverage results of the two macros below to look similar. Putting the coverage results in the source for the
I'm not exactly sure what to do. I'm thinking of treating closures (at least closures that start with a macro) as a special case (at least, when coverage is enabled), and find some way of handling the body span as if it included its own block braces. |
…mandry Coverage instruments closure bodies in macros (not the macro body) Fixes: rust-lang#84884 This solution might be considered a compromise, but I think it is the better choice. The results in the `closure.rs` test correctly resolve all test cases broken as described in rust-lang#84884. One test pattern (in both `closure_macro.rs` and `closure_macro_async.rs`) was also affected, and removes coverage statistics for the lines inside the closure, because the closure includes a macro. (The coverage remains at the callsite of the macro, so we lose some detail, but there isn't a perfect choice with macros. Often macro implementations are split across the macro and the callsite, and there doesn't appear to be a single "right choice" for which body should be covered. For the current implementation, we can't do both. The callsite is most likely to be the preferred site for coverage. r? `@tmandry` cc: `@wesleywiser`
I expect something that looks like the result, for a similar (non-macro) closure:
But instead we get results like the following:
This issue is demonstrated in the coverage results from the test: https://github.com/rust-lang/rust/blob/031c756d16290f3f8ed25a64126ff82cca17123d/src/test/run-make/coverage/closure.rs#L136
I have a new PR in progress to show more examples, and those examples expose the fact that the coverage for
println!(...)
is actually being added to the macro's source itself.Note that there were 5
println!(...)
macro calls with missing coverage in the corresponding test case, and the coverage report shows 5Unexecuted instantiations
. So all are taken into account.Nevertheless, this is a function-like macro, and it should behave like a function call, and show the coverage at the calling site.
The text was updated successfully, but these errors were encountered: