First of all, I apologize if this question has been asked before. The only similar problem I could find was this (but it seems different) :
Cyclic reference does not live long enough
My code is :
use std::cell::RefCell;
use std::rc::Rc;
type NodePointer = Option<Rc<RefCell<Node>>>;
#[derive(Debug)]
struct Node {
pub value : i32,
pub next : NodePointer
}
fn main() {
let mut vector = vec![None; 2];
let new_node = Rc::new(RefCell::new(Node {
value : 0,
next : None
}));
vector[1] = Some(Rc::clone(&new_node));
let new_node = Rc::new(RefCell::new(Node {
value : 0,
next : Some(Rc::clone(&new_node))
}));
vector[0] = Some(new_node);
println!("{:?}", vector);
// the following 3 lines would represent a body of the loop
let mut a = vector[0].as_ref(); // Option<&Rc<RefCell<Node>>>
let b = a.take().unwrap().borrow_mut(); // RefMut<Node>
a = b.next.as_ref(); //ERROR : borrowed value 'b' does not live long enough
println!("{:?}", vector);
}
The code below presents a short excerpt of my complete code. It is a bit weird, but variable 'a' would be used for looping over a vector (more than 2 values in complete code).
What I am trying to do is to make sure that variable 'a' is replaced with 'next' argument from vector[0] without modifying vector.
Compiler complains that 'b' does not live long enough, but I don't see why this is the case.
According to my understanding :
- vector[0] is Option<Rc<...>>
- variable 'a' is Option<&Rc<...>>
- a.take() does not modify vector[0]
- a.take() instead replaces 'a' with None
- borrow_mut() should give a reference to vector[0], but for some reason it doesn't (?) <- I think this is the problem here
- something happened to b, but I don't see what.
I am also aware that I could make use of Option::take() method instead of take_ref() (and it works in my complete code together with some additional modifications), but I would like to keep vector unmodified in-between 2 println statements
EDIT : for information, the following loop body would compile, but it modifies vector...
let mut a = vector[0].take(); // Option<&Rc<RefCell<Node>>>
let temp = a.unwrap();
let mut b = temp.borrow_mut(); // RefMut<Node>
a = b.next.take(); //ERROR : borrowed value 'b' does not live long enough
I may be wrong (still not 100% confident about the borrow checker), but I think the issue is this:
And I think it makes sense. In the first iteration, you get a
Option<&Rc<_>>
by borrowing fromvector
. But if you had aOption<&Rc<_>>
in the second iteration, where would it be borrowed from? You didn't take it fromvector
, you took it from stuff that only lived during the last iteration – it might be invalid. Or otherwise you would somehow need to ensure that all of the intermediateRefMut
s somehow lived for the duration of the loop.I don't think you can borrow something from one iteration to bring it to the next.
Instead, you should take advantage of the reference counting that you already have:
Now,
next
has typeOption<Rc<_>>
– shared ownership instead of a borrow.