I am trying to build a System
that contains Type
s, which contain Field
s, which in turn refer to (other) Type
s. In other words, trying to implement something similar to a possible in-memory representation of parsing Rust structs.
I have the following code (playground), which gives an error: cannot borrow
system as mutable because it is also borrowed as immutable
. I have started to use enough Rust to understand why that is an error: Adding to system
(a mutable borrow), which in turn adds to a vector, may move memory upon exhausting its capacity. This will make any dolled-out references (immutable borrows) dangled.
But I can't figure out how to do what I want/need to do. I think a Box
or RefCell
may be a part of a solution (to keep Type
objects in heap and thus keep them valid even when the vector (of such wrapper) reallocates). However, not sure if this is the correct way to think about and how to put them to a good use.
pub struct System<'system> {
types: Vec<Type<'system>>,
}
pub struct Type<'a> {
pub name: String,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub name: String,
pub tpe: &'a Type<'a>,
}
impl<'system> System<'system> {
fn new() -> Self {
let primitive_types: Vec<Type> = ["Int", "String"].iter().map(|tname| Type {
name: tname.to_string(),
fields: vec![],
}).collect();
System {
types: primitive_types,
}
}
fn find_type(&self, name: String) -> Option<&Type<'system>> {
self.types.iter().find(|tpe| tpe.name == name)
}
fn add_type(&mut self, tpe: Type<'system>) {
self.types.push(tpe);
}
}
pub fn test() {
let mut system = System::new();
let person_type = Type {
name: "Person".to_string(),
fields: vec![
Field {
name: "first_name".to_string(),
tpe: system.find_type("String".to_string()).unwrap(),
}
]
};
system.add_type(person_type);
}
Any hints on fixing this?