How to call async fn in a sync fn in asyn runtime

for code like this:

impl Drop for User {
    fn drop(&mut self) {
        [...]
        if self.dirty {
            self.save_when_exit();
        }
        [...]
    }
}

while save_when_exit has to be async fn because it will call sqlx;

At first, I tried


    #[tokio::main(flavor = "current_thread")]
    async fn save_when_exit(&self) {
        _ = storage::save_user_attributes(...)
        .await;
    }

But turns out it's not allowed by panic:

Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous task

So, I stucked because it is impossible for drop to be a async function.
Seems there is no way out except I rename drop to some_function and calls it manually, Or spawn a new thread to execute the async function;

Both are not good, I think, because the User is created in a async fn like that

async fn xxx() {
    let u = User([...]);
    drop(u);
}

ideally, I want something like

async fn xxx() {
    let u = User([...]);
    
   // the compiler do the following impicitly
   // drop(u).await;
}

EDIT:

I missed the "in async runtime" part of the question.

you should be able to use tokio::Runtime::block_on() or tokio::Handle::block_on(). see the previous post:

This is most likely not what OP is looking for, as calling block_on on the handle of a runtime already in a block_on call[1] results in the same panic OP gets when they try to spawn a new runtime. Example.


  1. The tokio docs call this an "asynchronous execution context" ↩︎

oopsie, I didn't read the problem description through, I miss the "in async runtime" part.

in that case, I think the the blocking operation must be run off the async worker thread, in the case of Drop, it means the type must be Send and the value should be moved into a spawn_blocking()-ed task. this would block one of the blocking worker of the thread pool, but should not block the async executor.

as far as I know, spawn_blocking()-ed task is not considered inside the async execution context.