Variable scope
Variable bindings have a scope, and are constrained to live in a block. A block is a collection of statements enclosed by braces {}
.
In the below example the scope for the variable language is only within the enclosed block.
if true {
let language = "English";
println!("Language is {}", language);
}
If this variable is accessed outside the block it will be a compiler error-
if true {
let language = "English";
println!("Language is {}", language);
}
println!("Language is {}", language);

To make the scope within the main method declare the vaiable outside the block.
let language = "English";
if true {
println!("Language is {}", language);
}
println!("Language is {}", language);
Output
Language is English
Language is English
Variable shadowing
Variable shadowing occurs when a variable declared within a certain scope (decision block, method or inner class) has the same name as a variable declared in an outer scope.
let language = "English";
if true {
println!("Language is {}", language);
}
let language = "French";
println!("Language is {}", language);
Output
Language is English
Language is French
In the above code the variable language is declared twice. Rust allows multiple variables with the same name, and these varaibles can be of different data type. The scope of the first variable remains until the next variable with same name is declared. The last variable with same name remains for the rest of the code.
Shadowing variable with different data type
let language = "English";
if true {
println!("Language is {}", language);
}
let language = 1; //here the first variable is de-scoped
println!("Language is {}", language);
Output
Language is English
Language is 1
When used correctly shadowing can be used for reusing common variable for different purposes and the ability to the mutability of data type. If this is not done carefully this can have a strange bugs in code.