I'm trying to create a chain of struct instances, like this:
Struct_instance_a:
id:1
prev:None
Struct_instance_b:
id:2
prev:Struct_instance_a
etc..
But getting this error from the compiler:
error[E0382]: borrow of moved value: `a`
error[E0382]: borrow of moved value: `a`
--> src/main.rs:31:9
|
28 | let a = crate::Node::new(None, 1);
| - move occurs because `a` has type `Node`, which does not implement the `Copy` trait
29 | let b=crate::Node::new(Some(a), 2);
| - value moved here
30 |
31 | assert_eq!(a.id, b.prev.unwrap().id);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
This is my code snippet:
fn main() {
println!("hello");
}
pub struct Node {
prev: Option<Box<Node>>,
id: u64,
}
impl Node {
fn new(prev: Option<Node>, id:u64) -> Node {
Node {
prev: match prev {
None => None,
Some(prev) => Some(Box::new(prev))
},
id
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_children() {
let a = crate::Node::new(None, 1);
let b = crate::Node::new(Some(a), 2);
assert_eq!(a.id, b.prev.unwrap().id);
}
}
I'm new to Rust and trying to understand why this doesn't work. So far I've read about ownership and borrowing and lifetimes and tried a few combinations of those. It feels like I'm close to the solution but missing some fundamental piece of knowledge yet.
When you do
Node::new(some(a), 2), then a is no longer accessible, it's ownership now belongs tob.That's why, when you later do
a.idit saysvalue borrowed here after move, you moved the ownership tob, therefore you can't doa.id. The only way to accessais throughb.prev.unwrap()(which is what you did.If you want for the Node
ato be accessible from bothaandb.prevthere's many ways to do that.One of the ways involve not moving the value at all (so
bnever has ownership ofato begin with). This can be done with references:This introduces lifetime annotations, which might not be what you want. In that case, you can use the
RCstruct, which is a smart pointer that allows a value to have multiple owners at the cost of some run-time checks:Note that for this to work we are doing
a.clone(). This clones the RC pointer, it doesn't clone the node. So now there exists 2 pointers (aandb.prev) but only 1 (excludingbitself) Node.One of the disadvantages of RC is that now the value inside is immutable. If you need to mutate the nodes, they would have to be
Rc<RefCell<Node>>instead ofRc<Node>.RefCellis another smart pointer, just likeRc. WhereRcallows a value to have multiple owners,RefCellallows to obtain a mutable reference (via run-time checks) to the inner object even if theRefCellitself is not mutable. By combiningRcandRefCellyou can have multiple owners that can mutate the value.