The following code gives me the "Assignment to borrowed a" error. Hows the compiler able to know that? Is the compiler special casing RefCell or is there something in the language that allows it to tell the compiler you have a borrowed value?
use std::cell::RefCell;
fn main() {
let mut a = RefCell::new(A{a:5});
let mut b = a.borrow_mut();
a = RefCell::new(A{a:6});
}
Also, why does this code work which seems to be doing the exact same thing?
use std::cell::RefCell;
fn main() {
let mut a = Box::new(A{a:5});
let mut b = &mut a;
a = Box::new(A{a:6});
}
The compiler is not special casing
RefCell. Butborrow_mut()has the following signature:So it returns a
RefMutthat keeps theRefCellborrowed while it is alive (because of the'_, that according to the lifetime elision rules borrows fromself). So while it is alive, you cannot assign to theRefCellbecause it is borrowed.The reason the second case with a mutable reference works is that since mutable references don't implement
Drop(a more precise term is that they don't have a drop glue, that is, neither they implementDropnor any of their fields (which is none for mutable references) has a drop glue, recursively), the compiler shortens the borrow and drop the reference early. But it cannot do that with theRefMutfrom theRefCellbecause it implementsDrop, and thus early-dropping it would change program behavior.