I was playing around with creating references and I ended up having this:
let mut z: &mut i32 = &mut 42;
but also the following that compiles
let &mut z: &mut i32 = &mut 42;
I was not actually aware that I could have the let &mut z form, as must of the occurrences I have seen has always been let mut z: which I interpret to mean, make it possible for z, to hand out mutable reference.
Variable declarations are patterns, not just names with an optional mut marker. In this case, the &mut in let &mut z "unwraps" the &mut of the type and of the value on the right:
let &mut z:
&mut i32 =
&mut 42
and z ends up being an i32 with a copy of the value 42 stored in it.
And it's somewhat tangential, but I'll mention that while &mut T is a distinct type compared to T or &T, the mut marker in a binding (let mut z = ...) doesn't change the type, it just changes whether or not you can overwrite or create a mutable reference to the variable.
It's an aid to avoid mutating things you don't mean to, but you could always assign the value to a new variable with a mutable binding, so adding or not adding mut doesn't change anything inherent to the type or value. It's just a property of the binding.
For example you can do:
let z = 13;
let mut z = z;
println!("{z}");
z = 42;
let z = z;
println!("{z}");
The mut in let mut z is the mutable binding marker, and doesn't "unwrap" anything on the right. It's not a part of any types. It's not &mut in particular.
You could rewrite the snippet like so.
let z: &mut i32 = &mut 42;
let mut z = z;
dbg!(z);
Variable declarations are patterns, not just names with an optional mut marker. In this case, the &mut in let &mut z "unwraps" the &mut of the type and of the value on the right:
When are variable declarations patterns? Like in the case of let &mut z: and when are they not patterns? As in the case let mut z, where the mut is just a mutable binding marker, and doesn't "unwrap" anything
Well, variable declarations are always patterns. Really you're asking the very sensible question, when is mut just a marker?
mut is just a marker when it does not follow & or ref. It is also followed by the name of the variable you're binding. More generally, the mut marker is part of an identifier pattern.
This does actually lead to ambiguity in some places. For example, how can you write a single pattern for this?
let &x = &42; // x is an i32
let mut x = x;
This won't work -- it tries to match against a &mut i32 on the right.
let & mut x = &42;
This works... but I don't think I've ever seen such a declaration in real code and don't really recommend it.