Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does rust consider borrows active in other branches

It appears the borrow checker considers other branches to hold borrows. For example

fn f(v: &mut Vec<i32>, a: bool) -> &i32 {
    match &v[0] {
        _ if a => {
            f(v, !a);
            &v[0]
        }
        x => {
            x
        }
    }
}

will not compile.

See it in the Rust Playground.

The error is:

error[E0502]: cannot borrow `*v` as mutable because it is also borrowed as immutable
 --> src/lib.rs:4:13
  |
1 | fn f(v: &mut Vec<i32>, a: bool) -> &i32 {
  |         - let's call the lifetime of this reference `'1`
2 |     match &v[0] {
  |            - immutable borrow occurs here
3 |         _ if a => {
4 |             f(v, !a);
  |             ^^^^^^^^ mutable borrow occurs here
...
8 |             x
  |             - returning this value requires that `*v` is borrowed for `'1`

Why does it do this and how do I get around it?

like image 832
The Acorn Avatar asked Apr 18 '26 16:04

The Acorn


1 Answers

I think this is a limitation of the current borrow checker and the new one Polonius will accept this.

Getting around this is usually done by re-arranging some control flow logic or by not using a reference in the match (cloning it or dereferencing copy types).

In the example, this is how you get around it:

fn f(v: &mut Vec<i32>, a: bool) -> &i32 {
    if a {
        f(v, !a);
    }
    &v[0]
}

or by using the fact that i32 is Copy:

fn f(v: &mut Vec<i32>, a: bool) -> &i32 {
    match v[0] {
        _ if a => {
            f(v, !a);
            &v[0]
        }
        _ => &v[0],
    }
}

For the example, the second method doesn't make too much sense but maybe for your use case doing this is easier/nicer.

like image 54
Hadus Avatar answered Apr 21 '26 12:04

Hadus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!