尽管范围拥有变量的所有权,但引用仍被保留

Reference is held beyond being used eventhough the scope has ownership of the variable

我有一些代码如下所示:

async move {
    let res = do_sth(&state).await;
    (state, res)
}.boxed()

(完整示例:https://gitlab.com/msrd0/async-issue

我会说 async move 块获取 state 的所有权并将 state 的引用传递给 do_sth 方法,这是一个 async fn。但是,编译器还会在 await 范围内保持 &state,我不知道为什么会这样做:

error: future cannot be sent between threads safely
  --> src/main.rs:30:5
   |
30 |         }.boxed()
   |           ^^^^^ future returned by `read_all` is not `Send`
   |
   = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)`
note: future is not `Send` as this value is used across an await
  --> src/main.rs:28:14
   |
28 |             let res = do_sth(&state).await;
   |                       ^^^^^^^------^^^^^^^- `&state` is later dropped here
   |                       |      |
   |                       |      has type `&gotham::state::State`
   |                       await occurs here, with `&state` maybe used later

我尝试将不带 awaitdo_sth 调用放入它自己的块中,但这并没有解决错误。

有什么方法可以避免这个错误吗?

该错误显然与所有权或生命周期无关:

error: future cannot be sent between threads safely

gotham_restful::State 没有实现 Sync trait, which means that its reference &state is not thread-safe. However, you are passing that reference to asynchronous function, which is then awaited, and the Rust compiler automatically infers that that function is not thread safe, so the entire block become "not thread safe". The return value of the read_all method has the + <a href="https://doc.rust-lang.org/stable/std/marker/trait.Send.html" rel="nofollow noreferrer">Send</a> 约束,但是,要求返回的 future 是线程安全的,所以这会导致错误。


一个可能的解决方案是将 do_sth 重写为 returns 未来的常规函数​​。这样你就可以确保从该函数返回的 future 实现 Send 并且是线程安全的,而不是依赖编译器来推断它在哪里是线程安全的:

fn do_sth(_state: &State) -> impl Future<Output = NoContent> + Send {
//   require that the future of this function is thread-safe ---^

    async move {
        Default::default()
    }
}

请注意,这实际上不会允许您执行任何非线程安全的操作,但是它会指示编译器 do_sth 函数应该是线程安全的,而不是尝试手动推断它是否应该是还是不是。