# False edges in `match` MIR lowering
I'm trying to understand them.
## Code and docs
[Comments says](https://github.com/rust-lang/rust/blob/3521a2f2f317cb978063842485c7d1bc86ec82b6/compiler/rustc_mir_build/src/build/matches/mod.rs?plain=1#L204-L211):
> ## False edges
>
> We don't want to have the exact structure of the decision tree be
> visible through borrow checking. False edges ensure that the CFG as
> seen by borrow checking doesn't encode this. False edges are added:
>
> * From each pre-binding block to the next pre-binding block.
> * From each otherwise block to the next pre-binding block.
The first case is set up [here](https://github.com/rust-lang/rust/blob/3521a2f2f317cb978063842485c7d1bc86ec82b6/compiler/rustc_mir_build/src/build/matches/mod.rs?plain=1#L1961-L1970), the second [here](https://github.com/rust-lang/rust/blob/3521a2f2f317cb978063842485c7d1bc86ec82b6/compiler/rustc_mir_build/src/build/matches/mod.rs?plain=1#L2114-L2119).
I couldn't find more explanation than that so I tried commenting out and looking at tests.
## Tests
From looking at the tests, the overall idea is to make borrowck think that we're trying each arm in order despite the fact that we're often more clever than that. Also that any guard may of may not be run.
In each case, the error mentioned disappears when I disable false edges.
### The pre-binding-to-pre-binding false edges
Originally added in https://github.com/rust-lang/rust/pull/45200 as "always true guards", now they do more than that.
- From tests/ui/borrowck/or-patterns.rs
```rust
fn or_pattern_moves_all(x: (String, String)) {
match x {
(y, _) | (_, y) => (),
}
&x.1;
//~^ ERROR borrow of moved value
}
```
- From tests/ui/borrowck/borrowck-match-already-borrowed.rs
```rust
fn main() {
let mut x = 1;
let r = &mut x;
let _ = match x {
_ => 0,
y => y + 2, //~ ERROR cannot use `x` because it was mutably borrowed
};
drop(r);
}
```
- From tests/ui/nll/match-cfg-fake-edges.rs
```rust
let x;
// Even though x *is* always initialized, we don't want to have borrowck
// results be based on whether patterns are exhaustive.
match y {
_ if { x = 2; true } => 1,
_ if {
x; //~ ERROR used binding `x` isn't initialized
false
} => 2,
_ => 3,
};
```
- From tests/ui/nll/match-cfg-fake-edges2.rs
```rust
fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
let r = &mut y.1;
// We don't actually test y.1 to select the second arm, but we don't want
// borrowck results to be based on the order we match patterns.
match y { //~ ERROR cannot use `y.1` because it was mutably borrowed
(false, true) => {},
(true, _) => drop(r),
(false, _) => {},
};
}
```
- From tests/ui/nll/match-guards-partially-borrow.rs
```rust
fn bad_indirect_mutation_in_if_guard4(mut b: &bool) {
match b {
&_ => (),
&_ if {
b = &true; //~ ERROR cannot assign `b` in match guard
false
} => (),
}
}
```
### The otherwise-to-pre-binding false edges
- From tests/ui/nll/match-cfg-fake-edges.rs
```rust
let x = String::new();
// Even though x *is* never moved before the use, we don't want to have
// borrowck results be based on whether patterns are disjoint.
match y {
false if { drop(x); true } => {},
true => drop(x), //~ ERROR use of moved value: `x`
false => {},
};
```
```rust
fn do_guards_in_order() {
// Like the previous case, making really sure we respect the order.
let [a, b, c, d]: [String; 4] = Default::default();
match true {
false if { drop(a); true } => {},
true if { drop(b); true } => drop(a),
//~^ ERROR use of moved value: `a`
false if { drop(c); true } => drop(b),
//~^ ERROR use of moved value: `b`
true => drop(c),
//~^ ERROR use of moved value: `c`
_ => {},
};
let [a, b, c, d]: [String; 4] = Default::default();
match true {
true => drop(c),
false if { drop(c); true } => drop(b),
true if { drop(b); true } => drop(a),
false if { drop(a); true } => {},
_ => {},
};
}
```