Theme
Q031. What do mem::forget and ManuallyDrop do to ownership and destruction?
Short Answer
mem::forget consumes a value and prevents its destructor from running, usually leaking its resources. ManuallyDrop<T> wraps a value and disables automatic destruction while preserving T's layout and validity requirements. The value can later be recovered or manually destroyed, but unsafe manual destruction must prevent double drop, use-after-drop, and invalid moves.
Deep Dive
mem::forget(value) is safe because Rust never guarantees that destructors must run. After the call, the value is inaccessible and its cleanup responsibility has been intentionally abandoned. It is rarely the best ownership-transfer primitive because failures before the call can still run the old destructor.
ManuallyDrop::new(value) disables automatic dropping immediately. Safe code can access the contained value and can recover it with ManuallyDrop::into_inner, restoring normal destruction. Low-level code may use unsafe ManuallyDrop::take or ManuallyDrop::drop when manually managing an active variant, union field, or raw ownership transfer.
ManuallyDrop does not provide uninitialized storage; MaybeUninit<T> serves that purpose. Public generic wrappers around manually dropped values are especially difficult to make sound.
Internal Model
ManuallyDrop<T> has the same layout and bit-validity requirements as T; it adds no runtime flag. The compiler simply omits automatic drop glue for the wrapped field.
After unsafe manual destruction, the bytes may remain, but they must not be exposed as a live T. Some cases, such as moving a ManuallyDrop<Box<_>> after manually dropping its contents, have additional validity hazards.
Example
rust
use std::mem::{self, ManuallyDrop};
fn main() {
let forgotten = String::from("leaked");
mem::forget(forgotten);
let manual = ManuallyDrop::new(String::from("recoverable"));
println!("{}", manual.len());
let recovered = ManuallyDrop::into_inner(manual);
drop(recovered);
}Common Mistakes
- Using
ManuallyDrop<T>as if it were uninitialized storage. - Calling
ManuallyDrop::droptwice or exposing the value afterward. - Using
mem::forgetas the default method for transferring raw ownership.
Follow-ups
- Why is
ManuallyDrop::dropunsafe? - When should
MaybeUninit<T>be used instead? - How can panic between raw ownership steps cause double cleanup?
Related
- Q024. How are ownership,
Drop, and RAII related? - Q027. What is the difference between
Drop::dropandstd::mem::drop? - Q030. Can Rust ownership prevent resource and memory leaks?
References
- Rust Reference
- Rust Standard Library
- Rustonomicon