0

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?

barakugav
  • 59
  • 3
  • 3
    It's not very clear why you think the compiler thinks you are trying to set the value of the node. In the code you gave, you really are changing only `b.ptr`. – jthulhu Jan 06 '23 at 15:41
  • 6
    `let b.ptr = ...` is not valid syntax – kmdreko Jan 06 '23 at 15:43
  • 1
    Relevant shoutout: https://rust-unofficial.github.io/too-many-lists/ – cadolphs Jan 06 '23 at 15:46
  • Friendly advice: implementing your node-based data structure in Rust will be *way* easier in the long run if you use indices/ids into a single giant array/hashmap of nodes instead of `Rc`. Mutability and ownership will be way easier to reason about. – alter_igel Jan 06 '23 at 19:44

1 Answers1

0

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.

Masklinn
  • 34,759
  • 3
  • 38
  • 57