`T` cannot be sent between threads safely with async/await usage

Hello,

Today I have encountered following problem:

provider.rs

#[async_trait]
pub trait SubpageDataProvider<T> where T: Client + std::marker::Sync {
    fn new(&self, _page_config: SubpageConfig, _page_client: T, _max_iterations_num: i32) -> Self; 
    async fn get_subpage_menu_items(&self) -> Result<Vec<MenuItem>, Error>;
}

ks_provider.rs

pub struct KsProvider <T> 
where T: Client {
    _page_config: SubpageConfig,
    _page_client: T,
    _max_iterations_num: i32 // 0 -> disables limit
}

#[async_trait]
impl <T> SubpageDataProvider <T> for KsProvider <T> where T: Client + std::marker::Sync {
    fn new(&self, _page_config: SubpageConfig, _page_client: T, _max_iterations_num: i32) -> Self { 
        Self {
             _page_config,
            _page_client,
            _max_iterations_num 
        }
    }

    async fn get_subpage_menu_items(&self) -> Result<Vec<MenuItem>, Error> {
        let body = self._page_client.get_subpage_html_body(&_request_uri).await?;
    //  ...
    }
}

For following project fragment it refuses to compile due to:

    error[E0277]: `T` cannot be sent between threads safely
  --> src/providers/kwestiasmaku_provider.rs:28:76
   |
28 |       async fn get_subpage_menu_items(&self) -> Result<Vec<MenuItem>, Error> {
   |  ____________________________________________________________________________^
29 | |         let mut _page_menu_items: Vec<MenuItem> = vec![];
30 | |
31 | |         let _a_value_selector = Regex::new(r">(.*?)</a>").unwrap();
...  |
75 | |         Ok(_page_menu_items)
76 | |     }
   | |_____^ `T` cannot be sent between threads safely
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `T`
   = help: consider adding a `where T: std::marker::Send` bound

Could you please help? Do you have any idea why does it happen? As you can see I did add where T: std::marker::Send to trait bound but it didn't solve the problem.

Regards

The code you pasted has a Sync bound but not a Send bound.

Hello,

Now I see... I have added Send but didn't notice that I am also missing Sync. Replacing trait definition to
pub trait SubpageDataProvider where T: Client + std::marker::Sync + std::marker::Send
solved issue.

Just a newbie question, could you please tell me why is that required? Maybe some doc/article about similar usecases?

Thank you for your help!

Regards

In short, T: Send means that it's safe to move unique ownership (T) or unique borrows (&mut T) to one other thread at time.

T: Sync means it's safe for multiple threads to have shared ownership (Arc<T>) or shared borrows (&T) simultaneously.

(I went into longer detail about this in Rust: a unique perspective.)

Many use cases require both (T: Send + Sync) because they might share a value on multiple threads for a while, and then mutate or drop it on a thread that may be different from the one that created it.

1 Like

Thank you a lot!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.