[英]Why is the Send trait required inside my match block?
I think my question relates to Rust Issue 57017 .我认为我的问题与Rust 问题 57017 相关。
The following code does not compile and produces error: future cannot be sent between threads safely
due to future created by async block is not 'Send'
originating in async fn execute_fail
.以下代码不会编译并产生error: future cannot be sent between threads safely
由于future created by async block is not 'Send'
源自async fn execute_fail
future created by async block is not 'Send'
error: future cannot be sent between threads safely
发送future created by async block is not 'Send'
。 On the other hand async fn execute_work
compiles and has the same functions and logic as execute_fail
but in a less elegant manner.在另一方面async fn execute_work
编译并具有相同的功能和逻辑execute_fail
但在一个不太精巧的方式。
async fn stream() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
async fn process() {}
async fn execute_fail() -> Result<(), Box<dyn std::error::Error>> {
match stream().await {
Err(err) => {
return Err(err);
}
Ok(()) => {
process().await;
}
}
Ok(())
}
async fn execute_work() -> Result<(), Box<dyn std::error::Error>> {
let mut is_success = false;
match stream().await {
Err(err) => {
return Err(err);
}
Ok(()) => {
is_success = true;
}
}
if is_success {
process().await;
}
Ok(())
}
async fn my_fn() {
tokio::spawn(async {
if let Err(err) = execute_fail().await {
panic!("error here");
}
});
tokio::spawn(async {
if let Err(err) = execute_work().await {
panic!("error here");
}
});
}
Gives:给出:
error: future cannot be sent between threads safely
--> src/lib.rs:39:5
|
39 | tokio::spawn(async {
| ^^^^^^^^^^^^ future created by async block is not `Send`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.11.0/src/task/spawn.rs:127:21
|
127 | T: Future + Send + 'static,
| ---- required by this bound in `tokio::spawn`
|
= help: the trait `Send` is not implemented for `dyn std::error::Error`
note: future is not `Send` as this value is used across an await
--> src/lib.rs:15:13
|
10 | match stream().await {
| -------------- has type `Result<(), Box<dyn std::error::Error>>` which is not `Send`
...
15 | process().await;
| ^^^^^^^^^^^^^^^ await occurs here, with `stream().await` maybe used later
16 | }
17 | }
| - `stream().await` is later dropped here
I would like an explanation why execute_fail
does not compile where as execute_work
does.我想解释为什么execute_fail
不能编译,其中作为execute_work
一样。 The compiler note note: future is not
Send as this value is used across an await
doesn't make sense to me as I don't see how any values are being used across an await.编译器注释note: future is not
Send, as this value is used across an await
中as this value is used across an await
对我来说没有意义,因为我看不到在 await 中如何使用任何值。
I would like an explanation why execute_fail does not compile where as execute_work does.我想解释一下为什么 execute_fail 不像 execute_work 那样编译。
When you match stream().await
it essentially works as:当您match stream().await
它本质上是这样工作的:
let v = stream().await;
match v {
...
}
So v
is alive for the entirety of the match, meaning as far as the compiler is concerned its "life" overlaps with the process().await
call.所以v
在整个匹配过程中都是存活的,这意味着就编译器而言,它的“生命”与process().await
调用重叠。 Values must be Send
to live through an await
call, as the coroutine may be resumed on a different thread than it was suspended.值必须Send
到await
调用才能存活,因为协程可能会在与挂起不同的线程上恢复。
Of note: the code here can be significantly simplified:值得注意的是:这里的代码可以显着简化:
async fn execute_fail() -> Result<(), Box<dyn std::error::Error>> {
if let Err(err) = stream().await {
return Err(err);
}
process().await;
Ok(())
}
or even甚至
async fn execute_fail() -> Result<(), Box<dyn std::error::Error>> {
stream().await?;
process().await;
Ok(())
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.