1

I have a World struct which contains a vector storing closures which capture references to the canvas attribute from World. I feel I have made all the lifetime notations that has to be given. but it throws an error which I am unable to understand.

I have shortened the example I have been working on:

use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
struct Canvas {}
struct World<'a> {
    animations: Vec<AnimateClosure<'a>>,
    canvas: Canvas,
}
impl<'a> World<'a> {
    fn new(arg: &str) -> World {
        World {
            canvas: Canvas {},
            animations: vec![],
        }
    }
    fn check_collision(&'a mut self) {
        self.animation_cycle();
    }
    fn animation_cycle(&'a mut self) {
        let canvas = &self.canvas;
        let width = 10.0;
        let height = 10.0;
        let closure = move |x: f64| {
            let new = canvas;
        };
        let animation = AnimateClosure::new(10, Box::new(closure) as Box<dyn Fn(f64)>);
        self.animations.push(animation);
    }
}
pub struct AnimateClosure<'a> {
    closure: Box<dyn Fn(f64) + 'a>,
}
impl<'a> AnimateClosure<'a> {
    pub fn new(duartion: u32, closure: Box<dyn Fn(f64) + 'a>) -> AnimateClosure<'a> {
        AnimateClosure { closure }
    }
}

pub fn main() {
    let mut world = World::new("game-of-drops");
    let closure_cell = Rc::new(RefCell::new(None));
    let closure_cell_clone = Rc::clone(&closure_cell);
    *closure_cell.borrow_mut() = Some(Closure::wrap(Box::new(move |x: f64| {
        world.check_collision();
        world.animation_cycle();
    }) as Box<dyn FnMut(_)>));
}

I feel the problem might be from the canvas field stored in animate_closure, but I do not understand how to solve the problem with more lifetime annotations.

error: borrowed data cannot be stored outside of its closure
  --> src/load.rs:45:9
   |
41 |     let mut world = World::new("game-of-drops");
   |         --------- ...so that variable is valid at time of its declaration
...
44 |     *closure_cell.borrow_mut() = Some(Closure::wrap(Box::new(move |x: f64| {
   |                                                              ------------- borrowed data cannot outlive this closure
45 |         world.check_collision();
   |         ^^^^^ --------------- cannot infer an appropriate lifetime...
   |         |
   |         cannot be stored outside of its closure

Cargo.toml

wasm-bindgen = "0.2.48"

[dependencies.web-sys]
version = "0.3.25"
features = ['console', 'CanvasRenderingContext2d']

Edit

This is not a duplicate of the question. I am not passing any reference to the closure to cause any conflicts here. Only reference comes from the attribute of world canvas.

raj
  • 5,989
  • 7
  • 30
  • 62
  • It looks like your question might be answered by the answers of [What does “borrowed data cannot be stored outside of its closure” mean?](https://stackoverflow.com/q/51118023/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 27 '19 at 15:23
  • Possible duplicate of [What does "borrowed data cannot be stored outside of its closure" mean?](https://stackoverflow.com/questions/51118023/what-does-borrowed-data-cannot-be-stored-outside-of-its-closure-mean) – E_net4 Aug 27 '19 at 15:30
  • Why do you have `(&'a mut self)` instead of `(&mut self)`? – Shepmaster Aug 27 '19 at 16:33
  • Duplicate may need to be combined with [What is the difference between '&self' and '&'a self'?](https://stackoverflow.com/q/45833618/155423). – Shepmaster Aug 27 '19 at 16:34
  • @Shepmaster by having ``(&'a mut self)`` i was trying to say that the ``self`` would only live for ``World<'a>`` lifetime. As the example you shared itseems that can constrain the lifetime if the struct is Contravariant. Should we always prefer a new lifetime ``b`` for all methods? What would be an example where only the same lifetime ``a`` make sense in method defenition? – raj Aug 27 '19 at 20:41

0 Answers0