Talking about “escape hatches” leaves me with a bad aftertaste. It has the connotation that Rust’s rules are badly designed and unreasonably restrictive, and so it also needs to have unprincipled workarounds to let you get out from under its own rules. Neither is true. Rust’s rules are very sensible, and the various types with so-called “interior mutability” work harmoniously with the rules, not against them.
We spent years confusing ourselves with the seductive, but false, notion that
& are fundamentally about mutability versus immutability. Now that we’ve learned through hard experience that this is not true, we should consider the possibility of not spreading the same confusion among newcomers to the language. The fundamental characteristic of
&, from which everything else flows, is that they provide exclusive and shared access, respectively, while ensuring safety. Turns out that if you have exclusive access to an object, it is always safe to mutate it (hence the name:
&mut). While if you only have shared access, in the general case, it is not - so access through a shared reference will usually be immutable. But some particular types can guarantee the safety of mutation even through shared access.
Atomic* can provide safe, shallow mutation, for the single- and multi-threaded case, respectively; and
Mutex use runtime checks to guarantee exclusive access, and can therefore translate shared
& to exclusive
&mut references for “deep” mutation, for the single- and multi-threaded cases, respectively.
The rules for other things, such as
Rc only providing shared references to the contained object, because shared ownership is inherently, well, shared (except if you can show that the reference count is 1!), also all naturally fall out of this framework.