Introduction
Constants in Rust are values that are bound to a name and are never allowed to change, similar to immutable variables but with important differences. Constants must always have an explicit type annotation, must be set to a value that can be computed at compile time, and are declared using the const keyword. Shadowing, on the other hand, is a distinct feature where you can declare a new variable with the same name as a previous one using let, effectively creating a new binding rather than mutating the old one.
Cricket analogy: A const is like a fixed boundary rope distance set before the match that can never move once play starts, always announced with its exact measurement, whereas shadowing is like a new batsman coming in and being called the striker again, a fresh binding reusing the label, not editing the previous batsman.
Syntax
// Constant declaration
const MAX_POINTS: u32 = 100_000;
// Shadowing
let x = 5;
let x = x + 1;
let x = x * 2;Explanation
The constant MAX_POINTS must have its type (u32) declared explicitly; Rust will not infer it. Constants can be declared in any scope, including the global scope, and are valid for the entire time the program runs within their scope. By convention, constant names use SCREAMING_SNAKE_CASE with underscores separating words for readability, such as MAX_POINTS. Shadowing is different from mutation: each let x = ... creates an entirely new variable that happens to reuse the name x, temporarily or permanently hiding the previous one. This allows you to change the type of a value while reusing the same name, which is not possible with mut since mut requires the type to stay the same.
Cricket analogy: Declaring MAX_POINTS: u32 is like officially registering a tournament's maximum overs as exactly 50, written with its unit in SCREAMING_SNAKE_CASE style like MAX_OVERS on the scoreboard, valid for the whole tournament; shadowing lets a commentator reuse the total to mean a completely different stat later in the broadcast, unlike a fixed rule that can't change type.
Example
const MAX_POINTS: u32 = 100_000;
fn main() {
println!("Max points: {}", MAX_POINTS);
let spaces = " ";
let spaces = spaces.len(); // shadowing changes type from &str to usize
let y = 3;
{
let y = y * 2; // shadowed only within this inner scope
println!("Inner y = {}", y);
}
println!("Outer y = {}", y);
println!("spaces = {}", spaces);
}Output
Max points: 100000
Inner y = 6
Outer y = 3
spaces = 3Key Takeaways
- Constants are declared with
const, require a type annotation, and must be compile-time computable. - Constant names conventionally use SCREAMING_SNAKE_CASE.
- Shadowing reuses a variable name to create a new binding with
let. - Shadowing allows changing the type of the value, unlike
mut. - A shadowed variable inside a scope only affects that inner scope.
Practice what you learned
1. Which keyword is used to declare a constant in Rust?
2. What is required when declaring a Rust constant?
3. How does shadowing differ from using `mut`?
4. What naming convention is typically used for Rust constants?
5. In the example `let y = 3; { let y = y * 2; }`, what is the value of the outer `y` after the inner block ends?
Was this page helpful?
You May Also Like
Variables and Data Types in Rust
Learn how Rust variables are immutable by default and explore its scalar and compound data types.
Operators in Rust
Explore Rust's arithmetic, comparison, logical, and bitwise operators with practical examples.
Type Conversion in Rust
Learn how Rust handles explicit type conversion using the as keyword and the From/Into traits.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics