I think you are digging too deep. Actual formal, rules are actually too complex for many to know (and even ones who know them only apply them occasionally, because it's so tedious… most of the time they leave to the compiler the nuiances and only have to think about all the fine details when they use unsafe
).
This makes this:
Quite obvious. Yes, you often need or want mutability and Rust gives it to you (but then, Haskell can do that, too), but it's more of a freebee: since you are the only one who touches that variable right now you may play with it freely, just be quiet, Ok?.
Even exception with !Unpin
into that category: yes, formally there are two references, we know most of them are harmless (they are inside refences), but since our language model is too primitive to express it we relax &mut
into &mut
. And similar thing happens when people implement complex data structures manually with unsafe
.
You couldn't summarise the whole language reference into one slogan (if that were possible then why would we need that reference) but we can define goals.
And Haskell goal is to make sure there are no mutable state at all (but it gives you anyway if you really need it) while Rust goal is to make sure there are unique borrower for every mutable variable.
Neither achieve their stated goals perfectly and neither makes an ideal (“no shared mutable state ever”), but that's Ok.
If you think about it that 99% of computer use is to manage some kind of shared mutable state (e.g. URLO exist to share various thought with members of URLO and other observers on the internet, banking computer system goal is to keep shared mutable eventually consistent information about our finances and so on).
But because shared mutable state is hard, really hard, always hard… it makes reasoning about your code complex… eventually developers realise that to write realiable code it's good idea to reduce that complexity as much as possible.
You can not remove shared mutable state from the language completely (because then said language would immediately become quite useless for many practical tasks), but you may try to control it.
Haskell and Rust pick radically different roads to the desired goal, it's obvious. But it would be nice if it were possible to actually explan the difference. “Rust cares about uniquiness and not about mutability”.
That's why Rust stopped using unique references with closures: simple observation solved the issue: you don't really need unique references ever. If you arrive at point where you actually need it (like with closures) you can just add one star! And capture &*something
instead of &something
.
Of course it, simultaneously, added exception for the generators, but, again, an attempt was made to stay without the existing range of types: &x
, &mut x
, *mut x
. And it's kinda obvious that difference between &mut x
and *mut x
is uniqueness, not mutability.
Thus I have to “agree”:
Yes, that's post is from 2014, it's outdated, but it aged extremely well: today it's even more correct then when it was written.
We no longer use unique references (even implicit ones for closures) and while &mut x
turns into *mut x
for generators it happens to reduce number of distinct concepts, not because it's, somehow, the best solution.
It's just one of the bad solutions picked as an answer for the problem which have no good solutions.