简体   繁体   English

为什么我的匹配块中需要发送特征?

[英]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 awaitas 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.值必须Sendawait调用才能存活,因为协程可能会在与挂起不同的线程上恢复。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM