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);
}
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.
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().
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);
}