Getting deadlock inside match of async function

I'm getting a deadlock on the following example:

use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use futures::lock::Mutex;
use std::sync::Arc;

struct A{

impl A {
    pub async fn do_something(&self) -> std::result::Result<(), ()>{

async fn lock_and_use(a: Arc<Mutex<A>>) {
    match a.clone().lock().await.do_something().await {
        Ok(()) => {
        Err(()) => {
            //try again on error
            println!("trying again");

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let a = Arc::new(Mutex::new(A{}));


If I did this:


there would be no problem, the lock() dies on the same line it's created. I thought this principle would be the same for match. If you think about match, it locks the value, calls do_something, awaits on it, and then compares the value. It's true that do_something returns a future which capture the self, but when we await on it, it should discard the self. Why it still holds self? How can I solve this without cloning the result?

You need to do this:

let value = a.clone().lock().await.do_something().await;
match value {

Consider also reading these articles:

  1. Shared state - Tokio tutorial
  2. Async: What is blocking?

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.