In this tutorial, you’ll learn how variable scope works in Rust and why it matters in memory safety.
What is Scope? #
In Rust, scope is the region of code where a variable is valid and can be accessed. When the scope ends, the variable is no longer available, and its memory is automatically freed.
This is one of Rust’s key features: memory safety without needing a garbage collector.
A Simple Scope Example #
fn main() {
{
let x = 5;
println!("Inside scope: x = {}", x);
} // <- `x` goes out of scope here
// println!("Outside scope: x = {}", x); // ❌ Error: `x` not found
}
Code language: Rust (rust)- The variable
xexists only inside the inner{ }. - When the block ends,
xis dropped, and we cannot use it anymore.
Scope in Functions #
Each function has its own scope. Variables declared inside a function cannot be used outside of it.
fn main() {
let message = "Hello!";
greet(message);
// println!("{}", name); // ❌ Error: `name` not defined here
}
fn greet(name: &str) {
println!("Greetings, {}!", name);
}
Code language: Rust (rust)messageis valid inmain.nameis only valid inside thegreetfunction.
Shadowing and Scope #
Rust allows shadowing, where a new variable with the same name replaces the previous one inside a scope.
fn main() {
let number = 10;
{
let number = 20; // shadows the outer `number`
println!("Inner scope number: {}", number);
}
println!("Outer scope number: {}", number);
}
Code language: Rust (rust)Output:
Inner scope number: 20
Outer scope number: 10
Code language: Rust (rust)Why Scope Matters for Memory Safety #
Rust automatically drops variables when they go out of scope. This prevents memory leaks and dangling references.
Here’s an example with String:
fn main() {
{
let s = String::from("Rust");
println!("String inside scope: {}", s);
} // `s` is automatically dropped here
// println!("{}", s); // ❌ Error: `s` not found
}
Code language: Rust (rust)You don’t need to manually free memory like in C/C++. Rust’s scope rules ensure that resources are safely cleaned up when no longer needed.
Summary #
- Variables are only valid within the scope they are defined.
- When a scope ends, variables are automatically dropped.
- Functions create their own scope.
- Shadowing allows you to reuse variable names within inner scopes.
- Scope rules are the foundation of Rust’s memory safety guarantees.