How to a assign a new value to an Rc in Rust

891 Views Asked by At

Im building a data structure containing nodes, and each node might point to another. The pointers between the nodes are implemented using Rc, something like this:

struct Node {
    ptr: Rc<Node>
}

I would like to be able to change the pointer 'ptr' of a node to point to another node, by cloning another existing Rc.

let a: Rc<Node> = ...;
let mut b: Node = ...;
let b.ptr = a.clone();

My problem is, the compiler think I am trying to set the value of the node, namely changing the underlying shared object of b.ptr, where I realy want to replace the pointer: reduce the refcount of the old value of b.ptr, increase the refcount of a, and change b.ptr to point to a.

I managed to do it with Cell<Rc>, but I seems too vebose and unnecessary.

How can I do that?

1

There are 1 best solutions below

0
Masklinn On

My problem is, the compiler think I am trying to set the value of the node, namely changing the underlying shared object of b.ptr

That's rather unlikely given the code you posted, and with code which is incomplete, separately broken, and without the error message, it's difficult to diagnose. Even Shepmaster has yet to achieve psychic powers letting him know information not provided.

Fixing the obviously missing or incorrect I get something like:

use std::rc::Rc;
struct Node {
    ptr: Option<Rc<Node>>,
}
fn main() {
    let a = Rc::new(Node { ptr: None });
    let b = Node { ptr: None };
    b.ptr = a.clone().into();
}

and the error message is completely clear:

error[E0594]: cannot assign to `b.ptr`, as `b` is not declared as mutable
 --> src/main.rs:8:5
  |
7 |     let b = Node { ptr: None };
  |         - help: consider changing this to be mutable: `mut b`
8 |     b.ptr = a.clone().into();
  |     ^^^^^ cannot assign

this is fixed by simply declaring b as mutable as the compiler suggests[0]:

use std::rc::Rc;
struct Node {
    ptr: Option<Rc<Node>>,
}
fn main() {
    let a = Rc::new(Node { ptr: None });
    let mut b = Node { ptr: None };
    b.ptr = a.clone().into();
}

[0]: not that it's always right, far from it, but in this case its suggestion is fine.