-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
coverage: Support match statements in branch coverage #130744
base: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
@rustbot label +A-code-coverage |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1fad5de
to
3af90ae
Compare
This comment has been minimized.
This comment has been minimized.
Within the `InstrumentCoverage` pass, we now represent branches as a list of arms, instead of a true/false pair, until we prepare the final table of mappings to be attached to the MIR body. (We then flatten the list into two-way branches by treating each arm as a branch between its success block, and the total of all later arms.) Currently all of the branches produced by MIR building are still two-way, but this is a step towards allowing many-way branches.
…e is not also enabled
3af90ae
to
5ccfda9
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
0c434e8
to
0fab23d
Compare
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred in coverage instrumentation. cc @Zalathar Some changes occurred in match lowering cc @Nadrieril Some changes occurred in coverage instrumentation. cc @Zalathar Some changes occurred in coverage instrumentation. cc @Zalathar Some changes occurred in coverage instrumentation. cc @Zalathar Some changes occurred in coverage tests. cc @Zalathar |
Note: There is still a bug with nested or-patterns + match guards being used together. ie. Branch coverage does not appear to work correctly on this code: let a = 1;
let b = 2;
match black_box((a, b)) {
(1, 2 | 3) | (2, 4) if b > 1 => {}
_ => {}
} tbh, I am not super sure what the correct behavior for coverage for nested or-patterns. |
@@ -1840,7 +1871,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | |||
}); | |||
for candidate in candidates_to_expand.iter_mut() { | |||
if !candidate.subcandidates.is_empty() { | |||
self.merge_trivial_subcandidates(candidate); | |||
// FIXME: Support merging trival candidates in branch coverage instrumentation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that turning on branch coverage can cause exponential blowups in MIR size, this is unfortunate. Are you sure tracking or-patterns is worth it? (I'm not expert here, just curious)
Fair warning that it may take me a while to get around to properly looking at this. (I also have some general concerns about expanding branch coverage with the rest of the coverage code in its present state, though I haven't looked at this PR closely enough to know whether those concerns apply here.) |
No worries, and yeah I was also not in love with the implementation 😅 After opening this PR, I am starting question what the correct behavior is. I think an argument can be made that a pattern should be considered a single branch. (Either it matches or it doesn't) But on the other hand I can see value in knowing if the rhs of an or-pattern was never matched. |
I'd say if you want to be sure all the parts of your pattern are useful, you can use MC/DC (when we manage to implement it) |
Thats true, I am starting to lean towards patterns being considered a single branch in branch coverage. |
☔ The latest upstream changes (presumably #131345) made this pull request unmergeable. Please resolve the merge conflicts. |
Is there actually a (Pre-) RFC for the whole branch coverage feature, just to understand the expected and defined behavior better? I'm asking because I found this issue taiki-e/cargo-llvm-cov#394 that indeed shows an interesting corner case for branch coverage and generics where it's a bit unintuitive what is the right thing to expect to see. |
I did a search for "coverage" in the rust-lang/rfcs repo and found very little about coverage. (and nothing about branch coverage) After a bit of searching, the origin of the branch coverage feature was merged in #122322 . |
Hi @Zalathar, just a friendly ping from the compiler team triage meeting in case this fell off your todo list 🙂 |
Hi, so the reason I've put my own branch coverage efforts on hold is that I'm pursuing deeper changes to the architecture of coverage instrumentation, to undo some old design decisions that are now causing difficulties. For that reason, I want to avoid new/expanded features that would make those deep changes harder, since they're hard enough already. And adding branch coverage support for match expressions now would indeed introduce significant obstacles. (I also have similar concerns about the necessary changes to MIR building, since that code is also quite tricky already, and could use some delicate improvements that would be made harder by adding more coverage-related code.) |
This PR builds on the work original done in #124154. (Also see #124118)
In addition, to supporting match arms this PR also attempts to support or-patterns in match patterns by tracking subbranches.
The current implementation handles the basics but nested or-patterns+match guards still have some issues. I figured I would open a PR with what I have so far to get feedback and to see if I am even headed in the right direction.
r? Zalathar
This is my first non-trivial PR for the compiler so apologies if I am doing something wildly incorrect.