Let's say we have a struct
containing callbacks:
use std::collections::HashMap;
struct Struct {
callbacks: HashMap<char, Box<Fn(&mut Struct)>>,
}
impl Struct {
fn new() -> Struct {
Struct {
callbacks: HashMap::new(),
}
}
fn add_callback<F: Fn(&mut Struct) + 'static>(&mut self, key: char, callback: F) {
self.callbacks.insert(key, Box::new(callback));
}
fn invoke_callback(&mut self, key: char) {
if let Some(callback) = self.callbacks.get(&key) {
callback(self); // NOTE: error here
}
}
fn print(&mut self) {
println!("Mutably print");
}
}
fn main() {
let mut strct = Struct::new();
strct.add_callback('a', |strct| {
strct.print();
});
strct.invoke_callback('a');
}
With this code, I have the following error:
src/main.rs:20:22: 20:26 error: cannot borrow `*self` as mutable because `self.callbacks` is also borrowed as immutable [E0502]
src/main.rs:20 callback(self);
^~~~
src/main.rs:19:33: 19:47 note: previous borrow of `self.callbacks` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `self.callbacks` until the borrow ends
src/main.rs:19 if let Some(callback) = self.callbacks.get(&key) {
^~~~~~~~~~~~~~
src/main.rs:21:10: 21:10 note: previous borrow ends here
src/main.rs:19 if let Some(callback) = self.callbacks.get(&key) {
src/main.rs:20 callback(self);
src/main.rs:21 }
^
error: aborting due to previous error
error: Could not compile `so`.
How can I invoke the callback that takes a mutable reference to self
?
The only way I found was to remove the callback from the HashMap
and inserting it back:
fn invoke_callback(&mut self, key: char) {
if let Some(callback) = self.callbacks.remove(&key) {
callback(self);
self.callbacks.insert(key, callback);
}
}
I wonder if there is a better way of invoking a callback contained in a struct
.