3 ms·
They're not quite that independent, because the choice of memory management strategy relies on the aliasing rules. But (as the post argues) the aliasing rules d
by Rusky 2y ago
They're not quite that independent, because the choice of memory management strategy relies on the aliasing rules. But (as the post argues) the aliasing rules don't rely on the memory management strategy.
The guarantee that &mut is unique enables mutations to change the "shape" of an object in memory- e.g. reallocating a Vec to grow it, or overwriting a Box with a new one and freeing the original, or overwriting an enum/union in-place with a different variant.
If &mut were not restricted in this way, then this "eager" memory re-use could cause other references, into the interior of the shape, to dangle. But this is how Rust manages memory- if there may be other references to the old memory, when is it safe to free it, and reuse it with a potentially different type? Lifetimes don't help you here, unless you make them powerful enough to re-encode the same old aliasing rules!
It's important to note that this is not only about heap allocations. The enum/union case, for example, is entirely in-place in Rust. So even if you switch to an arena or type-segregating allocator, and accept that the old references might point to stale or now-unrelated values, you still haven't recovered memory safety. You need to keep the old value, with its old type, in place in memory simultaneously.
GC provides memory safety by making it practical to forbid these kinds of memory layouts to begin with- the program cannot eagerly free an old backing array or heap object, nor can it overwrite an enum in-place. Instead it can only mutate the references themselves, leaving the old value alone for any other references that may still exist.
There is a middle ground, where a language could allow shared mutability with more compact memory layouts, but it requires a different set of restrictions: like GC, no references to array elements or Box/enum/union fields; without a GC, working with these values requires deep copying them. Languages like Java already do this, but only for primitive types where the copy can be atomic. (Or you could use something GC-like, such as reference counting and/or copy-on-write.)
The point of the post is that the Rust approach to memory management is not the only thing that the aliasing rules gives you, because they also aid in local reasoning about your programs, regardless of your approach to memory layout and allocation.
- mmaniac 2y agoAh right. That confirms my suspicion then that relaxing &mut would make lifetimes unsound.