Scope and the Drop Trait
In this page:
{
let name = value;
} // name dropped here
drop(name); // drop early
Automatic Cleanup at End of Scope
Every value's owner has a scope, and when that scope ends, Rust automatically runs cleanup code for the value, freeing any associated memory without any explicit action from you.
Example: Automatic Cleanup at End of Scope
fn main() {
let message = String::from("cleaned up automatically");
println!("{}", message);
} // message is dropped here
Login to try C/C++/Java/PHP code in the editor
Implementing Drop
You can implement the Drop trait for your own struct to run custom cleanup logic, such as printing a message, right when a value of that type goes out of scope.
Example: Implementing Drop
// Define a struct `Connection` to group related fields together
struct Connection {
name: String,
}
// Implement the `Drop` trait for `Connection`
impl Drop for Connection {
// Define the function `drop` taking `self`
fn drop(&mut self) {
// Print "Closing connection: {}" to the console, substituting in `self.name` (with a trailing newline)
println!("Closing connection: {}", self.name);
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `_conn`, set to `Connection { name: String::from("db") }`
let _conn = Connection { name: String::from("db") };
// Print "Using connection" to the console (with a trailing newline)
println!("Using connection");
}
Login to try C/C++/Java/PHP code in the editor
Drop Order Is Reverse of Declaration
When multiple values go out of scope together, Rust drops them in the reverse order they were declared, similar to unwinding a stack.
Example: Drop Order Is Reverse of Declaration
// Define a struct `Announcer` to group related fields together
struct Announcer(i32);
// Implement the `Drop` trait for `Announcer`
impl Drop for Announcer {
// Define the function `drop` taking `self`
fn drop(&mut self) {
// Print "Dropping {}" to the console, substituting in `self.0` (with a trailing newline)
println!("Dropping {}", self.0);
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `_first`, set to `Announcer(1)`
let _first = Announcer(1);
// Declare an immutable variable `_second`, set to `Announcer(2)`
let _second = Announcer(2);
// Print "Both created; watch the drop order below" to the console (with a trailing newline)
println!("Both created; watch the drop order below");
}
Login to try C/C++/Java/PHP code in the editor
Forcing an Early Drop
Sometimes you want a value cleaned up before its scope naturally ends. Since you cannot call .drop() directly, the standard library provides std::mem::drop to consume and drop a value early.
Example: Forcing an Early Drop
// Define a struct `Resource` to group related fields together
struct Resource;
// Implement the `Drop` trait for `Resource`
impl Drop for Resource {
// Define the function `drop` taking `self`
fn drop(&mut self) {
// Print "Resource released early" to the console (with a trailing newline)
println!("Resource released early");
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `res`, set to `Resource`
let res = Resource;
// Print "About to release early" to the console (with a trailing newline)
println!("About to release early");
drop(res);
// Print "Released; rest of main continues" to the console (with a trailing newline)
println!("Released; rest of main continues");
}
Login to try C/C++/Java/PHP code in the editor
- Manually trying to free or clean up a value yourself instead of trusting Rust's automatic
Dropbehavior. - Assuming
Dropruns in the order variables were created -- it actually runs in reverse order of declaration within a scope. - Implementing a custom
Dropand also calling.clone()unnecessarily, not realizing Drop only runs once per owned value automatically.
- When a value's owner goes out of scope, Rust calls the
Droptrait'sdropmethod automatically to clean it up. - Values are dropped in the reverse order they were declared within a scope.
- You can implement a custom
Dropfor your own types to run cleanup code, like closing a resource. - You cannot call
.drop()manually -- Rust prevents this to avoid double-free bugs; usestd::mem::dropinstead if needed.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: