What would be an idiomatic version of something like this playground:
trait Thing {
fn update(&mut self, parent: &ThingHolder) {
// Make some mutation of `self`
// which depends on method(s) from `parent`
}
}
// Quick sample `Thing` implementation
struct Usize(usize);
impl Thing for Usize {
fn update(&mut self, parent: &ThingHolder) {
self.0 += 1; // Note a realistic case would depend on `parent`
}
}
struct ThingHolder {
things: Vec<Box<dyn Thing>>,
}
impl ThingHolder {
fn update_things(&mut self) {
for t in self.things.iter_mut() {
t.update(&self);
}
}
}
- struct
ThingHolder
has a vector of Boxes to trait-objects (Vec<Box<dyn Thing>>
) - It wants to call a (mutating) update method on each
Thing
, which depends on (immutable) data from its parentThingHolder
- Different implementations of
Thing
will differ in the content ofupdate
As-is, this is a borrow-checker error:
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/lib.rs:23:22
|
22 | for t in self.things.iter_mut() {
| ----------------------
| |
| mutable borrow occurs here
| mutable borrow later used here
23 | t.update(&self);
| ^^^^^ immutable borrow occurs here
error: aborting due to previous error
Primary alternative I can see is instead of mutating, having Thing::update
return a new Box<dyn Thing>>
and having the loop replace elements in self.things
. This is for some scientific-ish code, so its unclear whether I want the penalty of copying each Thing
for each update.
Are there good alternatives I'm missing?
Thanks!