Future 不是 Send,仅当来自 async Trait 时

Jam*_*lor 0 rust

我有一个特点Serializer

trait Serializer {
    fn serialize(&self, data: Rc<()>) -> Result<(), Error>;
}
Run Code Online (Sandbox Code Playgroud)

还有一些Foo实现它的。值得注意的是,data不是Send

实际的实现需要异步上下文来执行,因此我将异步运行时的创建与实际的实现分开,如下所示:

struct Foo {}

impl Foo {
    async fn async_serialize(&self, _data: Rc<()>) -> Result<(), Error> {
        unimplemented!();
    }
}

impl Serializer for Foo {
    fn serialize(&self, data: Rc<()>) -> Result<(), Error> {
        let runtime = Builder::new_current_thread().enable_all().build().unwrap();
        runtime.block_on(async move { self.async_serialize(data).await })
    }
}
Run Code Online (Sandbox Code Playgroud)

这将按照我的预期进行编译和工作。

如果我重构代码,以便通过特征完成异步运行时创建:

#[async_trait]
trait AsyncSerializer {
    async fn async_serialize(&self, data: Rc<()>) -> Result<(), Error>;
}

#[async_trait]
impl AsyncSerializer for Foo {
    async fn async_serialize(&self, _data: Rc<()>) -> Result<(), Error> {
        unimplemented!();
    }
}
Run Code Online (Sandbox Code Playgroud)

这无法编译,现在抱怨Rc<()>不是Send

error: future cannot be sent between threads safely
  --> src/main.rs:19:73
   |
19 |       async fn async_serialize(&self, _data: Rc<()>) -> Result<(), Error> {
   |  _________________________________________________________________________^
20 | |         unimplemented!();
21 | |     }
   | |_____^ future created by async block is not `Send`
   |
   = help: within `impl Future<Output = Result<(), anyhow::Error>>`, the trait `Send` is not implemented for `Rc<()>`
note: captured value is not `Send`
Run Code Online (Sandbox Code Playgroud)

这个错误消息对我来说很有意义,Rc不是Send,但是:

  • 为什么这在以前不是问题?之前的实现(impl on Fooimpl AsyncSerializer for Foo)对我来说看起来很相似。
  • 我可以data用某种方式包裹来避免这种情况吗?

Ian*_* S. 5

代码脱糖的方式#[async_trait]需要发送 future,如此处所述。要解决此问题,请将属性宏更改为#[async_trait(?Send)].