Description
Alternative title: Multiple simultaneous overlapping mutable borrows.
I shouldn't find an existing issue on this, and it doesn't seem to me like a code error - at least, nothing in the documentation suggested to me that this was expected. At the very least, the error message is unclear if it is expected.
MRE:
struct Test<'a, T : 'a> {
contents : &'a mut T,
function : &'a fn(&'a mut T) -> ()
}
impl<'a, T : 'a> Test<'a, T> {
fn do_thing(self) {
let v : Vec<()> = vec![];
for item in v.iter() {
match (self.function)(self.contents) {
() => {}
}
}
}
}
Expectation:
This would compile. The mutable borrows don't overlap.
What happens:
rustc
complains that self.contents
is mutably borrowed twice at the same position.
error[E0499]: cannot borrow `*self.contents` as mutable more than once at a time
|
28 | match (self.function)(self.contents) {
| ^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first mutable borrow occurs here
...
32 | }
| - first borrow ends here
This is the only compiler error in the program. Any fixes to this error will cause the entire thing to compile successfully.
From testing, things that will prevent this:
- Removing the outside vec iterator
- Using a named external function with the same signature instead of a function from a field of
Test
.
Things that will not prevent this:
-
Using a function
impl
'd on a field ofTest
- e.g.struct FunctionWrapper<'a, T : 'a> { inner_func : ... } impl<a, T : 'a> FunctionWrapper<'a, T> { fn call(&self, arg : &'a mut T) { (self.inner_func)(arg) } } struct Test<'a, T : 'a> { function : FunctionWrapper<...> }
This is true even if you're not calling a stored function - a stored function was just the simplest example I could think of.
-
Passing in the value which is the argument of the function.
fn do_thing(self, other : &'a mut T)
will still complain of a double borrow at the same position ofother
Meta
Tested on
- rustc 1.19.0 (stable)
- rustc 1.20.0-nightly