Course contentsShow
← Rust
Lesson 288 of 1,9103. Borrowing and ReferencesFree lesson

The Interaction of Drop and Lifetimes

Understand why drop order is critical when dealing with references.

In this lesson, you will learn why the order in which Rust destroys objects—the Drop order—is vital for maintaining memory safety when lifetimes are involved.

The Problem: Dangling References

In Rust, variables are dropped in the reverse order of their declaration. This means that if variable B holds a reference to variable A, dropping B first is safe, but dropping A first would leave B pointing to deallocated memory.

The borrow checker uses lifetimes to ensure that B cannot outlive A. If you try to create a scenario where the "parent" (the source of the data) is dropped before the "child" (the reference), the compiler will prevent the code from compiling because it violates the lifetime constraints.

A Concrete Example

Consider a simple struct that holds a reference.

struct Holder<'a>(&'a i32);

impl<'a> Drop for Holder<'a> {
    fn drop(&mut self) {
        println!("Dropping holder");
    }
}

fn main() {
    let data = 10;
    let holder = Holder(&data);
    // When this scope ends, 'holder' is dropped first,
    // then 'data' is dropped. This is perfectly safe!
}

If the order were reversed, or if holder tried to persist longer than data, the compiler would reject it. Because holder has a lifetime 'a tied to the scope of data, the compiler forces a drop order that ensures data is still alive while holder is being cleaned up.

Why It Matters

When you implement Drop manually, you must be careful. If your Drop implementation accesses a reference field, you are guaranteed that the object being referenced is still alive. Rust’s ownership rules ensure that the object holding the reference is destroyed before the object being referenced. If you were allowed to drop them in any order, you could easily trigger a "use-after-free" bug, which is exactly what Rust’s lifetime system is designed to prevent.

Always remember: the borrow checker enforces that the "owner" outlives the "borrower," and the drop order guarantees that the "borrower" is cleaned up before the "owner" disappears.

Key Takeaway: Rust enforces a reverse-declaration drop order to guarantee that references never outlive the data they point to, preventing dangling pointers at runtime.