Hello! I'm having an issue with the lifetime specification of a key binding dynamic I've created in my program. I have a HashMap that maps integers (corresponding to key codes) to closures that call into the main struct (let's call it MainStruct) that comprises the business logic. Since I'm storing references in MainStruct, and key bindings may call methods that manipulate these references, I've come across some issues related to lifetimes. I've boiled down my problem to the following code snippet:
use std::cell::Cell;
use std::collections::HashMap;
use rand::Rng;
#[derive(Debug)]
struct ItemStruct {
id: u32,
vec: Vec<u32>,
}
impl ItemStruct {
pub fn new(id: u32) -> Self {
Self {
id,
vec: Vec::new(),
}
}
}
#[derive(Debug)]
struct Buffer<'buffer> {
pub item: Cell<Option<&'buffer ItemStruct>>,
}
impl<'buffer> Buffer<'buffer> {
pub fn set(&self, item: &'buffer ItemStruct) {
self.item.set(Some(item));
}
pub fn unset(&self) {
self.item.set(None);
}
}
struct MainStruct<'main> {
items: HashMap<u32, ItemStruct>,
buffer: Buffer<'main>,
}
impl<'main> MainStruct<'main> {
pub fn new() -> Self {
Self {
items: {
let mut map = HashMap::new();
map.insert(0, ItemStruct::new(0));
map.insert(1, ItemStruct::new(1));
map.insert(2, ItemStruct::new(2));
map
},
buffer: Buffer {
item: Cell::new(None),
},
}
}
pub fn add(&mut self, id: u32) {
self.items.insert(id, ItemStruct::new(id));
}
pub fn get(&self, id: u32) -> Option<&ItemStruct> {
self.items.get(&id)
}
pub fn store_buffer(&'main self, item: Option<&'main ItemStruct>) {
if let Some(item) = item {
self.buffer.set(item);
} else {
self.buffer.unset();
}
}
pub fn change_buffer(&'main self) {
let n: u32 = rand::thread_rng().gen_range(0..=2);
self.store_buffer(self.items.get(&n));
}
pub fn main_loop(
&'main mut self,
key_bindings: &HashMap<u32, Box<dyn FnMut(&mut MainStruct, u32)>>,
) {
(key_bindings.get(&0).unwrap())(self, 0);
}
}
fn main() {
let mut key_bindings: HashMap<u32, Box<dyn FnMut(&mut MainStruct<'_>, u32)>> = HashMap::new();
key_bindings.insert(
0,
Box::new(|m, id| {
m.store_buffer(m.get(id));
}),
);
let mut main = MainStruct::new();
main.main_loop(&key_bindings);
}
The issue occurs in main, where I'm inserting a Boxed closure into the HashMap representing the key bindings. The exact error message I'm getting is the following:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:92:15
|
92 | m.store_buffer(m.get(id));
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 91:18...
--> src/main.rs:91:18
|
91 | Box::new(|m, id| {
| __________________^
92 | | m.store_buffer(m.get(id));
93 | | }),
| |_________^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:92:13
|
92 | m.store_buffer(m.get(id));
| ^
note: but, the lifetime must be valid for the anonymous lifetime #3 defined on the body at 91:18...
--> src/main.rs:91:18
|
91 | Box::new(|m, id| {
| __________________^
92 | | m.store_buffer(m.get(id));
93 | | }),
| |_________^
note: ...so that the types are compatible
--> src/main.rs:92:15
|
92 | m.store_buffer(m.get(id));
| ^^^^^^^^^^^^
= note: expected `&MainStruct<'_>`
found `&MainStruct<'_>`
error: aborting due to previous error
Is there a way to solve this issue? If not, is there another (better) way to organize key bindings such as to achieve the desired functionality? Thanks a lot!
~dxx