I was experimenting with the async_trait crate and stumble upon the following error:

future created by async block is not Send

by the following code:

#[async_trait::async_trait] trait DatabaseManagerGetConnection { async fn get_connection(&self) -> Option<()>; } #[async_trait::async_trait] trait EntityRepositoryExecute { async fn execute (&self) -> Option<()>; } trait TableMapperToEntity { fn to_entity(&self) -> Option<()>; } struct DatabaseManager { sqlx_db_pool: sqlx::Pool<sqlx::Postgres> } #[async_trait::async_trait] impl DatabaseManagerGetConnection for DatabaseManager { async fn get_connection(&self) -> Option<()> { Some(()) } } struct EntityRepository <D: DatabaseManagerGetConnection>{ database_manager: std::sync::Arc<D> } #[async_trait::async_trait] // impl <D: DatabaseManagerGetConnection + Send + Sync> EntityRepositoryExecute for EntityRepository<D> { impl <D: DatabaseManagerGetConnection> EntityRepositoryExecute for EntityRepository<D> { async fn execute(&self) -> Option<()>{ self.database_manager.get_connection().await.unwrap(); Some(()) } } fn main() { } 

After a couple hours trying to understand the issue I tried to swap Line 32

impl <D: DatabaseManagerGetConnection> EntityRepositoryExecute for EntityRepository<D> {

with line Line 31:

impl <D: DatabaseManagerGetConnection + Send + Sync> EntityRepositoryExecute for EntityRepository<D> {

and the error went way. But I still confused on:

  • why I would need to add Send and Sync trait to the D: DatabaseManagerGetConnection?
    • My understanding was that async_trait::async_trait macro was already adding these "guarantees" (traits) to the DatabaseManagerGetConnection trait return itself.
  • As far as I am aware:
    • Arc implements Send + Sync
    • and sqlx::Pool<sqlx::Postgres> also implements Send + Sync

What am I missing?

4 posts - 3 participants

Read full topic