Rust Variables, Mutability, and Shadowing
Bindings are immutable by default; mut and shadowing change that.
On this page
Rust basics.
- Bindings are immutable by default; mut and shadowing change that.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
In Rust a let binding cannot be reassigned unless it is declared mut. Starting from immutable removes a whole class of accidental changes, and the compiler enforces it.
Shadowing declares a new binding with the same name using let again. It can even change the type, and the new binding is itself immutable. Here count is first changed in place to 3, and then a new count is created as 3 * 10.
Code example
fn main() {
let mut count = 1;
count += 2;
let count = count * 10;
println!("{}", count);
}30
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
fn main() { let mut count = 1; count += 2; let count = count * 10; println!("{}", count);}Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| A mutable binding starting at 1. | count = 1 | — | |
| Mutate it in place. | count = 3 | — | |
| Shadow it with a new immutable binding. | count = 30 | — | |
| Print the latest binding. | count = 30 | 30 |
Behind the scenes
How Rust processes this code
Rust checks types and ownership at compile time, then builds a native executable.
Cost and common mistakes
O(1) time and space.
- Removing mut from the first line makes count += 2 a compile error.
- Shadowing creates a new variable; it is not the same as mutating the old one.
Try it yourself
Predict the output if the last arithmetic line were let count = count + 1;
Reveal answer and reasoning
count is 3 before it, so the new binding is 4 and it prints 4.