rustinterior-mutability

"Unwrapping" Rc<RefCell<T>> in the proper way


I have a Rust data structure that I will have to pass around and manipulate from various places in my code. To my understanding the most simple and default way to do this is to wrap everything in Rc for the reference counting and a RefCell for interior mutability. I at least think that I have basic understanding of both structs and came up with the following approach:

use std::rc::Rc;
use std::cell::RefCell;

//  Some central data structure I would have to pass around and would like to manipulate from
//  different locations in my code.
struct MyState {
    data: i32 //  Some data
}

//  Just an example method that will mutate my sample state.
impl MyState {
    fn modify_state(&mut self, data: i32) {
        self.data += data;
    }
}

//  To be able to pass the structure around, I put it in a RefCell for interior mutability and Rc
//  for the ref counting. For convenience I wrap everything in a new type.
#[derive(Clone)]
struct MyStateRef(Rc<RefCell<MyState>>);

impl MyStateRef {
    fn new() -> Self {
        MyStateRef(Rc::new(RefCell::new(MyState{data: 0})))
    }
}

fn main() {
    //  Create an instance of MyState wrapped in Rc and RefCell
    let state = MyStateRef::new();

    //  "state" could now be cloned and passed around. At some point I would like to modify the
    //  internal MyState by calling modify_state.
    state.0 [...???...] .modify_state(3);
}

I'm not able to make the last line in the main function work. I tried various combinations of borrow_mut, get_mut, ... but just failed. I think that there is some Deref and DerefMut involved that is confusing me, but I cannot wrap my head around it.

Can somebody make the the last line work and explain why it is working?


Solution

  • borrow_mut is your friend:

        state.0.borrow_mut().modify_state(3);