Drop Checker, Drop Glue, ManuallyDrop<T>, and std::mem::forget
- Last updated
- Prerequisites:
- Rust ownership and lifetimes
- Understanding of RAII and destructors
- rust
- drop
- drop-checker
- manuallydrop
- mem-forget
- destructor
Read at your depth
The practical view
In Rust, values are dropped automatically at the end of their scope (RAII): the Drop trait's drop() runs when the value goes out of scope. Box, Vec, MutexGuard, File all free resources on drop. ManuallyDrop<T> is a wrapper that prevents the compiler from dropping the inner value automatically — you take manual control (e.g. for FFI where the C side owns the memory). std::mem::forget(v) prevents v's destructor from running (v is 'leaked' deliberately). The drop checker is part of the borrow checker that verifies drop ordering doesn't cause use-after-free (e.g. dropping a reference to a value that drops earlier).
The same idea in other frameworks
N/A — Rust language feature.N/A — Rust feature.N/A — Rust feature.N/A — Rust feature.Legacy vs modern
Automatic drop vs ManuallyDrop / mem::forget
RAII cleans up automatically; ManuallyDrop/mem::forget suppress the cleanup for cases where ownership moves outside Rust's rules.
let file = File::open(path)?;
// ❌ OLD: if code forgets to close, the OS file handle leakslet mut md = ManuallyDrop::new(raw_ptr_holder); // ✅ NEWInterview gotchas
Context
This tests the borrow-checker integration — interviewers want the drop-ordering analysis and the classic pattern it used to reject.
The mechanical answer
The drop checker is the part of the borrow checker that verifies values are not dropped while still borrowed (which would create a use-after-free when the borrow is later used, or when a destructor reads a dropped value). Historically (pre-NLL), it was conservative: it examined the drop order of locals and the lifetimes of borrows, and rejected code where a value that might be dropped at scope end was borrowed with a lifetime that extended to the end. The classic rejected pattern: a struct containing a reference to a field of another struct being dropped in the same scope, where the reference's lifetime outlived the field's drop. NLL (non-lexical lifetimes) made the analysis much more precise: borrows are considered live only where actually used, so many previously-rejected (but actually-safe) patterns now compile, and genuinely-unsafe drop orderings are still caught.
Trap
The naive answer is 'the drop checker prevents memory leaks'. It prevents use-after-free from drop-ordering, not leaks (leaks are prevented by RAII discipline, not the checker). Another trap: thinking NLL removed the drop checker — it made it more precise; the analysis still exists and still rejects unsound code. Candidates who describe the drop-order/liveness analysis show real understanding.
Context
This tests the ownership-transfer primitives — interviewers want the semantics of each and the soundness contract (who is responsible for the resource afterward).
The mechanical answer
mem::forget(v) consumes v and guarantees its destructor never runs — the value's resources are intentionally leaked. ManuallyDrop<T> is a wrapper that prevents the compiler from generating the drop glue for the inner value; you can later take the value out with ManuallyDrop::into_inner (moving it out, so you regain ownership and drop happens normally at the new scope) or keep it wrapped (never dropped). 'Just not dropping' isn't a thing in safe Rust — the compiler inserts drops; ManuallyDrop/forget are how you suppress them. Sound usage is when ownership is transferred to code outside Rust's cleanup rules: handing a heap allocation to a C library that will free it, or embedding Rust data in a foreign structure that manages its own lifetime. If you forget a value and nothing else frees it, you have a real resource leak — forget is sound but must be intentional.
Trap
The naive answer is 'forget and ManuallyDrop are the same'. forget consumes and never returns the value; ManuallyDrop lets you take it back (into_inner). Another trap: assuming forgetting is always a leak bug — it's the correct tool for ownership transfer to FFI; the leak is the consequence when used carelessly. Candidates who describe the take-back capability and the ownership-transfer contract show real depth.