Skip to content

monkeynut.org

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_drop feature 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) {}