Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding usage of Rc<RefCell<SomeStruct>> in Rust

Tags:

rust

I'm looking at some code that uses

Rc<RefCell<SomeStruct>>

So I went out to read about the differentes between Rc and RefCell:

Here is a recap of the reasons to choose Box, Rc, or RefCell:

Rc enables multiple owners of the same data; Box and RefCell have single owners.

Box allows immutable or mutable borrows checked at compile time; Rc allows only immutable borrows checked at compile time;

RefCell allows immutable or mutable borrows checked at runtime. Because RefCell allows mutable borrows checked at runtime, you can mutate the value inside the RefCell even when the RefCell is immutable.

So, Rc makes sure that SomeStruct is accessible by many people at the same time. But how do I access? I only see the get_mut method, which returns a mutable reference. But the text explained that "Rc allows only immutable borrows".

If it's possible to access Rc's object in mut and not mut way, why a RefCell is needed?

like image 904
Guerlando OCs Avatar asked May 25 '20 07:05

Guerlando OCs


People also ask

How does RefCell work?

The RefCell<T> keeps track of how many Ref<T> and RefMut<T> smart pointers are currently active. Every time we call borrow , the RefCell<T> increases its count of how many immutable borrows are active. When a Ref<T> value goes out of scope, the count of immutable borrows goes down by one.

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 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 .

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.


1 Answers

So, Rc makes sure that SomeStruct is accessible by many people at the same time. But how do I access?

By dereferencing. If you have a variable x of type Rc<...>, you can access the inner value using *x. In many cases this happens implicitly; for example you can call methods on x simply with x.method(...).

I only see the get_mut method, which returns a mutable reference. But the text explained that "Rc allows only immutable borrows".

The get_mut() method is probably more recent than the explanation stating that Rc only allows immutable borrows. Moreover, it only returns a mutable borrow if there currently is only a single owner of the inner value, i.e. if you currently wouldn't need Rc in the first place. As soon as there are multiple owners, get_mut() will return None.

If it's possible to access Rc's object in mut and not mut way, why a RefCell is needed?

RefCell will allow you to get mutable access even when multiple owners exist, and even if you only hold a shared reference to the RefCell. It will dynamically check at runtime that only a single mutable reference exists at any given time, and it will panic if you request a second, concurrent one (or return and error for the try_borrow methods, respecitvely). This functionality is not offered by Rc.

So in summary, Rc gives you shared ownership. The innervalue has multiple owners, and reference counting makes sure the data stays alive as long as at least one owner still holds onto it. This is useful if your data doesn't have a clear single owner. RefCell gives you interior mutability, i.e. you can borrow the inner value dynamically at runtime, and modify it even with a shared reference. The combination Rc<RefCell<...>> gives you the combination of both – a value with multiple owners that can be borrowed mutably by any one of the owners.

For further details, you can read the relevant chapters of the Rust book:

  • Rc<T>, the Reference Counted Smart Pointer
  • RefCell<T> and the Interior Mutability Pattern
like image 105
Sven Marnach Avatar answered Nov 03 '22 09:11

Sven Marnach