So I have this run function which creates a reactor, spawns some futures and then calls core.run(). Nothing should outlive this method. However I correctly get an error saying that the closure might outlive the borrowed content, which isn't the case.
spawn() requires a future that’s 'static - the compiler can’t reason about the rest of the code like you can . The typical way out is to use shared ownership even if technically unnecessary. Otherwise, you’d need to step into unsafe territory and enforce lifetime invariants without borrowck.
Generally, this means using Rc or Arc, depending on threading requirements. In the case of tokio, which is a single-threaded event loop, Rc is enough.
In your case, I don't think you need a Mutex (unless the real code does, which isn't visible in the playground). You can wrap the HashMap in a RefCell, which is like a single-threaded mutex.
So something like this for your example:
pub struct Coordinator {
// Rc<RefCell<>> wrapper
sessions : Rc<RefCell<HashMap<String, String>>,
}
...
// Make a clone - this gives you an "owned" handle to the data, even though all clones reference the same
// piece of data - this is shared ownership
let user_session_clone = Rc::clone(&self.sessions);
// Add `move` so the closure takes ownership of `user_session_clone`. Now your closure doesn't capture
// any references from its environment, and is therefore 'static
let us_f = user_sessions.for_each(move |user_session| {
let m = &mut *user_session_clone.borrow_mut();
m.insert( "".to_owned(), " ".to_owned() );
future::ok( () )
});
core.handle().spawn( us_f );