For example, I have the next structure:
struct MyStruct {
items: RefCell<HashMap<i32, SomeStruct>>,
}
impl MyStruct {
fn new() -> Self {
Self {
items: RefCell::new(HashMap::new()),
}
}
fn get_item(&self, key: &i32) -> Option<&SomeStruct> {
let items = self.items.borrow();
items.get(key)
}
}
That code won't compile due to different lifetimes. So, I've tried to introduce these lifetimes:
fn get_item<'a>(&'a self, key: &i32) -> Option<&'a SomeStruct> {
let items = self.items.borrow();
items.get(key)
}
However it fixed a nothing.
Is it possible to return Option<&'a SomeStruct>
or a similar type in this case?
As mentioned in the comments, you cannot return a named reference because such a reference would outlive the Ref
returned by RefCell::borrow()
. With the Ref
gone, nothing would stop you from calling borrow_mut()
to obtain a mutable reference with the shared reference still in existence, which would be undefined behavior.
Instead, you can return an optional Ref
which the caller can use to obtain a reference (whose lifetime is correctly tied to that Ref
). To get Option<Ref<SomeStruct>>
, you can use Ref::filter_map()
:
fn get_item<'a>(&'a self, key: &i32) -> Option<Ref<'a, SomeStruct>> {
Ref::filter_map(self.items.borrow(), |items| items.get(key)).ok()
}
As mentioned in the comments, you can even hide RefCell
usage from the public API, by returning Option<impl Deref<Target = SomeStruct> + 'a>
instead. (Playground.)