Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Shadowing in Rust occurs when a new variable is declared with the exact same identifier as a previously declared variable within the same or an enclosing scope. The compiler resolves any subsequent references to that identifier to the most recently declared variable, effectively obscuring the original variable from that point forward. To shadow a variable, the let keyword must be used for the new declaration. Because shadowing creates a completely new variable binding rather than modifying an existing one, the original variable does not need to be declared with the mut keyword. Furthermore, because a new variable is instantiated, the data type associated with the identifier can be changed.
let x = 5;       // Original binding (type: i32)
let x = x + 1;   // Shadows the first 'x' (type: i32)
let x = "six";   // Shadows the second 'x', changing the type (type: &str)
Shadowing is lexically scoped. When a variable is shadowed within an inner block, the shadowing effect is strictly bound to that block. Once the inner scope terminates, the inner variable is dropped, and the identifier reverts to resolving to the original variable in the outer scope.
let y = 10;

{
    // Shadows the outer 'y' strictly within this block
    let y = y * 2; 
    println!("Inner y: {}", y); // Outputs: 20
} // The inner 'y' goes out of scope and is dropped

// The identifier 'y' resolves to the outer variable again
println!("Outer y: {}", y); // Outputs: 10
It is critical to distinguish shadowing from variable mutation (reassignment). They are distinct mechanical operations in the Rust compiler:
  • Shadowing requires the let keyword, creates a new variable binding, allows the data type to change, and results in a variable that is immutable by default.
  • Mutation omits the let keyword, requires the original variable to be declared as mut, modifies the value in the existing memory location, and strictly enforces that the new value matches the original data type.
// Shadowing: Valid type change
let spaces = "   ";
let spaces = spaces.len(); // Rebinds 'spaces' to a usize

// Mutation: Invalid type change (Compile-time Error)
let mut spaces_mut = "   ";
spaces_mut = spaces_mut.len(); // ERROR: expected &str, found usize
Master Rust with Deep Grasping Methodology!Learn More