I thought I've understood how async works in Rust but I was very very wrong...
So here is a simplified example:
async fn process<F1: Future, F2: Future>(
f1: &mut F1,
f2: &mut F2,
) -> (Option<F1::Output>, Option<F2::Output>) {
todo!()
}
async fn test() {
let mut a = MyObject;
let mut b = MyObject;
let mut f1 = a.do_something();
let mut f2 = b.do_something();
loop {
// commenting this out doesn't help
let (f1_result, f2_result) = process(&mut f1, &mut f2).await;
if f1_result.is_some() {
drop(f1); // does nothing
f1 = a.do_something(); // still thinks f1 is not dropped
}
if f2_result.is_some() {
drop(f2); // does nothing
f2 = b.do_something(); // still thinks f1 is not dropped
}
}
}
General description:
- objects
a
andb
produce futures that I want to observe -
process
method waits for any future to complete and returns their results when completed - if any future completes - it is restarted / recreated
But compiler doesn't agree with me (same goes for f2):
error[E0499]: cannot borrow `a` as mutable more than once at a time
--> src/main.rs:31:18
|
22 | let mut f1 = a.do_something();
| ---------------- first mutable borrow occurs here
...
31 | f1 = a.do_something(); // still thinks f1 is not dropped
| -- ^^^^^^^^^^^^^^^^ second mutable borrow occurs here
| |
| first borrow might be used here, when `f1` is dropped and runs the destructor for type `impl Future<Output = ()>`
Playground link:
So the questions are:
- why? why does it happens? error message doesn't really help. It says that object might be used during dropping the future, but I explicitly drop said future before creating a new one...
- how can I fix it? preferrably without
futures
or other crates excepttokio
.
Thanks.