Referring to the following code below :
use std::collections::HashMap;
use std::sync::RwLock;
#[derive(Debug, PartialEq, Eq)]
pub enum RespType<'a> {
SimpleString(&'a str),
RespError((&'a str, &'a str)),
Integer(i32),
BulkString(Option<&'a str>),
Array(Vec<RespType<'a>>),
}
type Db<'a> = RwLock<HashMap<&'a str, RespType<'a>>>;
pub trait KeyValueStore<'a> {
fn get_value<'b>(&'a self, key: &'b str, callback: &'a dyn Fn(&'a RespType<'a>));
fn set_value(&'a mut self, key: &'a str, value: RespType<'a>) -> &'a RespType<'a>;
}
impl<'a> KeyValueStore<'a> for Db<'a> {
fn get_value<'b>(&'a self, key: &'b str, callback: &'a dyn Fn(&'a RespType<'a>)) {
static null_bulk_string:RespType = RespType::BulkString(None);
let guard = self.read().unwrap();
let result = guard.get(key);
match result{
Some(v) => {callback(v)}
None => {callback(&null_bulk_string)}
};
}
fn set_value(&'a mut self, key: &'a str, value: RespType<'a>) -> &'static RespType<'static> {
static ok: RespType = RespType::SimpleString("OK");
(*self.get_mut().unwrap()).insert(key, value).unwrap();
&ok
}
}
fn main(){
}
The error message is this:
error[E0597]: `guard` does not live long enough
--> src/main.rs:23:22
|
19 | impl<'a> KeyValueStore<'a> for Db<'a> {
| -- lifetime `'a` defined here
...
23 | let result = guard.get(key);
| ^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `guard` is borrowed for `'a`
...
28 | }
| - `guard` dropped here while still borrowed
The readlock is dropped at the end of get_value but I can't seem to pass it into callback which clearly doesn't have a lifetime that extends past the readlock. What's going on? Also I don't understand what the error message is trying to say. Can someone explain?
You're going a bit overboard with the lifetime annotations, which is tying things together that you don't intend to be tied together. Look at the signature of get_value
:
fn get_value<'b>(&'a self, key: &'b str, callback: &'a dyn Fn(&'a RespType<'a>));
This requires that the lifetime of the borrow given to the callback function must be valid as long as the borrow of self
, but it isn't. This is why the error message specifically says "argument requires that guard
is borrowed for 'a
" (which is actually an impossible condition to satisfy, as self
also has lifetime 'a
and any guard obtained from self
won't live as long as self
).
The solution is to simply not bind these lifetimes together:
fn get_value<'b>(&'a self, key: &'b str, callback: &dyn Fn(&RespType));
With this signature, the code compiles.
I would suggest taking a step back and trying to figure out what you're trying to convey with the lifetime annotations. It looks like you're just sprinkling them everywhere without understanding exactly what they do -- why does get_value
need the 'b
annotation on the key
argument, for example?