Notes on Rust async drop
Here are some notes from trying-out async
drop on rustc 1.93.0-nightly (2025-11-07).
I wanted to use async drop to ensure that an asynchronous cleanup operation was
performed prior to shutdown. However, I ended up hitting a "show-stopping" bug
:(. And, to be clear: this feature is incomplete, and therefore broken behavior
is to be expected.
The alternative approach that I ended up using was to thread a
task_tracker
through the call-stack, spawn onto this task_tracker from the synchronous drop
handler, and then perform a time-bounded wait on shutdown. Not as elegant, but
it does work.
- The "show stopping" bug was a crash during shutdown of the tokio runtime when a value with a async drop implementation was present. Presumably something about running the async drop implmementation during runtime shutdown doesn't work?
- If you're going to define an async drop implementation, you must also define a synchronous one.
- If you're dropping an async drop type in a crate without enabling the
async_dropfeature in that crate, then the synchronous drop implementation will be invoked. There is a lint for this, but it doesn't catch the case where the async drop is being performed from a generic function (see below). - The async drop implementation will only be invoked on exit from a block. It
will not be invoked in the following cases (instead the synchronous drop
implementation will be invoked):
- Drop due to assignment
- Manual invocation of
drop
- To ensure that I was hitting the async drop implementation, I made the synchronous drop implementation panic. (You should not do this in production code, because the synchronous drop implementation is invoked when unwinding from a panic, and panicking during a panic is not cool.)
- For explicit async drops, I found it useful to define my own drop function:
// Ensure that async_drop feature is enabled
#[allow(unused_imports)]
use std::future::AsyncDrop;
pub async fn async_drop<T>(_value: T) {}
9 November 2025