Inline scopes on RefCell?

It panics with already borrowed with following code:

use std::cell::RefCell;

fn main() {
    let c = RefCell::new(5);

    let mut p = c.borrow_mut();
    *p += 2;

    let mut p = c.borrow_mut();
    *p += 2;

    assert_eq!(*c.borrow(), 9);
}

But works with:

use std::cell::RefCell;

fn main() {
    let c = RefCell::new(5);
    *c.borrow_mut() += 2;
    *c.borrow_mut() += 2;
    assert_eq!(*c.borrow(), 9);
}

What's the differences behind the scene?

In the first example, you save the exclusive reference in the variable p and as long as that variable exists with the reference to the contents of c, you cannot borrow it again. In the second example, the reference is dropped right after the addition, enabling you to borrow at the end without error.

1 Like

The difference is when the destructor of the return value of borrow_mut() is executed. In the first case, both destructors happen at the end of the function when the let binding goes out of scope, but in the latter solution, it happens on the same line, before the next call to borrow_mut().

Is this a mechanism of Rust, any doc on it? Or it is an old thing existing already in like C/C++?

It is a mechanism of any language with RAII. You can read more here.

1 Like

You can force the references to be dropped earlier by putting them into separate scopes. So this version works:

use std::cell::RefCell;

fn main() {
    let c = RefCell::new(5);

    {
        let mut p = c.borrow_mut();
        *p += 2;
    }

    {
        let mut p = c.borrow_mut();
        *p += 2;
    }

    assert_eq!(*c.borrow(), 9);
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.