3
votes

I have a cyclic graph-like structure where nodes refer to other nodes. I've removed some stuff for brevity. I'm still just beginning to learn Rust, and I used Rust borrowed pointers and lifetimes and https://github.com/nrc/r4cppp/blob/master/graphs/src/rc_graph.rs as references

use std::cell::RefCell;
use std::rc::*;

fn main() {
    let node1 = Node::new(1);
    let node0 = Node::new(0);

    node0.borrow_mut().parent = Some(node1.clone());
    node1.borrow_mut().parent = Some(node0.clone());

    //works
    println!("Value of node0: {}", node0.borrow().value);

    //neither of the following work
    println!("Value of node0.parent: {}", node0.borrow().parent.as_ref().unwrap().borrow().value);
    println!("Value of node0: {}", node0.borrow().get_parent().borrow().value);
}

struct Node {
    value: i32,
    parent:  Option<Rc<RefCell<Node>>>
}

impl Node{

    fn new(val: i32) -> Rc<RefCell<Node>> {
        Rc::new(RefCell::new(Node {
            value: val,
            parent: None
        }))
    }


    fn get_parent(&self) -> Rc<RefCell<Node>> {
        self.parent.as_ref().unwrap().clone()
    }
}

I'm trying to output the value of node's parent, but I get the following compile errors:

16 |     println!("Value of node0.parent: {}", node0.borrow().parent.as_ref().unwrap().borrow().value);
   |                                           ^^^^^^^^^^^^^^ does not live long enough

and

17 |     println!("Value of node0: {}", node0.borrow().get_parent().borrow().value);
   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ does not live long enough

What am I doing wrong?

1

1 Answers

2
votes

You need to split the borrows out from the println! calls:

// Borrow them separately, so their scopes are larger.
let n0_borrowed = node0.borrow();
let n1_borrowed = node1.borrow();
let n0_parent = n0_borrowed.parent.as_ref().unwrap();
let n1_parent = n1_borrowed.parent.as_ref().unwrap();

println!("Value of node0: {}", node0.borrow().value);
println!("Value of node0.parent: {}", n0_parent.borrow().value);

println!("Value of node1: {}",node1.borrow().value);
println!("Value of node1.parent: {}", n1_parent.borrow().value);

Here it is running in the Playground.

Essentially, the borrowed references aren't living long enough when you chain all the calls together. Splitting them out increases their scope and they live longer.