Repository: rust
Issue: Tracking implementation for MC/DC
Labels: T-compiler,C-tracking-issue,A-code-coverage

### Introduction
[Modified condition/decision coverage](https://en.wikipedia.org/wiki/Modified_condition/decision_coverage) (MC/DC) is a code coverage criterion used widely in safety critical software components and is required by standards such as [DO-178B](https://en.wikipedia.org/wiki/DO-178B) and [ISO26262](https://en.wikipedia.org/wiki/ISO_26262).

**Terminology**
*condition*: boolean expressions that have no binary logical operators. For example, `a || b` is not "condition" because it has an or operator while `a==b` is.
*decision*:  longest boolean expressions composed of conditions and binary boolean expressions only.

MC/DC requires each condition in a decision is shown to independently affect the outcome of the decision.
e.g Suppose we have code like
```rust
if (a || b) && c {
    todo!();
}
```
Here `(a || b) && c` is a decision and `a`,`b`,`c` are conditions. 
* If test cases are `(a=true, b=false, c=true)` and `(a=false, b=false, c=true)`, we say `a` can independently affect the decision because the value of decision is changed as `a` changes while keep `b` and `c` unchanged. So that we get 1/3 MC/DC here (1 for `a` and 3 for `a`,`b`,`c`).
* Test cases `(a=false, b=true, c=true)` and `(a=false, b=false, c=false)` also show `b` can independently affect the decision. Though in the later case `c` is also changed but it is short-circuited and has no impacts (thus we can view it as same as `c=true`). While `c` is not acknowledged due to change of `b`.  Plus the two cases before we get 2/3 MC/DC.
* Test cases `(a=true,b=false,c=true)` and `(a=true,b=false,c=false)` show `c` can do the same. By now we get 3/3.

Notice that there are duplicate cases, so test cases collection {`(a=true, b=false, c=true)`,`(a=false, b=false, c=true)`,`(a=false, b=true, c=true)`, `(a=false, b=false, c=false)`,`(a=true,b=false,c=false)`} are sufficient to prove 3/3 MC/DC.
In fact we can use at least n+1 cases to prove 100% MC/DC of decision with n conditions. (In this example, {`(a=true,b=false,c=true)`,`(a=false,b=false,c=true)`,`(a=false,b=true,c=true)`,`(a=true,b=false,c=false)`} are enough)

### Progress
A basic implementation for MC/DC is filed on #123409 , which has some limits. There are still several cases need to handle:

- [x] Support plain boolean expressions like `let val = a || b`.  Done at
#125756 
#125766 
- [ ] Support pattern matching. Ferrous [suggests](https://arxiv.org/abs/2409.08708) that refutable patterns should be considered as decisions, which sounds certainly reasonable as these are considered as branches too.
Draft: #124278 
- [x] Support nested decisions like `if (a || b) || inner_decision(c || d)`. Done at #124255 
- [x] So far only decisions with at most 6 conditions are counted due to resource cost. This limit should be relaxed now that the llvm backend had this  [optimization](https://github.com/llvm/llvm-project/pull/82448).
#126733 

### Known Issues
- Decisions containing constant conditions may result incorrect report, where some non-constant conditions are regarded as constants or vice versa. This issue occurs because the way rustc produces counters for constants is not what llvm expects. It's fixed by [llvm #112694](https://github.com/llvm/llvm-project/pull/112694) and can be solved once rustc upgraded in-tree llvm to 20.
- Some nested decisions may cause panic as [llvm #91600](https://github.com/llvm/llvm-project/pull/91600) described.
- On some occasions rustc may painic with "instrprof failed to lower mcdc parameters", see #129989