The Drop Trait & RAII

The Drop trait lets a type run cleanup code automatically the instant its value goes out of scope, giving Rust deterministic resource management without a garbage collector.

Learn The Drop Trait & RAII in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll implement Drop , learn the exact drop order, drop a value early with std::mem::drop , and see the RAII guard pattern that powers things like MutexGuard .

What You'll Learn in This Lesson

1️⃣ Implementing Drop

To run code when a value is destroyed, implement the Drop trait, which has a single method: fn drop(&mut self) . Rust calls it automatically when the value goes out of scope — you never call it yourself. This is the hook for closing files, releasing locks, flushing buffers, or logging.

Notice the inner _b is cleaned up as soon as its block closes, while _a waits until the end of main . Cleanup is precisely scoped, not deferred to some later collection pass.

2️⃣ Drop Order & Dropping Early

Within a scope, values are dropped in the reverse of their declaration order — the last one created is the first to be destroyed, exactly like unwinding a stack. This guarantees that a value can safely rely on things declared before it still being alive during its own cleanup.

If you need to release a resource before the end of its scope, hand it to std::mem::drop . That moves the value in and lets it go out of scope immediately, running its destructor right there.

3️⃣ The RAII Guard Pattern

RAII (Resource Acquisition Is Initialization) is the idea that a resource's lifetime is bound to a value. A guard acquires the resource when constructed and releases it in its Drop . This is exactly how the standard library's MutexGuard works: locking returns a guard, and the lock is released automatically when the guard drops — even on an early return or a panic.

Because cleanup is tied to the guard's lifetime, you can't forget to release the lock — there is no matching unlock() call to miss. This is why Rust does not need a garbage collector: ownership tells the compiler exactly when every value dies, and Drop handles the rest deterministically.

Your turn. Fill in the blank marked ___ , then run it.

Build a Connection type that opens on creation and closes itself via Drop . Mind the reverse drop order. Run it with cargo run and check the output.

📋 Quick Reference — Drop & RAII

Practice quiz

What is the single method of the Drop trait?

  • fn close(self)
  • fn free()
  • fn drop(&mut self)
  • fn dispose(&self)

Answer: fn drop(&mut self). Drop has one method, fn drop(&mut self), which Rust calls automatically at end of scope.

When does a value's Drop run?

  • When its owner goes out of scope
  • Immediately after creation
  • Only on program exit
  • When you call .free()

Answer: When its owner goes out of scope. A value is dropped the moment its owner leaves scope, typically at the closing brace of its block.

What does RAII stand for?

  • Resource Allocation In Iteration
  • Random Access Inline Indexing
  • Reference And Index Invariant
  • Resource Acquisition Is Initialization

Answer: Resource Acquisition Is Initialization. RAII = Resource Acquisition Is Initialization: a resource's lifetime is tied to a value's lifetime.

Within a scope, in what order are values dropped?

  • Declaration order
  • Reverse of declaration order
  • Alphabetical order
  • Random order

Answer: Reverse of declaration order. Values drop in reverse of declaration order, like unwinding a stack.

Three values _first, _second, _third are declared in that order. Which drops first?

  • _third
  • _first
  • _second
  • They drop simultaneously

Answer: _third. Reverse declaration order means _third drops first, then _second, then _first.

How do you drop a value early, before its scope ends?

  • value.drop()
  • free(value)
  • std::mem::drop(value)
  • delete value

Answer: std::mem::drop(value). std::mem::drop(value) takes ownership and runs the destructor immediately.

Why can't you call value.drop() directly?

  • It's too slow
  • Rust forbids it to prevent dropping a value twice (double free)
  • drop() is private
  • It needs a feature flag

Answer: Rust forbids it to prevent dropping a value twice (double free). Calling .drop() directly is a compile error so a value is never cleaned up twice.

In a Connection type with Drop, if connection 1 then connection 2 are opened in main, which closes first?

  • Connection 1
  • Both at once
  • Neither closes
  • Connection 2

Answer: Connection 2. Reverse drop order means connection 2 (declared last) closes before connection 1.

Why does Rust not need a garbage collector?

  • It never frees memory
  • Ownership plus Drop give deterministic, compile-time-tracked cleanup
  • It uses reference counting only
  • It runs a collector thread

Answer: Ownership plus Drop give deterministic, compile-time-tracked cleanup. Each value has one owner whose scope end is known at compile time, so cleanup is inserted automatically.

Which combination is NOT allowed for a single type?

  • Both Debug and Clone
  • Both Clone and Drop
  • Both Copy and Drop
  • Both Debug and Drop

Answer: Both Copy and Drop. A type can't be both Copy and Drop: needing custom cleanup means it can't be trivially copyable.