I'm new to rust, and what I want is:
- A set of properties (Prop)
- A set of categories (Cat), which are defined by one or more Props
- A dictionary (Dict), which stores these things. Once created, Cats and Props are read-only.
It seems straightforward enough, but Rust is making it very difficult; with my programming background it's counterintuitive and frustrating, and I can't work out the correct way to do it.
use std::collections::HashMap;
struct Prop<'a> {
name: &'a str
}
type PropVec<'a> = Vec<&'a Prop<'a>>;
struct Cat<'a> {
name: &'a str,
props: PropVec<'a>
}
struct Dict<'a> {
props: HashMap<&'a str, Prop<'a>>,
cats: HashMap<&'a str, Cat<'a>>,
}
impl<'a> Dict<'a> {
pub fn define_prop(&mut self, name: &'a str) {
self.props.insert(name, Prop { name });
}
pub fn prop(&self, name: &str) -> Option<&Prop> {
self.props.get(name)
}
pub fn define_cat(&mut self, name: &'a str, prop_names: Vec<&'a str>) {
let mut props: PropVec<'a> = Vec::new();
for name in prop_names {
if let Some(prop) = self.prop(name) {
props.push(prop);
}
}
self.cats.insert(name, Cat { name: name, props });
}
}
fn main() {
let mut d = Dict { props: HashMap::new(), cats: HashMap::new() };
d.define_prop("foo");
d.define_cat("bar", vec!("foo"));
}
The compiler says:
error: lifetime may not live long enough
--> src/main.rs:29:24
|
19 | impl<'a> Dict<'a> {
| -- lifetime `'a` defined here
...
28 | pub fn define_cat(&mut self, name: &'a str, prop_names: Vec<&'a str>) {
| - let's call the lifetime of this reference `'1`
29 | let mut props: PropVec<'a> = Vec::new();
| ^^^^^^^^^^^ type annotation requires that `'1` must outlive `'a`
error[E0502]: cannot borrow `self.cats` as mutable because it is also borrowed as immutable
--> src/main.rs:37:9
|
19 | impl<'a> Dict<'a> {
| -- lifetime `'a` defined here
...
29 | let mut props: PropVec<'a> = Vec::new();
| ----------- type annotation requires that `*self` is borrowed for `'a`
...
32 | if let Some(prop) = self.prop(name) {
| --------------- immutable borrow occurs here
...
37 | self.cats.insert(name, Cat { name: name, props });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
And so:
- Because I'm using references, I need to put lifetimes everywhere, which leads to the first error. Is there another way to do it? I've tried using Box and Rc instead, but without success. If not, what is the correct way to specify the lifetimes?
- Is the comment about *self in line 29 anything to worry about?
- I understand that the first borrow of self is preventing the second, but surely it's possible to get the Prop, or a reference to it, and store it somewhere else?