dropping a tokio::pin! -ned async block does not release borrow

Viewed 217

I have some async blocks that borrow some variables of my main. I call pin! on those blocks so that I can use select! on them afterwards. I would expect that when dropping the block, I can move my variable as I want in my main:

use std::time::Duration;
use tokio; // 0.2.21

enum Error {
    Any,
}

#[derive(Debug)]
struct A {
    x: u32,
}

#[tokio::main]
async fn main() {
    let mut a = Some(A { x: 42 });
    let test_that_times_out = async {
        tokio::time::delay_for(Duration::from_secs(5)).await;
        a.replace(A { x: 36 });
    };
    let timeout = async {
        tokio::time::delay_for(Duration::from_secs(1)).await;
        let ret: Result<(), Error> = Err(Error::Any);
        ret
    };
    tokio::pin!(timeout, test_that_times_out);
    // pinning so we can tokio::select!

    // [...]

    drop(test_that_times_out);
    drop(a); // instead do some useful stuff by consuming a
}

(playground)

However, the compiler complains:

error[E0505]: cannot move out of `a` because it is borrowed
  --> src/main.rs:31:10
   |
16 |       let test_that_times_out = async {
   |  _____________________________________-
17 | |         tokio::time::delay_for(Duration::from_secs(5)).await;
18 | |         a.replace(A { x: 36 });
   | |         - borrow occurs due to use in generator
19 | |     };
   | |_____- borrow of `a` occurs here
...
31 |       drop(a); // instead do some useful stuff by consuming a
   |            ^ move out of `a` occurs here
32 |   }
   |   - borrow might be used here, when `test_that_times_out` is dropped and runs the destructor for type `impl std::future::Future`

Removing the pin! call makes this snippet compile, however I cannot use select! anymore in this case, which is required for my use case. Is there a better way to release the borrow before moving a? Is it possible at all?

0 Answers
Related