Reputation: 8747
I have state that needs to be mutated multiple times by JavaScript callbacks (it's a game, so input from the user needs to modify the game state). I can't seem to figure out how to do it though. This is the simplest example I can think of that demonstrates the problem I'm having:
#[wasm_bindgen(start)]
pub fn run() {
let data = Rc::new(RefCell::new(vec![0]));
let closure = Closure::wrap(Box::new(&mut || {
data.borrow_mut().push(0);
console_log!("{data:?}");
}) as Box<dyn FnMut()>);
closure.forget();
}
I thought that using an Rc
would make data
live as long as it's used, but I get this error:
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:19:47
|
19 | let closure = Closure::wrap(Box::new(&mut || {
| _________________________________-_____________^
| |_________________________________|
| ||
20 | || data.borrow_mut().push(0);
21 | || console_log!("{data:?}");
22 | || }) as Box<dyn FnMut()>);
| || ^- - temporary value is freed at the end of this statement
| ||_____||
| |_____|cast requires that borrow lasts for `'static`
| creates a temporary which is freed while still in use
error[E0597]: `data` does not live long enough
--> src/lib.rs:20:9
|
19 | let closure = Closure::wrap(Box::new(&mut || {
| - -- value captured here
| _________________________________|
| |
20 | | data.borrow_mut().push(0);
| | ^^^^ borrowed value does not live long enough
21 | | console_log!("{data:?}");
22 | | }) as Box<dyn FnMut()>);
| |______- cast requires that `data` is borrowed for `'static`
...
25 | }
| - `data` dropped here while still borrowed
How can I fix this problem?
Upvotes: 0
Views: 768
Reputation: 70990
Rc
can make it live enough, but currently you're borrowing the Rc
itself which is destroyed at the end of run()
. You need to clone it, and move the clone into the closure:
#[wasm_bindgen(start)]
pub fn run() {
let data = Rc::new(RefCell::new(vec![0]));
let closure = Closure::wrap(Box::new({
let data = Rc::clone(&data);
&mut move || {
data.borrow_mut().push(0);
console_log!("{data:?}");
}
}) as Box<dyn FnMut()>);
closure.forget();
}
You also need to not borrow the closure itself, which is the reason for the "temporary value dropped while borrowed" error. Replace the &mut move || {
with just move || {
.
Upvotes: 2