-1

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>`
Ali Husham
  • 816
  • 10
  • 31

1 Answers1

0

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>>.

WorldSEnder
  • 4,875
  • 2
  • 28
  • 64
  • But, I also need mitate the `sel.curr` from inside the closure – Ali Husham Apr 24 '22 at 19:56
  • 1
    You want "shared mutable state" and there isn't one correct answer to give, if you aren't precise on how you want to mutate. Use that search term to learn about it, there should be enough other answers, besides, that's what I meant with changing the type of `self.curr`. @alial-karaawi – WorldSEnder Apr 24 '22 at 20:04
  • I believe that I have to tell rust to set a lifetime to the closure 'a. Maybe I should sell it like this `}) as Box<&'a yn FnMut(_)>);` what do you think @worldSEnder – Ali Husham Apr 24 '22 at 22:11
  • @alial-karaawi the [docs for Closure::wrap](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/closure/struct.Closure.html#method.wrap) state that the `dyn Fn` or `FnMut` *must be `'static`*, I don't think you can work around that. – WorldSEnder Apr 24 '22 at 22:56