Rust Variables and Mutability
A variable is a named storage location in memory. You give it a name, store a value in it, and use that name later to read or change the value. Rust handles variables differently from most languages — by default, all variables are immutable, meaning you cannot change them after you set them.
Creating a Variable with let
Use the let keyword to create a variable:
fn main() {
let age = 25;
println!("My age is {}.", age);
}
Output:
My age is 25.
The variable age now holds the value 25. Rust figures out the type (integer) automatically — you do not have to write it yourself in simple cases.
Variables Are Immutable by Default
If you try to change the value of a variable after you create it, Rust refuses to compile:
fn main() {
let age = 25;
age = 30; ← This causes a compiler error
}
The compiler shows this error:
error[E0384]: cannot assign twice to immutable variable `age`
Why Immutability by Default?
When a value cannot change, you can trust that it stays the same throughout your program. This prevents bugs where one part of your code accidentally changes a value another part depends on.
The Locked Box Diagram
let age = 25; [ age ] = [ 25 ] ← Box is sealed. You can read it but not change it. age = 30; ← Compiler: "This box is locked. You cannot put 30 in it."
Making a Variable Mutable with mut
When you do need to change a variable, add the mut keyword:
fn main() {
let mut score = 0;
println!("Score: {}", score);
score = 10;
println!("Score after update: {}", score);
}
Output:
Score: 0 Score after update: 10
mut tells Rust this variable's value will change. Now the compiler allows reassignment.
The Unlocked Box Diagram
let mut score = 0; [ score ] = [ 0 ] ← Box is open. You can put a new value in. score = 10; → [ score ] = [ 10 ] ← Value updated successfully.
Constants
A constant is a value that never changes and is known before the program runs. Use the const keyword to create one. Constants must always have a type written explicitly, and their names are written in ALL_CAPS by convention.
const MAX_SCORE: u32 = 100;
fn main() {
println!("Maximum score is {}.", MAX_SCORE);
}
Difference Between let and const
Feature let const --------- ------ ------ Can be mutable Yes (add mut) No — always fixed Type annotation Optional Required Computed at Runtime Compile time Naming style snake_case UPPER_SNAKE_CASE Scope Inside functions Anywhere in program
Shadowing
Shadowing lets you create a new variable with the same name as an existing one. The new variable "shadows" the old one — inside the current block, the old value is hidden.
fn main() {
let number = 5;
let number = number + 1; ← New variable also named "number"
let number = number * 2; ← Another new variable named "number"
println!("The number is {}.", number);
}
Output:
The number is 12.
Each let number = creates a fresh variable. The old one disappears from view.
Shadowing vs Mutability
Shadowing looks similar to mutability but works differently. With shadowing, you can change the type of the value. With mut, the type must stay the same.
let spaces = " "; ← spaces is a text value let spaces = spaces.len(); ← spaces is now a number (shadowed) let mut spaces = " "; spaces = spaces.len(); ← Compiler error: type mismatch
The Name Tag Diagram
First: [ number ] → [ 5 ] Second: [ number ] → [ 6 ] (old tag hidden, new tag with same name) Third: [ number ] → [ 12 ] (hidden again)
Variable Naming Rules
Rust variable names follow these rules:
- Start with a letter or underscore
- Contain only letters, numbers, and underscores
- Use
snake_casestyle — all lowercase with underscores between words - Reserved keywords like
fn,let, andmutcannot be used as names
let user_age = 30; ← Good: snake_case let userAge = 30; ← Works but not Rust style let 2fast = 10; ← Bad: starts with a number let fn = 5; ← Bad: fn is a reserved keyword
Unused Variable Warning
Rust warns you when you create a variable but never use it. This helps catch typos and dead code.
fn main() {
let name = "Alex"; ← Warning: unused variable `name`
}
To silence the warning on purpose, start the name with an underscore:
let _name = "Alex"; ← No warning
Quick Reference
let x = 5; ← Immutable variable let mut x = 5; ← Mutable variable const MAX: u32 = 100; ← Constant let x = x + 1; ← Shadowing (new x hides old x)
