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 Box
ed 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