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: Treat each match arm as a "branch" for branch coverage #124154
base: master
Are you sure you want to change the base?
Conversation
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.
lgtm, the added tests really speak for themselves 🎉
left a small style nit
Some small style updates (diff). |
I noticed that I accidentally included my let-else test as well, but instead of removing it, I decided to just add my if-let test as well. Both of these test show that the respective features don't support branch coverage yet. |
Discard match expressions early if they have <2 arms (diff). |
59c2385
to
356427f
Compare
After investigating some more, I realised that my scheme for making the false-branch expressions isn't accounting for the actual control flow around match guards. For matches with no guards, the false-count for any arm is just the sum of the execution counts of all subsequent arms. But for an arm with a guard, we also need to subtract the number of times that the match succeeded but the guard failed. We're currently failing to do that, which is why we get inflated counts, which then mess up all earlier arms too. |
For now I've updated the implementation to skip any match expressions that have guards, so that at least we aren't producing wrong branch-coverage numbers for them (diff). |
More style updates (diff). |
It looks like the point where we know an arm's pre-binding block and its guard-succeeded block is just after the call to Is there a good way to forward this information to |
☔ The latest upstream changes (presumably #124194) made this pull request unmergeable. Please resolve the merge conflicts. |
d0dfcd8
to
bc042ac
Compare
OK, I think I've figured out guarded arms. My previous attempts were on the right track; I just needed to be very careful with my algebra for computing synthetic counts. |
This comment has been minimized.
This comment has been minimized.
f66890e
to
4be7969
Compare
More assertions when extracting branch arms from MIR (diff). |
Minor tweaks (diff). |
coverage: Prepare for improved branch coverage When trying to rebase my new branch coverage work (including rust-lang#124154) on top of the introduction of MC/DC coverage (rust-lang#123409), I found it a lot harder than anticipated. With the benefit of hindsight, the branch coverage code and MC/DC code have become more interdependent than I'm happy with. This PR therefore disentangles them a bit, so that it will be easier for both areas of code to evolve independently without interference. --- This PR also includes a few extra branch coverage tests that I had sitting around from my current branch coverage work. They mostly just demonstrate that certain language constructs listed in rust-lang#124118 currently don't have branch coverage support. `@rustbot` label +A-code-coverage
coverage: Prepare for improved branch coverage When trying to rebase my new branch coverage work (including rust-lang#124154) on top of the introduction of MC/DC coverage (rust-lang#123409), I found it a lot harder than anticipated. With the benefit of hindsight, the branch coverage code and MC/DC code have become more interdependent than I'm happy with. This PR therefore disentangles them a bit, so that it will be easier for both areas of code to evolve independently without interference. --- This PR also includes a few extra branch coverage tests that I had sitting around from my current branch coverage work. They mostly just demonstrate that certain language constructs listed in rust-lang#124118 currently don't have branch coverage support. ``@rustbot`` label +A-code-coverage
Rollup merge of rust-lang#124217 - Zalathar:pre-branch, r=oli-obk coverage: Prepare for improved branch coverage When trying to rebase my new branch coverage work (including rust-lang#124154) on top of the introduction of MC/DC coverage (rust-lang#123409), I found it a lot harder than anticipated. With the benefit of hindsight, the branch coverage code and MC/DC code have become more interdependent than I'm happy with. This PR therefore disentangles them a bit, so that it will be easier for both areas of code to evolve independently without interference. --- This PR also includes a few extra branch coverage tests that I had sitting around from my current branch coverage work. They mostly just demonstrate that certain language constructs listed in rust-lang#124118 currently don't have branch coverage support. ``@rustbot`` label +A-code-coverage
LL| | | ||
LL| 1|fn never_taken() { | ||
LL| 1| match black_box(false) { | ||
LL| 1| _ if black_box(false) => {} |
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.
I am wondering why the pattern _
and the guard black_box(false)
are in the same code region, while there are 2 branch expressions.
I would have expected the guard to have its own counter displayed underneath
LL| 1| _ if black_box(false) => {}
^1 ^0
There are other simplifications we could potentially be performing, but this one is directly motivated by branch coverage of match arms, because it naturally handles the common case where a match arm has no guard.
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.
☔ The latest upstream changes (presumably #124399) made this pull request unmergeable. Please resolve the merge conflicts. |
This PR adds branch coverage instrumentation for individual arms in
match
expressions.It seems to work well in most cases. However, the current implementation cannot handle match expressions containing or-patterns
|
, and therefore ignores such match expressions entirely.(More specifically, it ignores a match expression if any of its
Candidate
s haspre_binding_block = None
.)Right now I'm not sure whether this should be merged as-is (to provide a useful subset of functionality, and avoid bit-rot), or should be left as a draft until the or-pattern limitation can be lifted (could potentially require major rework).