I am trying to learn Rust, specifically lifetimes and smart pointers and would like to know the most Rusty way of doing this.
Specifically, assume we are designing a mock language and "analyzer":
a=1 # each line is of form name=number|name
b=2
c=a # a is "copied" to c and should have value 1
a=4 # a and all its references should now have value 4
Lets design some bogus "Memory Node" abstraction
| Code | Memory Nodes | 
|---|---|
| a=1 | Node { name: "a", value: 4 } | 
| b=2 | Node { name: "b", value: 2 } | 
| c=a | Node { name: "c", value: 1 } | 
| a=4 | Node { name: "a", value: 4 } | 
Note: We want only three memory nodes to exist and not four like a AST
So that I can resolve values of variables, I must keep a context from name to "Memory Node"
To keep my analyzer's API clean I don't want to expose this Context.
Lets say our base structs look like these:
struct Root {
    pub nodes: Vec<&Node>,
}
struct Node {
    pub name: String,
    pub value: u64,
}
struct Context {
    nodes: HashMap<String, Node>,
}
impl Node {
    fn new(line: &str, context: &mut Context) -> Node {
         // Add self to context
         // If node exists in context, update it and return the same
         // return new node
    }
}
However, we cant keep copies of Node in both Context and Root.
One way is to wrap node up like Rc<RefCell<Node>> everywhere, this would make the client API not neat. I would ideally like to maintain Root containing a Vec of &Node as the public API. An example implementation is here https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7ec7ecd29eea2626a11b90c829777e30
When I try this using lifetimes I get an error that I cant really circumvent - https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5c5054872806b94a5b3a8ad4a75c1282
It gives:
error[E0499]: cannot borrow `context` as mutable more than once at a time
  --> src/main.rs:49:39
   |
43 |     fn new(text: &str) -> Root {
   |                  - let's call the lifetime of this reference `'1`
...
49 |             let node = Node::new(row, &mut context);
   |                                       ^^^^^^^^^^^^ `context` was mutably borrowed here in the previous iteration of the loop
...
52 |         Root { nodes, context }
   |         ----------------------- returning this value requires that `context` is borrowed for `'1`
error[E0505]: cannot move out of `context` because it is borrowed
  --> src/main.rs:52:23
   |
43 |     fn new(text: &str) -> Root {
   |                  - let's call the lifetime of this reference `'1`
...
49 |             let node = Node::new(row, &mut context);
   |                                       ------------ borrow of `context` occurs here
...
52 |         Root { nodes, context }
   |         --------------^^^^^^^--
   |         |             |
   |         |             move out of `context` occurs here
   |         returning this value requires that `context` is borrowed for `'1`
Some errors have detailed explanations: E0499, E0505.
For more information about an error, try `rustc --explain E0499`.
Alternatively what are other Rusty ways to do this, without using Smart pointers if possible?
