Lesson 3 of 22
Lesson Progress: 0%
In Rust, variables are immutable by default — once a value is bound to a name, it cannot be changed. You create a variable with the let keyword, and the compiler guarantees that the value stays the same throughout its lifetime. Immutability is a key safety feature: it prevents accidental modifications and makes code easier to reason about. If you need a new value, you can use shadowing, which creates a fresh variable that hides the previous one. Shadowing lets you reuse a variable name while keeping each binding immutable. This lesson explores how immutable variables work in Rust through simple examples.
fn main() {
let x = 5;
println!("{}", x);
}Instructions
▼ ← Click the triangle to hide or reveal instructions.Task Incomplete
Editor Input:
Editor Output:
let x = 5; creates a new variable named x and binds it to the value 5.x will always hold 5.x as i32 (a 32-bit integer) automatically.println!("{}", x); prints the value of x, which is 5.x = 10; later would cause a compiler error.fn main() {
let a = 10;
let b = 20;
println!("{}", a + b);
}Instructions
▼ ← Click the triangle to hide or reveal instructions.Task Incomplete
Editor Input:
Editor Output:
a holds 10 and b holds 20.a + b to compute new values.a + b produces 30, which is passed to println!.a and bkeep their original values — immutability means nothing changes.fn main() {
let msg = "Hi";
println!("{}", msg);
}Instructions
▼ ← Click the triangle to hide or reveal instructions.Task Incomplete
Editor Input:
Editor Output:
let msg = "Hi"; stores a string literal.msg as &str (a string slice) automatically.msg is immutable, it will always contain "Hi".msg with println! displays Hi on the screen.fn main() {
let x = 5;
let x = x + 1;
println!("{}", x);
}Instructions
▼ ← Click the triangle to hide or reveal instructions.Task Incomplete
Editor Input:
Editor Output:
let.let x = 5; binds x to 5, then let x = x + 1; creates a new binding.x is still 5, but the new x shadows it with the value 6.xis individually immutable — you cannot reassign without let.6 because the second binding is the one in scope.fn main() {
let a = 7;
let b = 3;
println!("{}", a - b);
}Instructions
▼ ← Click the triangle to hide or reveal instructions.Task Incomplete
Editor Input:
Editor Output:
a and b hold the values 7 and 3.a - b subtracts b from a, producing 4.a nor bis modified by the subtraction — the result is a new temporary value.4, confirming the arithmetic works as expected.fn main() {
let x = 1;
let x = "one";
println!("{}", x);
}Instructions
▼ ← Click the triangle to hide or reveal instructions.Task Incomplete
Editor Input:
Editor Output:
x is a number, the second is a string.let x = 1; creates an integer, while let x = "one"; creates a &str.x is replaced by the new string x— they are separate variables.one because the second shadowing binding is active.Test Incomplete