Repository: rust
Issue: E0502: Borrow checker fails when borrowing with opposite conditions
Labels: A-diagnostics,T-compiler

<!--
The borrow checker complains that I borrow a resource both immutably and mutably within the same (loop) scope. 
However, these borrows are the opposite of an immutable condition. 

I could rewrite the code using tuple destructurization and the borrow checker stops complaining.

This issue is opened to suggest a look into the borrow checker, or simply to provide some documentation on the workaround from rustc.
-->

Given the following code: <!-- Please provide a link to play.rust-lang.org -->

```rust
fn no_compile_main() {
    let mut _buf0 = 12;
    let mut _buf1 = 14;

    for i in 0..5 {
        let last = if i % 2 == 0 {&_buf0} else {&_buf1};
        let this = if i % 2 == 0 {&mut _buf1} else {&mut _buf0};
        *this += 1;
        println!("i: {}, last: {}, this: {}", i, last, this);
    }
}

fn main() {
    let mut _buf0 = 12;
    let mut _buf1 = 14;
    for i in 0..5 {
        let (last, this) =
            if i % 2 == 0 {
                (&_buf0, &mut _buf1)
            } else {
                (&_buf1, &mut _buf0)
            };
        *this += 1;
        println!("i: {}, last: {}, this: {}", i, last, this);
    }
}
```

The current output is:

```
error[[E0502]](https://doc.rust-lang.org/stable/error-index.html#E0502): cannot borrow `_buf1` as mutable because it is also borrowed as immutable
  --> src/main.rs:8:35
   |
7  |         let last = if i % 2 == 0 {&_buf0} else {&_buf1};
   |                                                 ------ immutable borrow occurs here
8  |         let this = if i % 2 == 0 {&mut _buf1} else {&mut _buf0};
   |                                   ^^^^^^^^^^ mutable borrow occurs here
9  |         *this += 1;
10 |         println!("i: {}, last: {}, this: {}", i, last, this);
   |                                                  ---- immutable borrow later used here

error[[E0502]](https://doc.rust-lang.org/stable/error-index.html#E0502): cannot borrow `_buf0` as mutable because it is also borrowed as immutable
  --> src/main.rs:8:53
   |
7  |         let last = if i % 2 == 0 {&_buf0} else {&_buf1};
   |                                   ------ immutable borrow occurs here
8  |         let this = if i % 2 == 0 {&mut _buf1} else {&mut _buf0};
   |                                                     ^^^^^^^^^^ mutable borrow occurs here
9  |         *this += 1;
10 |         println!("i: {}, last: {}, this: {}", i, last, this);
   |                                                  ---- immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
```

<!-- The following is not always necessary. -->
Ideally the output should look like:

```
...
If the mutable/immutable borrows are under the opposite condition, restructure the code using tuple destructuring:
let mut a = if cond {&mut _a} else {&mut _b};
let b = if cond {& _b} else {& a};

into
let (mut a, b) = if cond { (&mut _a, &_b) } else { (&mut _b, &a) };
```

<!--
If the problem is not self-explanatory, please provide a rationale for the
change.
-->

<!--
If dramatically different output is caused by small changes, consider also
adding them here.

If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions. The output might also be
different depending on the Edition.
-->
 
The problem still exists in the beta and nightly versions.
[Illustrated code in Godbolt for different versions](https://rust.godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DEArgoKkl9ZATwDKjdAGFUtEywYgATKUcAZPAZMADl3ACNMYm8AdlIAB1QFQjsGFzcPb3jE5IEAoNCWCKivWKtMGxShAiZiAjT3Ty5LTGtbASqagjyQ8Mi9c076jKaB2u6CookASktUE2Jkdg4AUg0AQSoGAGoGVAB9NBY4ukw9liZAiCmt5eiAIVW1reet%2BgItlhN3vbCTKg0bgBmAAiWy4XmWgIe6xer0w70%2B31%2BVC4QNBUkh0LWj1h/GIWzwBO2GgAdCSAKw3e442EvN6vJjmNEEqgEm5eSleNGQ0EA24PLwANh%2Bfw0t1BLSUVIFwuRXHFmJptLh7wICDwCmZeFZhOWHK2XJ5PK2fOpQsRWxFKPFW0lmGlesFFqtYuiwMVMOVWwAVGqNeyHiCwR6nl64sRAgRaAwwJA9V4KA63aQGeYQEngSm/Qp0/yFV4fASUwZzFn1QopiHYQr1jXsetNh8Lgwrg7Pc96c7kXyg%2BCq3T4R8vpa5cyMVClVs8WzAiayZS8%2B3afSICWLFts9cjUuvSy2XrOdyg6asbvdxBHS6U46u38uJWd16bXa26Gz7SL0KrU12U7hy6HzfM8FQnR9nl9csA2NeVQKA2Fw0jaNY0/BNc2pZNUwINCHgw7NsPzQs8GLRl103ftnjrcUOBmWhOHJXhPA4LRSFQTgACUzHeBQ5gWe09UBHhSCwpjqJmABrEBJEkElBQADlkwUpLkhSlIU/ROEkBjNF4ViOF4HMNCE7SZjgWAkEOY56DICgIAsk4ogYPBgAQKMAE8%2BDoAhIhzCAwm00gwkCGpXP8w42EEAB5BhaBCkTSCwc4jHEOL8GIcpbAAN0wHM4swVRyi%2BJZmMjFp/NoPAwmIYKXCwfyCAjFhOB4GYqAMYAFAANTwTAAHcIriRgmt4fhBBEMR2CkGRBEUFR1Di3QmgMIwQFMUtyrCHNIBmVA4jaBgcv0lp0pSBwGGcVwGj0fxAh6Qo%2BiaBIkj2oZGiyJ6UnGXoohGI6Knaapahe/pfr2joxhuiZ7ssAG6gu4Zoc6T67u%2BmZuPmRY9HqzAlma9SOHo0hGOY3TVoIZAdiclyYq2CAONLLZcEIEh2QElMXCOeyWfvXhhK0KZxO8LgSQATmiWSNC8LhRfFyXhdkvHNMJ/zdP0kBDN56jSFMxAQDmAg4i%2BchKDsqzglYJZSfJoXBSF5jMHwIgI3QPQRuEURxEm12ZrUfyFtIHqqriIaaLorS4t0iKvgN95UFZS2KectyafZyzIi5qYeeMgXAUBEkc/zgvC4VsPic4VX1azvGvBLnSy6MkT%2BdILLiCSexJCAA%3D%3D%3D)