You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 of Test - 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 of other
Meta
Tested on
rustc 1.19.0 (stable)
rustc 1.20.0-nightly
The text was updated successfully, but these errors were encountered:
The problem is in the declaration fn(&'a mut T) -- you're giving the function a reference for the full lifetime 'a, and since &mut is invariant this can't be reduced to borrow only during one loop iteration. It compiles if you change this to function: &'a fn(&mut T) -> (), which uses an anonymous lifetime akin to a HRTB like function: &'a for<'b> fn(&'b mut T) -> ().
Thanks for the answer! Good to know it's not actually a bug, and the explanation does make sense. I'll see about making a PR to adjust the error message slightly if the mut borrow is happening at the same place twice - that was probably the most confusing part of all this.
Extended error message for mut borrow conflicts in loops
RFC issue: rust-lang/rfcs#2080
The error message for multiple mutable borrows on the same value over loop iterations now makes it clear that the conflict comes from the borrow outlasting the loop. The wording of the error is based on the special case of the moved-value error for a value moved in a loop. Following the example of that error, the code remains the same for the special case.
This is mainly because I felt the current message is confusing in the loop case : #43437. It's not clear that the two conflicting borrows are in different iterations of the loop, and instead it just looks like the compiler has an issue with a single line.
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:
Expectation:
This would compile. The mutable borrows don't overlap.
What happens:
rustc
complains thatself.contents
is mutably borrowed twice at the same position.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:
Test
.Things that will not prevent this:
Using a function
impl
'd on a field ofTest
- e.g.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
The text was updated successfully, but these errors were encountered: