为什么我的匹配块中需要 Send 特性?
Why is the Send trait required inside my match block?
我认为我的问题与 Rust Issue 57017 有关。
以下 code 无法编译并生成 error: future cannot be sent between threads safely
,因为 future created by async block is not 'Send'
源自 async fn execute_fail
。另一方面,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");
}
});
}
给出:
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
我想解释为什么 execute_fail
不像 execute_work
那样编译。编译器注释 note: future is not
Send as this value is used across an await
对我来说没有意义,因为我看不到任何值是如何在等待中使用的。
I would like an explanation why execute_fail does not compile where as execute_work does.
当您 match stream().await
时,它基本上是:
let v = stream().await;
match v {
...
}
因此 v
在整个匹配过程中都处于活动状态,这意味着就编译器而言,它的“生命”与 process().await
调用重叠。值必须是 Send
才能通过 await
调用,因为协程可能会在与暂停不同的线程上恢复。
注意:这里的代码可以大大简化:
async fn execute_fail() -> Result<(), Box<dyn std::error::Error>> {
if let Err(err) = stream().await {
return Err(err);
}
process().await;
Ok(())
}
甚至
async fn execute_fail() -> Result<(), Box<dyn std::error::Error>> {
stream().await?;
process().await;
Ok(())
}
我认为我的问题与 Rust Issue 57017 有关。
以下 code 无法编译并生成 error: future cannot be sent between threads safely
,因为 future created by async block is not 'Send'
源自 async fn execute_fail
。另一方面,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");
}
});
}
给出:
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
我想解释为什么 execute_fail
不像 execute_work
那样编译。编译器注释 note: future is not
Send as this value is used across an await
对我来说没有意义,因为我看不到任何值是如何在等待中使用的。
I would like an explanation why execute_fail does not compile where as execute_work does.
当您 match stream().await
时,它基本上是:
let v = stream().await;
match v {
...
}
因此 v
在整个匹配过程中都处于活动状态,这意味着就编译器而言,它的“生命”与 process().await
调用重叠。值必须是 Send
才能通过 await
调用,因为协程可能会在与暂停不同的线程上恢复。
注意:这里的代码可以大大简化:
async fn execute_fail() -> Result<(), Box<dyn std::error::Error>> {
if let Err(err) = stream().await {
return Err(err);
}
process().await;
Ok(())
}
甚至
async fn execute_fail() -> Result<(), Box<dyn std::error::Error>> {
stream().await?;
process().await;
Ok(())
}