Awaiting async code in Drop

I currently have this struct in my code:

/// auto flushes on drop
struct Flusher<'a, W: AsyncWriteExt + Unpin>(&'a mut W);

which I want to use to automatically flush my async file stream instead of manually calling flush. However Drop doesn't support async code because it isn't defined as an async fn. But is there some way to do something like this in tokio:

impl<W: ...> Drop for Flusher<'_, W> {
    fn drop(&mut self) {
        let _ = self.0.flush().await;
    }
}

unfortunately, currently there's no reliable way to run async code in drop, the async_drop feature is in very early phase and not coming to stable in the foreseeable future.

in some cases, you may work around it by blocking the current thread to run the async function, but it is not always possible, and would be very delicate and error prone even if it is, e.g. it may cause deadlock or panic.

As @nerditation said, there's not direct way to implement it in Drop and I would not recommend to do that any way.

Your main goal is to avoid running .flush().await after write file, right? Another option to achieve that is more simple and straightforward - just add some methods. For example, you can do something like that:

struct Flusher<'a, W: AsyncWriteExt + Unpin>(&'a mut W);

impl<'a, W: AsyncWriteExt + Unpin> Flusher<'a, W> {
    async fn write(
        &mut self,
        data: impl Into<&[u8]>,
    ) -> tokio::io::Result<()> {
        let _ = self.0.write(data.into()).await?;
        self.0.flush().await?;

        Ok(())
    }
}

Also you can add some methods to load file or similar. If I'm digging into the wrong place and you're trying to solve some other kind of problem, let me me know, perhaps we'll figure something out.

After a bit of poking around I found this crate: async-dropper which seems good for my use case? It works with tokio so I'll use that.