use tokio; // 1.16.1
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::runtime::Runtime;
// Third-party code
fn call_fn_mut(mut f: impl FnMut(String) + Send + 'static) {
f(String::from("hello"));
}
fn blocking_send(rt: Arc<Runtime>, tx: mpsc::Sender<String>, msg: String) {
rt.block_on(tx.send(msg)).unwrap();
}
fn main() {
let (tx, mut rx) = mpsc::channel(1);
let rt = Arc::new(Runtime::new().unwrap());
// let rt_cloned = rt.clone(); // Won't compile without this
// call_fn_mut(move |msg| blocking_send(rt_cloned.clone(), tx.clone(), msg));
call_fn_mut(move |msg| blocking_send(rt.clone(), tx.clone(), msg));
rt.block_on(async {
println!("{}", rx.recv().await.unwrap());
});
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0382]: borrow of moved value: `rt`
--> src/main.rs:24:5
|
19 | let rt = Arc::new(Runtime::new().unwrap());
| -- move occurs because `rt` has type `Arc<Runtime>`, which does not implement the `Copy` trait
...
22 | call_fn_mut(move |msg| blocking_send(rt.clone(), tx.clone(), msg));
| ---------- -- variable moved due to use in closure
| |
| value moved into closure here
23 |
24 | / rt.block_on(async {
25 | | println!("{}", rx.recv().await.unwrap());
26 | | });
| |______^ value borrowed here after move
|
= note: borrow occurs due to deref coercion to `Runtime`
For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground` due to previous error
Here I expect rt
to be .clone()
ed first, then moved into the FnMut
clousre, but it seems not.
Actually, I have to make a let rt_cloned = rt.clone()
manually, and then pass it into the clousre via rt_cloned.clone()
, just as the two statements where I have commented out.
I'm not sure whether it is designed to behave like that or it is a bug, could anyone help?