-
Notifications
You must be signed in to change notification settings - Fork 12.1k
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
Support mcdc analysis for pattern matching #124278
base: master
Are you sure you want to change the base?
Conversation
r? @wesleywiser rustbot has assigned @wesleywiser. Use |
Failed to set assignee to
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
39732bf
to
0255b0b
Compare
Determining decision of pattern matching is more tricky than expected. I should write it down here in case someone feels confused about it. We call patterns like The first rule is that candidate is constructed where all match pairs representing The second rule is the first pair will be removed and compiler will insert its sub pairs into the candidate's match pairs if it is "full matched" Thus in all, the evaluate order of
While the order of
And the order of
A more mischievous example is
Hopefully the decision structure were not taken as mischief by users. |
This comment has been minimized.
This comment has been minimized.
I have pushed an impractical commit to show design for constructing decisions and mcdc branches of pattern matching. |
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #124255) made this pull request unmergeable. Please resolve the merge conflicts. |
Split mcdc code to a sub module of coverageinfo A further work from rust-lang#124217 . I have made relatively large changes when working on rust-lang#124278 so that it would better split them from `coverageinfo.rs` to avoid potential troubling merge work with improved branch coverage by `@Zalathar` . Besides `BlockMarkerGenerator` is added to avoid ownership problems (mostly needed for following change of rust-lang#124278 ) All code changes are done in [a37d737a](rust-lang@a3d737a) while the second commit just renames the file. cc `@RenjiSann` `@Zalathar` This will impact your current work.
Implementation for if-let has been drafted. Due to llvm does not support nested decisions yet tests for let-chains are not added. I should try to reduce coverage expressions and investigate if it works for matching guards later. |
☔ The latest upstream changes (presumably #124972) made this pull request unmergeable. Please resolve the merge conflicts. |
17b9e82
to
baefce9
Compare
05534ce
to
386f870
Compare
coverage: Memoize and simplify counter expressions When creating coverage counter expressions as part of coverage instrumentation, we often end up creating obviously-redundant expressions like `c1 + (c0 - c1)`, which is equivalent to just `c0`. To avoid doing so, this PR checks when we would create an expression matching one of 5 patterns, and uses the simplified form instead: - `(a - b) + b` → `a`. - `(a + b) - b` → `a`. - `(a + b) - a` → `b`. - `a + (b - a)` → `b`. - `a - (a - b)` → `b`. Of all the different ways to combine 3 operands and 2 operators, these are the patterns that allow simplification. (Some of those patterns currently don't occur in practice, but are included anyway for completeness, to avoid having to add them later as branch coverage and MC/DC coverage support expands.) --- This PR also adds memoization for newly-created (or newly-simplified) counter expressions, to avoid creating duplicates. This currently makes no difference to the final mappings, but is expected to be useful for MC/DC coverage of match expressions, as proposed by rust-lang#124278 (comment).
Rollup merge of rust-lang#125106 - Zalathar:expressions, r=davidtwco coverage: Memoize and simplify counter expressions When creating coverage counter expressions as part of coverage instrumentation, we often end up creating obviously-redundant expressions like `c1 + (c0 - c1)`, which is equivalent to just `c0`. To avoid doing so, this PR checks when we would create an expression matching one of 5 patterns, and uses the simplified form instead: - `(a - b) + b` → `a`. - `(a + b) - b` → `a`. - `(a + b) - a` → `b`. - `a + (b - a)` → `b`. - `a - (a - b)` → `b`. Of all the different ways to combine 3 operands and 2 operators, these are the patterns that allow simplification. (Some of those patterns currently don't occur in practice, but are included anyway for completeness, to avoid having to add them later as branch coverage and MC/DC coverage support expands.) --- This PR also adds memoization for newly-created (or newly-simplified) counter expressions, to avoid creating duplicates. This currently makes no difference to the final mappings, but is expected to be useful for MC/DC coverage of match expressions, as proposed by rust-lang#124278 (comment).
☔ The latest upstream changes (presumably #125331) made this pull request unmergeable. Please resolve the merge conflicts. |
659eede
to
7e0374f
Compare
Thanks to @Nadrieril now I could find a way to treat each arm in The basic idea is to update test vectors of every decision in every arms. For instance, match val {
Pat::A | Pat::B => { /* update test vectors of `Pat::A | Pat::B` and `Pat::C | Pat::D` here */}
Pat::C | Pat::D=> { /* update test vectors of `Pat::A | Pat::B` and `Pat::C | Pat::D` here */}
_ => { /* update test vectors of `Pat::A | Pat::B` and `Pat::C | Pat::D` here */}
} By updating test vectors of all decisions simultaneously we can deal with tests affecting different decisions. Fortunately we have implemented decision depth to such cases. |
normal_branch_spans: Vec<MCDCBranchSpan>, | ||
mcdc_spans: Vec<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)>, | ||
decision_ctx_stack: Vec<DecisionCtx>, | ||
decision_ends: FxIndexMap<Span, Rc<RefCell<Vec<BlockMarkerId>>>>, |
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.
decision_ends
is introduced because:
- Candidates with
|
may not havepre_binding_block
when matching finishes. - For every arm in
match
statements,arm_block
is generated inlower_match_arms
and immediately compiler digs into code in the arm, which might contain many other decisions.
Hence when a PatternDecisionCtx
is finished, we do not know all blocks which are "ends" of these decisions. Instead we fulfill them in add_ends_to_decision
later. Because decisions produced by same ctx
share same ends, Rc<RefCell<_>>
is used here.
coverage: Memoize and simplify counter expressions When creating coverage counter expressions as part of coverage instrumentation, we often end up creating obviously-redundant expressions like `c1 + (c0 - c1)`, which is equivalent to just `c0`. To avoid doing so, this PR checks when we would create an expression matching one of 5 patterns, and uses the simplified form instead: - `(a - b) + b` → `a`. - `(a + b) - b` → `a`. - `(a + b) - a` → `b`. - `a + (b - a)` → `b`. - `a - (a - b)` → `b`. Of all the different ways to combine 3 operands and 2 operators, these are the patterns that allow simplification. (Some of those patterns currently don't occur in practice, but are included anyway for completeness, to avoid having to add them later as branch coverage and MC/DC coverage support expands.) --- This PR also adds memoization for newly-created (or newly-simplified) counter expressions, to avoid creating duplicates. This currently makes no difference to the final mappings, but is expected to be useful for MC/DC coverage of match expressions, as proposed by rust-lang/rust#124278 (comment).
Changed a bit to fit with constant folding. The main goal is to find all |
…anch mappings any more
Upon compiling my projects with "--coverage-options=mcdc", I have found there are still some work to do with pattern matching expanded by macros. I would like to investigate whether we should refactor this implementation for macros. |
To finish the second task at #124144.
Changes
That means,
coverage-options=mcdc
may give different branch coverage results of pattern matching withcoverage-options=branch
temporarily.match
.Note. The results might be a bit counter intuitive due to reorder as this comment introduces.