title: How can I use an async lambda in an async method of this async trait?
body: <p>I'm trying to reproduce in Rust what I did in Golang using Clean Architecture with Repository pattern.</p>
  <p><a href="https://github.com/frederikhors/rust-trait-with-async-fn-with-async-closures" rel="nofollow noreferrer">The code in this repo is a small reproduction</a>.</p>
  <p>It works in both <a href="https://github.com/frederikhors/rust-trait-with-async-fn-with-async-closures/commit/35e2bc71885b53f6b78aa45062bf82ea6b3088e4" rel="nofollow noreferrer">first</a> and <a href="https://github.com/frederikhors/rust-trait-with-async-fn-with-async-closures/commit/b98fa9c43038c52a1b8e02b8c8f487fce8effb7d" rel="nofollow noreferrer">second</a> commit.</p>
  <p>But <a href="https://github.com/frederikhors/rust-trait-with-async-fn-with-async-closures/commit/c1a58c29ee7edf0f52ce17a547c251d3ade387d5" rel="nofollow noreferrer">when I add a lambda as argument of an async function</a> in the async trait the error on <a href="https://github.com/frederikhors/rust-trait-with-async-fn-with-async-closures/blob/main/src/main.rs#L60" rel="nofollow noreferrer">line 60</a> is:</p>
  <pre><code>future cannot be sent between threads safely
  the trait `std::marker::Sync` is not implemented for `dyn std::ops::FnMut(&amp;'life3 Player) -&gt; std::result::Result&lt;Player, ()&gt;`
  required for the cast to the object type `dyn std::future::Future&lt;Output = std::result::Result&lt;(), ()&gt;&gt; + std::marker::Send`rustc
  main.rs(59, 9): captured value is not `Send` because `&amp;` references cannot be sent unless their referent is `Sync`
  </code></pre>
  <p>I do not understand what to do and I don't know if this is a correct pattern.</p>
  <p>In Golang this is a very useful (and easy) patter to share in a DB transaction an element between repository code and business logic:</p>
  <ul>
  <li>the repository function get the player from DB</li>
  <li>it calls the lambda (or an async anonym function, in Golang there is no closure like in Rust) with this existing player</li>
  <li>the business logic code works with this existing player in the same DB transaction</li>
  <li>the business logic code can return the &quot;updated&quot; player to save or an error to the repository code</li>
  <li>the repository can continue or abort the DB transaction</li>
  </ul>
  <p><strong>Is this a correct way to do things in Rust?</strong></p>
  <p>If not, what alternatives?</p>
  <p>If yes, how to fix this code?</p>
  <h3>Code</h3>
  <ul>
  <li>main.rs:</li>
  </ul>
  <pre class="lang-rust prettyprint-override"><code>use std::sync::{Arc, Mutex};
  
  #[derive(Clone)]
  struct Player {
      pub name: String,
      pub payed: bool,
  }
  
  #[async_trait::async_trait]
  trait RepoMemory {
      async fn player_create(&amp;self, name: &amp;str, payed: bool) -&gt; Result&lt;Player, ()&gt;;
  
      async fn player_delete(
          &amp;self,
          id: &amp;str,
          // lambda: impl FnMut(&amp;Player) -&gt; Result&lt;Player, ()&gt;,
          lambda: &amp;dyn FnMut(&amp;Player) -&gt; Result&lt;Player, ()&gt;,
      ) -&gt; Result&lt;(), ()&gt;;
  }
  
  struct InMemoryRepository {
      pub players: Mutex&lt;Vec&lt;Player&gt;&gt;,
  }
  
  impl InMemoryRepository {
      pub fn new() -&gt; Self {
          Self {
              players: Mutex::new(vec![]),
          }
      }
  }
  
  #[async_trait::async_trait]
  impl RepoMemory for InMemoryRepository {
      async fn player_create(&amp;self, name: &amp;str, payed: bool) -&gt; Result&lt;Player, ()&gt; {
          let mut players = self.players.lock().unwrap();
  
          if players.iter().any(|player| player.name == name) {
              println!(&quot;Player {} already exists!&quot;, name);
  
              return Err(());
          }
  
          let new_player = Player {
              name: name.to_string(),
              payed,
          };
  
          players.push(new_player.clone());
  
          println!(&quot;Player {} created&quot;, &amp;name);
  
          Ok(new_player)
      }
  
      async fn player_delete(
          &amp;self,
          name: &amp;str,
          lambda: &amp;dyn FnMut(&amp;Player) -&gt; Result&lt;Player, ()&gt;,
      ) -&gt; Result&lt;(), ()&gt; {
          let mut players = self.players.lock().unwrap();
  
          match players.iter().position(|player| player.name == name) {
              Some(index) =&gt; {
                  let player = players.get(index).unwrap();
  
                  lambda(player)?;
  
                  players.remove(index);
  
                  println!(&quot;Player {} deleted&quot;, name);
  
                  Ok(())
              }
              None =&gt; {
                  println!(&quot;Cannot find player {}!&quot;, name);
  
                  Err(())
              }
          }
      }
  }
  
  struct CreateCommand {
      repo: Arc&lt;dyn RepoMemory&gt;,
  }
  
  impl CreateCommand {
      pub fn new(repo: Arc&lt;dyn RepoMemory&gt;) -&gt; Self {
          Self { repo }
      }
  
      pub async fn execute(&amp;self, name: &amp;str, payed: bool) -&gt; Result&lt;Player, ()&gt; {
          let created_player = self.repo.player_create(name, payed).await.unwrap();
  
          Ok(created_player)
      }
  }
  
  struct DeleteCommand {
      repo: Arc&lt;dyn RepoMemory&gt;,
  }
  
  impl DeleteCommand {
      pub fn new(repo: Arc&lt;dyn RepoMemory&gt;) -&gt; Self {
          Self { repo }
      }
  
      #[allow(clippy::result_unit_err)]
      pub async fn execute(&amp;self, name: &amp;str) -&gt; Result&lt;bool, ()&gt; {
          self.repo
              .player_delete(name, &amp;|existing_player| {
                  // I need to work with existing_player here, do some .await calls and return it to repo maybe, for example:
  
                  if existing_player.payed {
                      println!(&quot;Cannot delete paying player {}!&quot;, name);
  
                      return Err(());
                  }
  
                  Ok(existing_player.clone())
              })
              .await?;
  
          Ok(true)
      }
  }
  
  struct Service {
      pub player_create: CreateCommand,
      pub player_delete: DeleteCommand,
  }
  
  fn new_service() -&gt; Service {
      let repo_memory = Arc::new(InMemoryRepository::new());
  
      Service {
          player_create: CreateCommand::new(repo_memory.clone()),
          player_delete: DeleteCommand::new(repo_memory),
      }
  }
  
  #[tokio::main]
  async fn main() {
      let service = new_service();
  
      let bob = Player {
          name: &quot;bob&quot;.to_owned(),
          payed: true,
      };
  
      service
          .player_create
          .execute(&amp;bob.name, bob.payed)
          .await
          .unwrap();
  
      service.player_delete.execute(&amp;bob.name).await.unwrap();
  
      let john = Player {
          name: &quot;john&quot;.to_owned(),
          payed: false,
      };
  
      service
          .player_create
          .execute(&amp;john.name, john.payed)
          .await
          .unwrap();
  
      service.player_delete.execute(&amp;john.name).await.unwrap();
  }
  </code></pre>