Why Send requires Sync in this case?

On this very simple example, I require OnConsume to be a Send function so I can send it to threads.

use std::sync::Arc;

trait EncodedPacket {}

pub type OnConsume = Arc<dyn Fn() -> Option<Box<dyn EncodedPacket>> + Send>;

pub trait Decoder: Send{}

pub struct DummyDecoder {
    pub on_consume: Option<OnConsume>,
}

impl Decoder for DummyDecoder {}

Playground

I'm getting this error about Sync though.

Error:

error[E0277]: `(dyn Fn() -> Option<Box<(dyn EncodedPacket + 'static)>> + Send + 'static)` cannot be shared between threads safely
  --> src/lib.rs:14:6
   |
7  | pub trait Decoder: Send
   |                    ---- required by this bound in `Decoder`
...
14 | impl Decoder for DummyDecoder {
   |      ^^^^^^^ `(dyn Fn() -> Option<Box<(dyn EncodedPacket + 'static)>> + Send + 'static)` cannot be shared between threads safely
   |
   = help: the trait `Sync` is not implemented for `(dyn Fn() -> Option<Box<(dyn EncodedPacket + 'static)>> + Send + 'static)`
   = note: required because of the requirements on the impl of `Send` for `Arc<(dyn Fn() -> Option<Box<(dyn EncodedPacket + 'static)>> + Send + 'static)>`
   = note: required because it appears within the type `Option<Arc<(dyn Fn() -> Option<Box<(dyn EncodedPacket + 'static)>> + Send + 'static)>>`
note: required because it appears within the type `DummyDecoder`
  --> src/lib.rs:10:12
   |
10 | pub struct DummyDecoder {

Why is it that it requires Sync for (dyn Fn() -> Option<Box<(dyn EncodedPacket + 'static)>> + Send + 'static)?

It's because you're putting it in an Arc, and for Arc to be Send its contents have to be Sync.

Here's a great post on Send and Sync.

3 Likes

The meaning of Sync is that the value may be immutably accessed from several threads at the same time, which your Arc would let you do if it was Send.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.