It's common to hear people refer to &T and &mut T not as "mutable" or "immutable" but "shared" versus "unique". What probably muddles this is that the `mut` keyword _also_ is used for declaring things mutable or immutable, just at the binding level rather than the type level. These are related due to the fact that you can't take a `&mut` reference to a binding that isn't declared as `mut`, which probably also muddles the water a bit.
IIRC under the current current Rust-to-LLVM compilation rules, &mut T is noalias (because it's exclusive), and &T is noalias or readonly or something (because all other &T are immutable) unless T contains an UnsafeCell. It actually took many years to get &mut T to be noalias without exposing LLVM bugs resulting in miscompiled Rust (which went undiscovered because Rust is the first LLVM language to use noalias so heavily).
And noalias and pointer aliasing is a huge mess, with crates like owning_ref and Tokio's intrusive linked lists and Pin<Box<T>> being unsound under the proposed Stacked Borrows rules. And I just found a LLVM codegen soundness issue: https://github.com/rust-lang/rust/issues/63787.
to be pedantic &mut is still a borrow not ownership, as another simplification the difference is that &mut can modify a value but must keep the borrowed value in a valid state, while full ownership can destroy a value
Agreed! I also like that declaring a mutable binding is extra code beyond a regular binding rather than something the same (or shorter). At least for me, making things immutable by default and then only relaxing it when necessary leads to code that tends to be less buggy, and I suspect this might be true for others as well.