I read somewhere that immutable and mutable borrows are perhaps alternatively understood as exclusive and shared borrows.
Yes, when it comes to exterior mutability, it's basically single mutable xor multiple immutable.
The price you pay for this convenience is run-time checking of access.
The nice thing is that RefCell is not magic, it's Rust all the way down. E.g. the status of the borrow is updated by the destructors (Drop) of the reference types. All administration is done using a signed integer to do reference counting. The value 0 means 'no borrows', any positive number indicates the number of immutable borrows, -1 means one mutable borrow.
It's well worth reading the implementation of RefCell some time!
I'd like to point out that `RefCell` does contain a bit of magic, since it is based on `UnsafeCell`, which is _the_ core "primitive" of Rust that enables interior mutability:
So basically if Rust's stdlib didn't provide it, you could reimplement it yourself from scratch.
EDIT: actually, reading the comments, it looks like I'm wrong about that:
> If you have a reference `&SomeStruct`, then normally in Rust all fields of `SomeStruct` are immutable. The compiler makes optimizations based on the knowledge that `&T` is not mutably aliased or mutated, and that `&mut T` is unique. `UnsafeCell<T>` is the only core language feature to work around the restriction that `&T` may not be mutated.
This annotation let's the compiler treat their items in special ways, but it is usually for either easier way to refer to them (I want to desugar this type to a cell of what I already have) or for diagnostics. I think box is one of the few "magical" things in the language.
Sorry, I should have been clearer about that. You are completely right that at some point things have to rely on some primitives that are 'magic' (in this case UnsafeCell). But I meant that RefCell itself uses standard constructs to guarantee the 'single mutable xor multiple immutable' invariant.
Yes, when it comes to exterior mutability, it's basically single mutable xor multiple immutable.
The price you pay for this convenience is run-time checking of access.
The nice thing is that RefCell is not magic, it's Rust all the way down. E.g. the status of the borrow is updated by the destructors (Drop) of the reference types. All administration is done using a signed integer to do reference counting. The value 0 means 'no borrows', any positive number indicates the number of immutable borrows, -1 means one mutable borrow.
It's well worth reading the implementation of RefCell some time!