Variable Shadowing
In this page:
let name = value;
let name = new_expression_using(name);
Basic Shadowing
Using let again with a name that already exists creates a brand new variable that shadows (hides) the old one. The old value still existed, but it is no longer accessible under that name.
Example: Basic Shadowing
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `x`, set to `5`
let x = 5;
// Declare an immutable variable `x`, set to `x + 1`
let x = x + 1;
// Declare an immutable variable `x`, set to `x * 2`
let x = x * 2;
// Print "x is {}" to the console, substituting in `x` (with a trailing newline)
println!("x is {}", x);
}
Login to try C/C++/Java/PHP code in the editor
Shadowing Can Change Type
Because shadowing creates a completely new variable, the new binding is free to have a different type than the original, which plain mutation with mut never allows.
Example: Shadowing Can Change Type
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `spaces`, set to `" "`
let spaces = " ";
// Declare an immutable variable `spaces`, set to `spaces.len()`
let spaces = spaces.len();
// Print "Number of spaces: {}" to the console, substituting in `spaces` (with a trailing newline)
println!("Number of spaces: {}", spaces);
}
Login to try C/C++/Java/PHP code in the editor
Shadowing Within a Block
A shadowed variable inside an inner block only shadows the outer one for the duration of that block. Once the block ends, the outer variable's value is visible again.
Example: Shadowing Within a Block
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `x`, set to `1`
let x = 1;
{
// Declare an immutable variable `x`, set to `x + 10`
let x = x + 10;
// Print "Inner x: {}" to the console, substituting in `x` (with a trailing newline)
println!("Inner x: {}", x);
}
// Print "Outer x: {}" to the console, substituting in `x` (with a trailing newline)
println!("Outer x: {}", x);
}
Login to try C/C++/Java/PHP code in the editor
Shadowing vs Mutability
Shadowing and mut solve different problems: mut changes a value in place while keeping the same type, whereas shadowing produces an independent new binding, optionally with a new type, without ever needing mut.
Example: Shadowing vs Mutability
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `value`, set to `"42"`
let value = "42";
// Declare an immutable variable `value` (an integer), set to `value.parse().unwrap()`
let value: i32 = value.parse().unwrap();
// Print "Parsed value: {}" to the console, substituting in `value` (with a trailing newline)
println!("Parsed value: {}", value);
}
Login to try C/C++/Java/PHP code in the editor
- Confusing shadowing with mutation -- shadowing creates an entirely new variable, it does not change the old one in place.
- Thinking shadowing requires
mut; in fact shadowing works with plain immutableletbindings. - Overusing shadowing to change a variable's type repeatedly in a way that makes code confusing to follow.
- Shadowing declares a new variable with
letthat reuses an existing name, hiding the previous one. - Shadowing can change the type of the value stored under that name, unlike mutation.
- Each shadowed variable exists until the end of its scope or until shadowed again.
- Shadowing is useful for transforming a value step by step while keeping a meaningful name.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: