Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cyclic reference does not live long enough

Tags:

rust

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?

like image 462
Newtang Avatar asked Oct 20 '25 15:10

Newtang


1 Answers

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.

like image 175
Simon Whitehead Avatar answered Oct 22 '25 04:10

Simon Whitehead



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!