← Back to Rust Course | Chapter 2: Variables & Types | Lesson 1 of 7

Declaring Variables with let

The word let is how you tell Rust "I want to remember this value under a name."

Basic let Bindings

The let keyword creates a new variable binding, associating a name with a value. Once assigned, that value can be read anywhere later in the same scope.

Example: Basic let Bindings

markup
fn main() {
    let language = "Rust";
    println!("Learning {}", language);
}

Type Annotations

Although Rust can usually infer a variable's type from its value, you can add an explicit type annotation after a colon. This is required when the type cannot be inferred, and is sometimes used for clarity.

Example: Type Annotations

markup
fn main() {
    let count: i32 = 42;
    println!("count = {}", count);
}

Immutability by Default

Variables created with let are immutable by default, meaning you cannot assign a new value to them after creation. Attempting to do so is a compile error, which is Rust's way of preventing accidental changes.

Note: Try uncommenting a reassignment line for an immutable variable locally -- the compiler error message is very descriptive.

Example: Immutability by Default

markup
fn main() {
    let pi = 3;
    println!("pi is approximately {}", pi);
    // pi = 4; // this line would fail to compile
}

Scope of Variables

A variable is only valid within the block of code (the curly braces) where it was declared. Once that block ends, the variable goes out of scope and can no longer be accessed.

Example: Scope of Variables

markup
fn main() {
    {
        let inner = "only visible here";
        println!("{}", inner);
    }
    println!("Outer scope continues");
}
Common Mistakes
  1. Forgetting that variables declared with plain let are immutable by default and cannot be reassigned.
  2. Trying to use a variable before it has been given a value with let.
  3. Assuming let always needs an explicit type, when Rust can usually infer it from the assigned value.
Chapter Summary
  • let binds a name to a value; by default the binding is immutable.
  • Rust infers types automatically in most cases, but you can annotate them explicitly with let x: i32 = 5;.
  • A variable must be initialized before it is used.
  • Bindings are scoped to the block { } they are declared in.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.