Even though Rust provides its Rust book, I struggled with understanding the
mut keyword. I asked myself, "Am I the only one who has this problem?" A quick Google search confirmed that I was not alone.
As a result, I decided to write this article to provide a detailed explanation of the
To create an unmuttable variable in Rust, simply write
let x = 1337. It's straightforward. If you want to create a variable that can be mutated later, just add the
mut keyword after
let. Rust has a helpful convention that encourages clarity of intentions.
mut keyword informs others that this variable will be modified somewhere else in the code. Okay.
Let's visualize it. Two variables here,
let mut x = 1337 and
let y = 42.
At the moment, everything is straightforward. However, things start to get a little curly when using
mut references. Let's create some.
let mut x = 1337; let y = 42; let x_ref = &mut x; let y_ref = &y;
I created two references (or "borrowed" in terms of Rust). One of them is a mutable reference, and the other is a read-only reference. Let's create a scheme for that again.
In the given scheme, I have 4 variables, 2 of which are references. Both reference variables are immutable and do not have the
mut keyword after
let, which means I cannot change what they point to. However, I can still change the value they reference.
*x_ref = 777;
If you write this, the Rust compiler will not complain, and the value of
x (not the ref itself) will change to
777. However, there's a red square on the scheme indicating that
x_ref lacks the mutability option. So, why can I change the value it refers to?
Let’s come back to the scheme for the
let x_ref = &mut x.
The first white block contains the name:
x_ref. The second one informs me about the type stored in that variable. In its complete form, without any implicit type annotations, I can write as follows:
let x_ref: &mut i32 = &mut x;
I can interpret this as: let's create an immutable variable named
x_ref that will hold a mutable reference to
i32 and initialize it immediately with the mutable reference to the
i32 value in the
This means I can modify the value it points to, but I cannot alter the reference's value (or address). In other words, I can't write something like:
let x_ref: &mut i32 = &mut x; let mut z = 0; x_ref = &mut z; // Not allowed!
In terms of the schemes, I want to change the direction the arrow is pointing to in the code block above. However, even if the
z variable is mutable, I can't change the arrow because the problem lies in the immutability of the
To change the arrow direction, I need to modify the address stored in the
x_ref variable. However, I cannot do this as the variable is immutable.
Let’s do it!
let mut x: i32 = 1337; let mut x_ref: &mut i32 = &mut x; // I've added mut before x_ref let mut z = 0; x_ref = &mut z; // Allowed!
There are too many instances of
mut here around
x_ref, right? Let's describe them.
let mut x_ref: I am creating a mutable variable named
x_ref, which means I can change its value later.
&mut i32: I am stating that the variable will contain mutable reference(s) to some value of type
&mut x: I am borrowing (getting a reference to) the variable
Then, I created a variable named
z and assigned it the value of
0. Afterward, when I wrote
x_ref = &mut z, I indicated that I understand
x_ref to be a mutable variable that can only hold references to
Since the type of
i32, I am able to assign its address to the
x_ref variable. To obtain the address of
z, I used the
&mut z syntax.
The Mental Trick
Take a look at
= in the statement, it may look a little bit obvious, but…
let mut x_ref = &mut x;
… I see it as a divider (especially if you rotate it by 90 degrees) that splits the statement into two sub-statements: left and right. The left side provides information about the variable itself, while the right side tells us about the value.
When I use the
* dereference operator to change the value...
*x_ref = 100;
... I do not change the value of the
x_ref variable. Instead, I am changing the value that
x_ref is referencing.
mut frequently before. What if I omit some of them?
let i = 1; let j = 2; let mut k = &i;
Can I change the value of
i here? Using the divider technique, it's quite simple to answer. I can change the value of
k (I see
mut on the left side), but the value (right side) is an immutable reference to
i (there is no
let i = 1; let j = 2; let mut k = &i; k = &j; // This is legal. *k = 3; // This is not.
In this article, we've dissected the nuances of the
mut keyword and references. Remember, there's a distinction between a mutable reference and a mutable variable holding a reference. Our trick?
= sign as a mental divider to better understand assignments in Rust. This simple visualization can clear up many confusions.