How to return a nested MutexGuard?


I need to return a locked reference to a value that is accessed through two mutexes.
Here is an example:

use std::sync::{Mutex, MutexGuard};

struct A {
    val: Mutex<Mutex<u32>>,

impl A {
    pub fn new() -> Self {
        Self {
            val: Mutex::new(Mutex::new(0)),

    pub fn lock(&self) -> MutexGuard<u32> {
        let first_lock = self.val.lock().unwrap();
        let second_lock = first_lock.lock().unwrap();

fn main() {
    let a = A::new();

    *a.lock() = 1;

The code fails to compile:

error[E0515]: cannot return value referencing local variable `first_lock`
  --> src/
16 |         let second_lock = first_lock.lock().unwrap();
   |                           ---------- `first_lock` is borrowed here
17 |         second_lock
   |         ^^^^^^^^^^^ returns a value referencing data owned by the current function

I expected the error, but nevertheless, I don't see how I can return second_lock while it references first_lock. Maybe there is a way to make first_lock own second_lock?

You can't. Both mutex guards must be in scope to access the inner value.


If you make it:


then you can clone the Arc and unlock the outer Mutex immediately. Note however that you can't return a guard borrowing from an Arc that sits in function's local variable, nor return both Arc and a reference to it together, so it will need to be a two-step process where first function call gets Arc<Mutex<u32>>, and then a second one that gets lock out of it. In practice this makes sense for types like Mutex<HashMap<K, Arc<Mutex<u32>>>> where get() is separate from later use.


As others have said, you can't do that.

Would it work for you to replace the lock() method with a do_locked() method that takes an FnOnce that you call with the locks held?


This is possible if you switch to the mutexes provided by the parking_lot crate and enable the arc_lock feature. In this case, the guard object you get back will hold its own internal clone of the Arc that was used to take the lock originally.


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.