Actually I try to implement the following functionality in Rust.
I want to have a structure Node which has a vector to some other Node structures. In addition I have a master vector which keeps all the Node structures which have been instantiated.
The key point here is that the Nodes are allocated within a loop (i.e. an own scope) and the master vector keeping all the structures (or references to the structures) is declared outside the loop which is in my opinion a 0815 use case.
After a lot of trying I came up with this code which still does not compile. Actually I tried it with just &Node and alternatively with RefCell<&Node>, both do not compile.
struct Node<'a> {
name: String,
nodes: RefCell<Vec<&'a Node<'a>>>,
}
impl<'a> Node<'a> {
fn create(name: String) -> Node<'a> {
Node {
name: name,
nodes: RefCell::new(Vec::new()),
}
}
fn add(&self, value: &'a Node<'a>) {
self.nodes.borrow_mut().push(value);
}
fn get_nodes(&self) -> Vec<&'a Node> {
self.nodes.take()
}
}
// Later the code ...
let mut the_nodes_ref: HashMap<String, RefCell<&Node>> = HashMap::new();
let mut the_nodes_nodes: HashMap<String, &Node> = HashMap::new();
// This works
let no1_out = Node::create(String::from("no1"));
let no2_out = Node::create(String::from("no2"));
no1_out.add(&no2_out);
no2_out.add(&no1_out);
the_nodes_nodes.insert(no1_out.name.clone(), &no1_out);
the_nodes_nodes.insert(no2_out.name.clone(), &no2_out);
let no1_ref_out = RefCell::new(&no1_out);
let no2_ref_out = RefCell::new(&no2_out);
the_nodes_ref.insert(no1_out.name.clone(), no1_ref_out);
the_nodes_ref.insert(no2_out.name.clone(), no2_ref_out);
// This works not because no1 and no2 do not live long enough
let items = [1, 2, 3];
for _ in items {
let no1 = Node::create(String::from("no1"));
let no2 = Node::create(String::from("no2"));
no1.add(&no2); // <- Error no2 lives not long enough
no2.add(&no1); // <- Error no1 lives not long enough
the_nodes_nodes.insert(no1.name.clone(), &no1);
the_nodes_nodes.insert(no2.name.clone(), &no2);
let no1_ref = RefCell::new(&no1);
let no2_ref = RefCell::new(&no2);
the_nodes_ref.insert(no1.name.clone(), no1_ref);
the_nodes_ref.insert(no2.name.clone(), no2_ref);
}
I kind of understand the problem, but I am wondering how to solve this problem. How can I allocate a structure within an separate scope (here the for loop) and then use the allocated structures outside the for loop. I mean it is a common use case to allocate a structure within a loop and use it later outside of the loop.
Somehow I have the feeling that the missing link is to tell the Rust Compiler via the lifetime parameters, that the references should also stay alive outside the for loop but I have no idea how to do that. But maybe this is also not the correct way to do it ....
Actually another key point here is that I want that the Nodes have references to the other Nodes and not copies of the Nodes. The same is true for the master vector, this vector should have references to the allocated Nodes and not copies of the Nodes.