I'm trying to make a struct containing two hashmaps - one with some value, and one with reference to another hashmap's element. Here is my code.
use std::collections::HashMap;
struct Foo;
struct Bar<'s>(&'s Foo);
struct MyStruct<'a> {
first : HashMap<&'a str, Foo>,
second : HashMap<&'a str, Bar<'a>>,
}
impl<'a> MyStruct<'a> {
fn new() -> MyStruct<'a> {
let mut result = MyStruct {
first : HashMap::new(),
second : HashMap::new(),
};
match result.first.get("") {
Some(t) => { result.second.insert("", Bar(t)); },
None => {},
}
result
}
}
fn main() {
}
and this code fails to compile with following error :
error:
result.first
does not live long enough
I think this problem is related to lifetime, but I can't clearly explain what is wrong.
Could anybody explain what is happening and how to solve this error?
P.S. struct Foo
and Bar
are from library, so I can't modify these structs.
The problem is indeed related to ownership/borrowing/lifetimes.
In general, in Rust, it is not possibly to (safely) take a reference in a sibling attribute; therefore having .second
point into .first
is impossible.
However, even if you separated this in two structures, you will still run into problems because taking a reference into a HashMap
borrows it (which means that as long as the reference lives, modifying the HashMap
is forbidden), which is probably not what you wish for.
This last hurdle can be avoided, in this case, by simply sharing the memory; for example, having both HashMap
using a Rc<X>
value instead of X
and &'a X
respectively...
... however this will not help with your particular question given the Foo
and Bar<'a>
types.
You could change your structure into:
struct MyStruct<'a, 'b> {
first: HashMap<&'a str, &'b Foo>,
second: HashMap<&'a str, Bar<'b>>,
}
and then maintain the actual Foo
instances elsewhere. A possibility if you need to allocate those Foo
while maintaining the HashMap
is to use arena allocation such as Arena<Foo>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With