Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between Rc<RefCell<T>> and RefCell<Rc<T>>?

The Rust documentation covers Rc<RefCell<T>> pretty extensively but doesn't go into RefCell<Rc<T>>, which I am now encountering.

Do these effectively give the same result? Is there an important difference between them?

like image 785
Gman man Avatar asked Aug 05 '19 23:08

Gman man


People also ask

What is RefCell t Rust?

RefCell<T> represents the single ownership over the data that it holds. If we use RefCell<T>, then the invariants are enforced at the runtime. RefCell<T> is mainly used in the single-threaded scenario and will give an error if we use in a multithreaded case. RefCell<T> checks the mutable borrows at the runtime.

What is RC in Rust?

To enable multiple ownership, Rust has a type called Rc<T> . Its name is an abbreviation for reference counting, which keeps track of the number of references to a value to know whether or not a value is still in use.

Is RC mutable Rust?

Shared references in Rust disallow mutation by default, and Rc is no exception: you cannot generally obtain a mutable reference to something inside an Rc . If you need mutability, put a Cell or RefCell inside the Rc ; see an example of mutability inside an Rc.

Is RefCell send?

To get shared ownership (implying cheap Clone ) plus mutability in a multi-threaded context, you need Arc<Mutex<U>> . Note that Mutex<U> also cannot be Send unless U is. In fact, RefCell<T> is Send , at least when T: Send .


1 Answers

Do these effectively give the same result?

They are very different.

Rc is a pointer with shared ownership while RefCell provides interior mutability. The order in which they are composed makes a big difference to how they can be used.

Usually, you compose them as Rc<RefCell<T>>; the whole thing is shared and each shared owner gets to mutate the contents. The effect of mutating the contents will be seen by all of the shared owners of the outer Rc because the inner data is shared.

You can't share a RefCell<Rc<T>> except by reference, so this configuration is more limited in how it can be used. In order to mutate the inner data, you would need to mutably borrow from the outer RefCell, but then you'd have access to an immutable Rc. The only way to mutate it would be to replace it with a completely different Rc. For example:

let a = Rc::new(1);
let b = Rc::new(2);

let c = RefCell::new(Rc::clone(&a));
let d = RefCell::new(Rc::clone(&a));

*d.borrow_mut() = Rc::clone(&b); // this doesn't affect c

There is no way to mutate the values in a and b. This seems far less useful than Rc<RefCell<T>>.

like image 121
Peter Hall Avatar answered Sep 25 '22 20:09

Peter Hall