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
RefMut
that keeps theRefCell
borrowed 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 theRefCell
because 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 implementDrop
nor 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 theRefMut
from theRefCell
because it implementsDrop
, and thus early-dropping it would change program behavior.