I'm new at Rust and still struggling with the borrow checker and getting lifetimes right.
Here's a simple struct I've started to build - it stores collections of command-line argument like things (which can be represented by a --string
or a -c
or both):
struct OptionMap<'a, T: 'a> {
name: HashMap<String, &'a T>,
short_name: HashMap<char, &'a T>,
options: Vec<T>
}
impl<'a, T: 'a> OptionMap<'a, T> {
pub fn new() -> OptionMap<'a, T> {
OptionMap {
name: HashMap::new(),
short_name: HashMap::new(),
options: Vec::new()
}
}
pub fn register(&mut self, name: &OptionName, option: T) {
if name.name.is_some() {
self.name.insert(name.name.unwrap().to_owned(), &option);
}
if name.short_name.is_some() {
self.short_name.insert(name.short_name.unwrap(), &option);
}
self.options.push(option);
}
}
I get two of these errors (one for each of the &option
parameters I wrote):
Compiling glam v0.1.0 (file:///Users/carson/Projects/glam)
src/options.rs:57:66: 57:72 error: `option` does not live long enough
src/options.rs:57 self.name.insert(name.name.unwrap().to_owned(), &option);
^~~~~~
src/options.rs:54:62: 66:6 note: reference must be valid for the lifetime 'a as defined on the block at 54:61...
src/options.rs:54 pub fn register(&mut self, name: &OptionName, option: T) {
src/options.rs:55 {
src/options.rs:56 if name.name.is_some() {
src/options.rs:57 self.name.insert(name.name.unwrap().to_owned(), &option);
src/options.rs:58 }
src/options.rs:59 }
...
src/options.rs:54:62: 66:6 note: ...but borrowed value is only valid for the scope of parameters for function at 54:61
src/options.rs:54 pub fn register(&mut self, name: &OptionName, option: T) {
src/options.rs:55 {
src/options.rs:56 if name.name.is_some() {
src/options.rs:57 self.name.insert(name.name.unwrap().to_owned(), &option);
src/options.rs:58 }
src/options.rs:59 }
...
I pass a reference to each of the hash maps (so they borrow it) and then pass the option straight to the vector to move it there, so that the option doesn't go out of scope.
It seems like the scope of 'a
and the scope of option
should be the same to me - since OptionMap
is created with lifetime 'a
, and T
is bound by that lifetime as well, and option
gets moved into options
at the end of the function. What am I missing? I feel like I'm constantly fighting with lifetimes in Rust, like there's something that hasn't clicked for me yet.