I'm trying to create a method that returns an iterator over the values of HashMap
that is boxed inside a RefCell
, but i'm having an error where Ref
returned by RefCell::borrow
doesn't live long enough for iterator to be returned from the method. Here's my code:
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::collections::hash_map::Values;
struct Foo {
map: Rc<RefCell<HashMap<i32, i32>>>,
}
impl Foo {
fn iter(&self) -> Values<i32, i32> {
self.map.borrow().values()
}
}
fn main() {
let foo = Foo {
map: Rc::new(RefCell::new(HashMap::new()))
};
for v in foo.iter() {
println!("{}", v)
}
}
Compilation error:
rustc 1.15.1 (021bd294c 2017-02-08)
error: borrowed value does not live long enough
--> <anon>:12:9
|
12 | self.map.borrow().values()
| ^^^^^^^^^^^^^^^^^ does not live long enough
13 | }
| - temporary value only lives until here
|
How do I return a reference to something inside a RefCell without breaking encapsulation? suggests creating a guard that incapsulates Ref
and provides an interface for accessing the underlying value, but what I need to do is to return an iterator object (Values<'a, K, V>
) that already incapsulates a plain reference to a HashMap
.
My main problem is that I have a runtime tracked reference Ref<T>
while I need a plain reference to create an iterator. Ref::map
exposes a plain reference for mapping, but it requires the mapper function to return another reference which is impossible here. Should I redo the entire iterator functionality to work with Ref
or is there a better way?