ProgramGuru

Variables, mutability and shadowing

Variables, mutability and shadowing

A student’s name can stay fixed while a corrected mark changes. Rust bindings are immutable by default: let names a value, and let mut permits reassignment. A binding is the name-to-value association in the program, not a permanent storage rule for every object in an application.

What you’ll learn

  • Choose mut only when reassignment is intended.
  • Distinguish shadowing from changing a binding’s value.

Variables, mutability and shadowing in action

  1. Integer mark: 72

    The mutable integer starts at 72 and becomes 80.

    Integer mark: 72
  2. Correction: 80

    The second let score shadows it with a String produced by to_string.

    Correction: 80
  3. Shadowed text: 80

    Printing uses that new text binding.

    Shadowed text: 80
The mutable integer starts at 72 and becomes 80. The second let score shadows it with a String produced by to_string. Printing uses that new text binding. The name never changes.

Variables, mutability and shadowing explained

Use mut where a value intentionally changes. Shadowing declares a new binding with the same name, which can have a different type; it is not reassignment of the old binding. Assignment uses =, while equality comparisons use ==. Rust often infers types from initial values and later operations.

Work through the Rust program

Save the complete source as main.rs in the Rust environment. No standard input is needed.

Rust 2024 · complete program

fn main() {
  let name = "Diya";
  let mut score = 72;
  score += 8;
  let score = score.to_string();
  println!("{name}: {score}");
}

Expected output

Diya: 80

Follow the execution

The mutable integer starts at 72 and becomes 80. The second let score shadows it with a String produced by to_string. Printing uses that new text binding. The name never changes.

Try the complete program in the Rust compiler. For tests, Cargo commands and local files, use the specified local environment.

Try a small variation

Your task: Why can the second let score hold text?

Rust 2024 · complete program

fn main() {
  let name = "Diya";
  let mut score = 72;
  score += 8;
  let score = score.to_string();
  println!("{name}: {score}");
}

Worked answer

It declares a new binding that shadows the integer. Reassigning text to the existing integer would fail because mut permits changing a value, not freely changing its type.

Mistakes and limits to recognize

Shadowing can clarify a transformation, but repeatedly reusing a name for unrelated meanings makes code hard to follow. A const item needs an explicit type and a constant expression; it is not simply another spelling of every let binding.

Check your understanding

Why can the second let score hold text?
Choose one answer. You can try again.

Answer and explanation

It declares a new binding that shadows the integer.

It declares a new binding that shadows the integer. Reassigning text to the existing integer would fail because mut permits changing a value, not freely changing its type.

Take the idea into your next program

It declares a new binding that shadows the integer. Reassigning text to the existing integer would fail because mut permits changing a value, not freely changing its type. Shadowing can clarify a transformation, but repeatedly reusing a name for unrelated meanings makes code hard to follow.

Further reading: the official Rust Book on variables, mutability and shadowing.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Numbers, division and conversions →