#AskFedi: does anyone have a good article that explains *in depth* what Cell and RefCell are for in #Rust? So not just "this is what they do" or "this is how they work", but more questions like "why does this exist", "why would you need this", "what other approaches could have been taken and why was this one better".
(Do not send me ad-hoc explanations please; an explanation that fits into a toot is almost certainly not going to be in-depth enough here. I'm looking for articles that were written with deliberation and review.)
@raito Hmm, this seems a bit too dense/abstract for me - it seems to be *about* interior mutability, but doesn't seem to explain how eg. Rust ended on the Cell/RefCell abstractions, or exactly what the difference is with your standard mutable/immutable references.
The problem I keep running into is that everyone says "you can't mutate a thing to which you have a shared reference, for safety reasons, but if you put it in a Cell/RefCell then you can" and it is entirely unclear to me why it's suddenly okay in a Cell/RefCell and how it ensures safety in that case, and if it's so easy, why that isn't just default behaviour for references, and so on.
@joepie91 We often say that Ref/RefCell implements a dynamic borrow checker *at runtime*, as Rust wants to be ~zero cost abstraction-ish, you cannot have it as the default, it's too expensive.
@raito Okay, I think *that* is the key point I was looking for. But this still leaves the question: if there's Cell/RefCell and there's also RwLock/Mutex, which seem to exist for the same purpose, why would you be using one or the other?
Cell/RefCell: single-threaded
RwLock/Mutex: multi-threaded
RwLock/Mutex is more expensive than Cell/RefCell!
@joepie91 (note that you can reason about the Sync/Send traits to conclude this as well, they do not give rise to the same Sync/Send traits depending on whether you do Rc<RefCell<T>> or Arc<RefCell<T>>, etc. Some are non-sense, some makes sense.)
@joepie91 maybe i can really just explain it in a toot but you let me know if it's not sufficient
Ref/RefCell is a wrapper structure that switches the static borrow checking to a *dynamic* borrow checking
The reason for why you can is because Cell/RefCell is just a proxy for your reference and the borrow checker says "OK you can do that", under the hood, it uses `unsafe` to bypass safe Rust rules.
But *also*, it is still OK because it's full of dynamic checking code.