THE QUESTION
When are RefCell counted down?
THE CASE
// Working
use std::cell::RefCell;
fn main() {
let username = RefCell::new("");
*username.borrow_mut() = "Genese";
*username.borrow_mut() = "Salathiel";
println!("{}", username.borrow()); // Salatthiel
}
Then…
// !working
use std::cell::RefCell;
fn main() {
let username = RefCell::new("");
let mut username_mutable_borrow = username.borrow_mut();
*username_mutable_borrow = "Genese";
let mut username_mutable_borrow = username.borrow_mut();
*username_mutable_borrow = "Salathiel";
println!("{}", username.borrow());
}
// thread 'main' panicked at 'already borrowed: BorrowMutError', src/main.rs:7:48
I did other experiments with std::ops::Deref without much success or insights.
>Solution :
RefCell::borrow_mut() returns a RefMut. If this RefMut is stored in a variable, it lives til the end of the containing scope. This is the reason for the panic in your second example – both username_mutable_borrows live until the end of the scope, so they’re colliding.
However, in the first example, you don’t store the RefMuts in variables. They are temporaries. The scope of temporaries is the smallest scope of the following:
- The entire function body.
- A statement.
- The body of a
if,whileorloopexpression. - The
elseblock of anifexpression. - The condition expression of an
iforwhileexpression, or amatchguard. - The expression for a match arm.
- The second operand of a lazy boolean expression.
The smallest applicable scope here is the containing statement, and so they live only until the end of it. Therefore they do not collide.