after using move in closure I got "cannot infer an appropriate lifetime due to conflicting requirements "

91 views Asked by At

my struct

use web_sys::{Document, Element, window};
use wasm_bindgen::{UnwrapThrowExt, JsCast};
use std::cell::RefCell;
use wasm_bindgen::closure::Closure;
use web_sys::console::log_1;


pub struct Draggable2 {
    doc: Document,
    pub(crate) body: Element,
    prev: Option<Element>,
    pub(crate) curr: Option<Element>,
    dragged: Option<Element>,
}

impl Draggable2 {
    pub(crate) fn new() {
        let doc = window().unwrap_throw().document().unwrap_throw();
        let body = doc.query_selector("body").unwrap_throw().unwrap_throw();
        let _self = &mut Draggable2 { doc, body, prev: None, curr: None, dragged: None };
        _self.drag_handler();
    }
}

problem accor when I use self.curr inside the clouse with move

use web_sys::console::log_1;

use crate::editor::plugins::draggable_2::draggable_2::Draggable2;
use wasm_bindgen::prelude::Closure;
use wasm_bindgen::JsCast;

impl<'a> Draggable2 {
    pub fn drag_handler(&'a mut self) {

        let closure = Closure::wrap(Box::new(move |event: web_sys::DragEvent| {
            log_1(&format!("{:#?}", self.curr).into());
self.curr = get_element(event.psge_x(),event.page_y())
        }) as Box<dyn FnMut(_)>);

        self.body.add_event_listener_with_callback("drop", &closure.as_ref().unchecked_ref());
        closure.forget();
    }
}

full error message.

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/editor/plugins/draggable_2/drag_handler.rs:13:46
   |
13 |           let closure = Closure::wrap(Box::new(move |event: web_sys::DragEvent| {
   |  ______________________________________________^
14 | |             log_1(&format!("{:#?}", self.curr).into());
15 | |         }) as Box<dyn FnMut(_)>);
   | |_________^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
  --> src/editor/plugins/draggable_2/drag_handler.rs:7:6
   |
7  | impl<'a> Draggable2 {
   |      ^^
note: ...so that the types are compatible
  --> src/editor/plugins/draggable_2/drag_handler.rs:13:46
   |
13 |           let closure = Closure::wrap(Box::new(move |event: web_sys::DragEvent| {
   |  ______________________________________________^
14 | |             log_1(&format!("{:#?}", self.curr).into());
15 | |         }) as Box<dyn FnMut(_)>);
   | |_________^
   = note: expected `(&mut Draggable2,)`
              found `(&'a mut Draggable2,)`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
  --> src/editor/plugins/draggable_2/drag_handler.rs:13:23
   |
13 |         let closure = Closure::wrap(Box::new(move |event: web_sys::DragEvent| {
   |                       ^^^^^^^^^^^^^
   = note: expected `<dyn FnMut(DragEvent) as WasmClosure>`
              found `<(dyn FnMut(DragEvent) + 'static) as WasmClosure>`
1

There are 1 answers

4
WorldSEnder On

Because self is a reference, self.curr will not get moved into the closure, despite the move annotation before it. So the closure has to capture a reference, i.e. &self.curr. The lifetime of this reference is 'a, so the closure also inherits that lifetime. But Closure::wrap expects a closure with a lifetime of 'static, so valid "forever".

Your question doesn't contain enough information on how to solve this. It might be that moving a clone into the closure is sufficient

    let captured_curr = self.curr.clone();
    let closure = Closure::wrap(Box::new(move |event: web_sys::DragEvent| {
        log_1(&format!("{:#?}", captured_curr).into());
    }) as Box<dyn FnMut(_)>);

or you have to somehow share the current value with the closure, for example by changing the type of self.curr to a shareable Rc<RefCell<Option<Element>>.