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 :
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:
// b borrows from a
let b = a.take().unwrap().borrow_mut();
// now, a borrows from b
// note that the lifetime of `a` doesn't magically change just because you're not using the original value anymore
// so from the type checker's perspective, a and b borrow from each other at the same time – not allowed
a = b.next.as_ref();
// btw, if you replace `a =` with `let c =` or even `let a =`, creating a new variable with a new lifetime, it compiles
// let a = b.next.as_ref();
// but doesn't work for us since you want to put it in a loop
And I think it makes sense. In the first iteration, you get a Option<&Rc<_>>
by borrowing from vector
. But if you had a Option<&Rc<_>>
in the second iteration, where would it be borrowed from? You didn't take it from vector
, 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 intermediate RefMut
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:
let mut next = vector[0].clone();
while let Some(node) = next {
next = node.borrow_mut().next.clone();
}
Now, next
has type Option<Rc<_>>
– shared ownership instead of a borrow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With