Try-Bind implementations

I've stumbled upon this pattern three times in three different code bases. I'll name it Try-Bind: First search for a match, then use the match.

I might be approaching this wrong.

...
let api = api.clone();

tokio::spawn(async move {
    let handlers: &[&dyn MessageHandler] = &[&Shrug, &Reqex];

    for handler in handlers {
        let handler = handler;
        if handler.test(&message).await {
            _ = handler.handle(message, api).await;
            return
        }
    }
});

Ideally I'd loop through all implementors of MessageHandler automatically, but here I listed them manually.

#[async_trait]
trait MessageHandler {
    async fn test(&self, message: &Message) -> bool;
    async fn handle(&self, message: Message, api: AsyncApi) -> Option<()>;
}
struct Shrug;
#[async_trait]
impl MessageHandler for Shrug {
    async fn test(&self, message: &Message) -> bool {
        message.text.as_ref().is_some_and(|t| t == "/shrug")
    }

    async fn handle(&self, message: Message, api: AsyncApi) -> Option<()> {
        let result_message = SendMessageParams::builder()
            .chat_id(message.chat.id)
            .text("¯\\_(ツ)_/¯")
            .build();

        if let Err(err) = api.send_message(&result_message).await {
            println!("Failed to send shrug: {err:?}");
            return None;
        }

        Some(())
    }
}
error: future cannot be sent between threads safely
   --> src/main.rs:34:29
    |
34  | ...                   tokio::spawn(async move {
    |                       ^^^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: within `&dyn MessageHandler`, the trait `Sync` is not implemented for `dyn MessageHandler`
note: future is not `Send` as this value is used across an await
   --> src/main.rs:39:63
    |
37  | ...                   for handler in handlers {
    |                                      -------- has type `std::slice::Iter<'_, &dyn MessageHandler>` which is not `Send`
38  | ...                       let handler = handler;
39  | ...                       if handler.test(&message).await {
    |                                                     ^^^^^ await occurs here, with `handlers` maybe used later
note: required by a bound in `tokio::spawn`
   --> /home/jc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.35.1/src/task/spawn.rs:166:21
    |
164 |     pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
    |            ----- required by a bound in this function
165 |     where
166 |         F: Future + Send + 'static,
    |                     ^^^^ required by this bound in `spawn`


I have tried a dozen ways to shape the (in this case) MessageHandler functions.

Every dyn type is assumed to not be thread-safe unless specified otherwise. Change the type from &[&dyn MessageHandler] to &[&dyn MessageHandler + Sync].

Or, add a supertrait bound to MessageHandler:

trait MessageHandler: Sync {

These have the same effect except that the supertrait bound affects all uses of MessageHandler.