Foo
can be modified using the method .modify()
:
struct Foo;
impl Foo {
fn modify(&mut self) {}
}
Bar
stores a callback:
struct Bar<'a> {
callback: Box<FnMut() + 'a>,
}
impl<'a> Bar<'a> {
fn new<F: FnMut() + 'a>(f: F) -> Bar<'a> {
Bar {
callback: Box::new(f),
}
}
}
init()
takes a slice of Bar
and executes their callbacks:
fn init(bars: &mut [Bar]) {
for b in bars {
(*b.callback)();
}
}
And now the most interesting:
Changing Foo
in a loop works fine; on each iteration of the loop foo
is mutably borrowed and .modify()
is called:
fn main() {
let mut foo = Foo;
for _ in 0..10 {
foo.modify();
}
}
Changing Foo
inside of the callbacks does not work:
fn main() {
let mut foo = Foo;
let mut bar1 = Bar::new(|| foo.modify());
let mut bar2 = Bar::new(|| foo.modify());
init(&mut [bar1, bar2]);
}
Try it on the playground, it has an error:
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> src/main.rs:27:29
|
26 | let mut bar1 = Bar::new(|| foo.modify());
| -- --- previous borrow occurs due to use of `foo` in closure
| |
| first mutable borrow occurs here
27 | let mut bar2 = Bar::new(|| foo.modify());
| ^^ --- borrow occurs due to use of `foo` in closure
| |
| second mutable borrow occurs here
...
30 | }
| - first borrow ends here
How to implement a similar guarantee for item 2?
You can use
RefCell
:Be careful with
borrow_mut()
, it panics if the value is currently borrowed.If you can change
Bar
andinit()
, you can pass valuefoo
to theinit()
separate from the methodmodify()
: