This question is not about why the compiler gives these errors — I think I understand that. This question is about how to manage the situation on the mutable path while hoping to be able to call other functions.
This is a simplification of what I am trying to do. I have a lot of Foo
s inside World
and I need to update them based on other data from World
. I have several private functions inside World
that I would like to be able to call.
pub struct Foo {
id: i32,
//...
}
pub struct Bar {
//...
}
pub struct World {
foos: Vec<Foo>,
bars: Vec<Bar>,
//...
}
impl World {
pub fn create() -> World {
World {
foos: Vec::new(),
bars: Vec::new(),
}
}
pub fn update(&mut self) {
for foo in self.get_foos_mut() {
//error[E0XXX]: cannot borrow `*self` as mutable/imutable ...
let _bar = self.get_bar_given_foo(foo);
//alter foo based on bar and other world things calling other world functions...
//...
}
}
//some useful utility functions that should be called several times
//from different World places...
fn get_foos_mut(&mut self) -> &mut [Foo] {
//select slice interval based on foos or any other calculation using self data...
&mut self.foos[..]
}
fn get_bar_given_foo(&self, foo: &Foo) -> &Bar {
//select bar based on foo or any other calculation using self data...
&self.bars[foo.id as usize]
}
//other utility functions that abstract e sequence of operations that I would
//like to use on the update path...
}
fn main() {
let mut world = World::create();
world.update();
}
You can also run the code.
It looks a very limiting situation because when on a mutable path like the update
function, I am unable to call any of the private methods from self
.
Since I don't want to clone all the data, I could think of three solutions. I tried 1 and 2 and both work.
Inline everything. Since this solution works for the example above, it looks like the compilation error is caused by the limitation of the Rust compiler that as I understand: it just looks the function signature and not the implementation of the functions.
Create functions that receive references to what they need. There is no need borrow
self
again. The functionWorld::get_foos_mut(&mut self) -> &mut [Foo]
could be removed and created a new one outsideWorld
:fn world_get_foos_mut(foos: &mut Vec<Foo>) -> &mut [Foo]
The code on the playground shows this solution.Create macros instead of regular functions? Since they are macros I suspect that there won't be any borrow involved. Since I am not familiar with macros I am unable to tell if this works or how to do this yet.
I really need other options because Solution 1 is not viable in my opinion and solution 2 looks very cumbersome and fragile (it looks that I might have the same problems but with the references inside World
).
I am really frustrated about not being able to find the correct model to handle this.
Will the Rust compiler try to analyze these situations in the future?