How Rust guarantees deterministic cleanup of files, sockets, locks, and heap buffers the exact instant scopes exit.
struct DatabaseLock {
name: String,
}
impl Drop for DatabaseLock {
fn drop(&mut self) {
println!(">>> RAII: Lock '{}' released back to pool!", self.name);
}
}
fn main() {
{
let _lock = DatabaseLock { name: String::from("users_table") };
println!("Executing safe write transaction...");
} // _lock falls out of scope here; drop() executes deterministically!
println!("Transaction finalized.");
}In languages with a garbage collector (Java, Go, Python), memory is reclaimed unpredictably at a later time, meaning non-memory resources like file handles and mutex locks require manual closing.
In Rust, destruction is 100% deterministic: when the enclosing block ends or a function returns, the compiler automatically invokes the `Drop::drop` method for every active resource in that scope.
Even in the event of a panic, Rust automatically unwinds the stack, executing Drop destructors along the way to prevent resource leaks and database corruption.
1. Variables in a function are dropped in reverse order of declaration (LIFO stack). 2. Fields inside a struct/enum are dropped in direct order of declaration. 3. Vector elements are dropped from index 0 to len-1.
struct Pair { a: String, b: String }
// When Pair drops: a is dropped first, then b.
let x = String::from("1");
let y = String::from("2");
// At scope exit: y drops first, then x.