I have a struct and method like this:
pub struct S {
a: Vec<u32>,
b: Vec<u32>,
}
impl S {
// Pretend that this function has a similar signature but an
// implementation that is much more complicated and verbose
fn b_index_mut(&mut self, i: usize) -> &mut u32 {
&mut self.b[i]
}
pub fn foo(&mut self) {
for (i, x) in self.a.iter_mut().enumerate() {
*self.b_index_mut(i) += *x;
}
}
}
S.foo()
will not compile:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src\main.rs:15:14
|
14 | for (i, x) in self.a.iter_mut().enumerate() {
| ------ first mutable borrow occurs here
15 | *self.b_index_mut(i) += *x;
| ^^^^ second mutable borrow occurs here
16 | }
| - first borrow ends here
There is this possible implementation which eliminates this error by simply moving the body of S.b_index_mut()
into S.foo()
:
impl S {
pub fn foo(&mut self) {
for (i, x) in self.a.iter_mut().enumerate() {
self.b[i] += *x;
}
}
}
However, as I said in the comment in the first implementation, the real S.b_index_mut()
that I have in mind is much more verbose that the example, and it is really something that should have its own function.
A possible work around is to pass b
as an argument to S.b_index_mut()
:
impl S {
// Pretend that this function has a similar signature but an
// implementation that is much more complicated and verbose
fn b_index_mut(b: &mut Vec<u32>, i: usize) -> &mut u32 {
&mut b[i]
}
pub fn foo(&mut self) {
for (i, x) in self.a.iter_mut().enumerate() {
*S::b_index_mut(&mut self.b, i) += *x;
}
}
}
This solution compiles and solves the abstraction problem. However, it seems inelegant. Something feels wrong to me about calling a struct function that doesn't take self
for anything other than a constructor.
If the real version of S.b_index_mut()
requires factoring in more members of S
(that are not a
), just writing the function call itself can become quite verbose.
Is there an elegant solution to this problem?