0

I'm trying to write a renderer for my abstract node system.

Each node is on a circuit, which looks like:

struct Circuit<'a> {
  nodes: Vec<Node>,
  connections: Vec<Connection<'a>>,
}

Where each nodes contains some arbitrary data, and a connection connects those two nodes.

struct Connection<'a> {
  from: &'a Node,
  to: &'a Node,
}

In one instance, I'm trying to mutably iterate over Circuit.nodes and change some data, while still keeping the refences to Node inside Connections. I want the Connection references to still hold the reference to the same Node structs, but point to the updated data after the mutable borrow.

But with this setup, I get an cannot borrow 'circuit.nodes' as mutable because it is also borrowed as immutable error.

I have tried to use RefCell and a Mutex, but to no success. No resource I could find explained this problem well.

JameEnder
  • 49
  • 6
  • 1
    Please provide more context, including a minimal reproducible example and what you tried regarding `RefCell`. – PitaJ Nov 09 '22 at 00:09
  • Have you read [Why can't I store a value and a reference to that value in the same struct?](/q/32300132/2189130) – kmdreko Nov 09 '22 at 01:31
  • In your case, the easiest solution is probably to change `Connection` so that it holds the indices of the nodes in the `nodes` vector instead of holding direct references. – Jmb Nov 09 '22 at 08:10

1 Answers1

1

Maybe you want to wrap your Nodes in a Rc (or Arc if in multithreaded contexts), that way connections and the circuit can share ownership over the nodes

use std::rc::Rc;
use std::cell::RefCell;
fn main() {
    let a = Rc::new(RefCell::new(Node { data: "a".into() }));
    let b = Rc::new(RefCell::new(Node { data: "b".into() }));
    let conn = Connection {
        from: a.clone(),
        to: b.clone(),
    };
    let cir = Circuit {
        nodes: vec![a.clone(), b.clone()],
        connections: vec![conn],
    };
}

#[derive(Debug)]
struct Node {
    data: String,
}

#[derive(Debug)]
struct Circuit {
  nodes: Vec<Rc<RefCell<Node>>>,
  connections: Vec<Connection>,
}

#[derive(Debug)]
struct Connection {
  from: Rc<RefCell<Node>>,
  to: Rc<RefCell<Node>>,
}
cafce25
  • 15,907
  • 4
  • 25
  • 31
  • That actually works! Thank you so much, never would have i though about wrapping it twice like that. Is there anyway to prevent `.borrow()` everywhere in my code, or is it something i need to live with? – JameEnder Nov 09 '22 at 12:51
  • Yea you'll often see `Rc/Arc` and `RefCell/Mutex` used in combination to allow for shared mutable access. As for getting rid of `.borrow()`, only if you don't need mutable access to the `Node`s in that case you could drop all the `RefCell`s – cafce25 Nov 09 '22 at 21:16