Shadowing is the ability to declare a variable with the same name multiple times in the same scope, where the new variable "shadows" the previous one. In languages without shadowing (C, C++), redefining a variable leads to an error or undefined behavior. Rust allows shadowing, and each variable is an independent object with a new type or value. This is convenient for stepwise transformations of a value — for example, turning a string directly into a number without coming up with new names.
Problem: on one hand — improved readability, preventing variable name bloating; on the other — complicated debugging if a variable is accidentally "shadowed" in a complex block and an unexpected result is obtained.
Solution: Shadowing is used only where it genuinely facilitates transformation and does not hinder readability. Each "let var = ...;" creates a new variable, leaving the old one unchanged outside the declaration block.
Example code:
fn example() { let x = "42"; let x = x.parse::<i32>().unwrap(); println!("x: {}", x); // x: 42 }
Key features:
Can shadowing change the mutability of a variable?
Yes, you can "shadow" an immutable variable with a mutable one and vice versa:
let x = 5; let mut x = x; x += 1;
Does shadowing mean that the previous variable has been destroyed?
No, the values of the previous variable live until the end of the block where they were declared, but they become inaccessible by name.
Can shadowing be used inside a loop or within nested blocks?
Yes, each scope allows declaring variables with the same names, and these are different variables.
In the function, there's let result = expr1; ... let result = expr2;, where types differ.
Pros:
Cons:
Shadowing is used only to change the type: first, a string is parsed, then it is assigned a numeric value.
Pros:
Cons: