mut
is a keyword in Rust that has a few very distinct functionalities; mainly 2 you’ve come across so far. The one it has in
let mut x: Box<i32> = Box::new(1);
is marking the mutability of a local variable. This is something that has no effect on the type of the variable x
.
It does control whether (ordinary) mutation can happen to the variable x
(and everything that it owns): essentially re-assigning or taking a mutable reference to x
will be prohibited without that mut
. Some people just consider this kind of feature more of a very strong kind of “lint”, by the way. It doesn’t make the Box
itself somehow different. In fact, if you have
let x: Box<i32> = Box::new(1);
you can just go on and still do
let mut y = x;
// now, mutate *y
i.e. move ownership off to another, now mutable variable, then mutate the box.
On the other hand, the keyword mut
is also used in the types of references. There is the type &mut T
of “mutable exclusive references to T
” and &T
or “immutable shared references to T
”. These are simply completely distinct types.
Now in your pseudo-code
let x: mut Box<i32> = Box::new(1);
you tried to put a mut
into a type involving Box
, however mutability is never part of types; except that it’s a keyword used in the name of the &mut T
type. It doesn’t make sense where you put it. [Neither would e.g. Box<mut i32>
or so make any sense.]
The simple answer is: support for annotating mutability of local variables is limited to the level of annotating the whole variable. That’s all Rust supports.
(Fun fact, temporary variables, i.e. the places where intermediate results from computations are stored, are always mutable. Hence, e.g. something like vec![1].push(2)
compiles fine, though it’s somewhat of a useless example, because it modifies the Vec
in a temporary variable, which is then necessarily immediately dropped before it could ever be used for anything else again.)