Reputation: 33
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?
Upvotes: 3
Views: 393
Reputation: 1664
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.
Upvotes: 4