Currently, I'm trying to implement a closure that captures one of the arguments to the enclosing function:
pub struct RegisteredHtmlEvent<'a> {
event_target: EventTarget,
type_: &'a str,
closure: wasm_bindgen::closure::Closure<dyn std::ops::FnMut(Event)>
}
pub fn add_event_listener_state<'a, T>(&self, type_: &'a str, state: T, listener: Box<dyn Fn(&T, Event) -> ()>) -> Result<RegisteredHtmlEvent<'a>, JsValue> {
let closure = Closure::wrap(Box::new(move |event| listener(&state, event)) as Box<dyn FnMut(Event)>);
match self.event_target.add_event_listener_with_callback(type_, closure.as_ref().unchecked_ref()) {
Err(e) => Err(e),
_ => {
Ok(RegisteredHtmlEvent {
event_target: self.event_target.clone(),
type_,
closure: closure
})
}
}
}
Naively, I assume that add_event_listener_state takes ownership of the state parameter. Then, the closure should take ownership of state.
But, compiling gives me the following error:
error[E0310]: the parameter type `T` may not live long enough
--> src/web_sys_mixins.rs:48:34
|
47 | pub fn add_event_listener_state<'a, T>(&self, type_: &'a str, state: T, listener: Box<dyn Fn(&T, Event) -> ()>) -> Result<RegisteredHtmlEvent<'a>, JsValue> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
48 | let closure = Closure::wrap(Box::new(move |event| listener(&state, event)) as Box<dyn FnMut(Event)>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@src/web_sys_mixins.rs:48:43: 48:79 listener:std::boxed::Box<dyn for<'r> std::ops::Fn(&'r T, web_sys::Event)>, state:T]` will meet its required lifetime bounds
Surprisingly, "T: Clone" doesn't help. Making the state parameter 'static causes problems with the caller because state is transient. (It's not static.)
How do I get the closure to take ownership of the state parameter without making it 'static?