2

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Theof
  • 65
  • 7
  • 1
    It looks like your question might be answered by the answers of [Moved variable still borrowing after calling `drop`?](https://stackoverflow.com/q/43428894/155423); [What are the options to end a mutable borrow in Rust?](https://stackoverflow.com/q/35765440/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jun 08 '20 at 14:00
  • 2
    The duplicates [applied to your question](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bfb51620159544f98e87678f8d45ea67). – Shepmaster Jun 08 '20 at 14:02
  • 1
    Indeed, this is a good answer. In this case I would have liked to use the variable a inside the else-clause of the tokio::select! macro, so it is a bit cumbersome, but using blocks will do the trick: I may just set a flag inside the else-clause and check it outside that block. Thanks a lot ! – Theof Jun 08 '20 at 14:09

0 Answers0