How to return value referencing local variable?

use std::{collections::VecDeque, collections::HashMap, sync::Arc};
use tokio::sync::Mutex;

struct Employee {
    name: String,
    old: u32,
}

struct Department{
    employees: Arc<Mutex<VecDeque<Employee>>>,
}

struct Company{
    Departments: Arc<Mutex<HashMap<u32, Department>>>, //DepartmentID: u32
}

impl Company {
    pub async fn get_department(&self, id: u32) -> Option<&Department>{
        let mut department = self.Departments.lock().await;
       department.get(&id) // err: cannot return value referencing local variable `department` returns a value referencing data owned by the current function
    }
}

#[tokio::main]
async fn main(){
    let company = Company { Departments: Arc::new(Mutex::new(HashMap::new())), };
    let department1 = company.get_department(1);
}

You can't. If you need to access something inside Mutex, you have to return the MutexGuard.

3 Likes

So, what is solutions to return &Department value?. I want to get a department in company by id

You can't. A reference to the inside of the mutex can't live longer than the MutexGuard that you get from locking. So you have to return the guard object instead and then use that to get to the Department data.

You might have better luck if you use a proper concurrent hashmap like dashmap instead of Mutex<HashMap<_>, though i think it also works through guard objects that you'd have to return.

3 Likes

Since you're using tokio's Mutex you could use MutexGuard::try_map to map the MutexGuard

1 Like

Since your department type is reference counted with an Arc, you could just clone it to get another shared handle to the same value and return the clone.

1 Like

You can return Department (owned copy), or Box<Department> if you want to return it by pointer. You can return Arc<Department> if you want to return a shared reference that isn't temporary. Mutex<HashMap<K, Arc<V>> is a common pattern in such case.

But you can't return a temporary unprotected borrow of a mutex-protected value. This is literally unsafe — some other thread/future could mutate the HashMap and change or remove the Department as soon as the MutexGuard is dropped, leaving you with a data race or a dangling pointer. In this case it's not a limitation of the borrow checker, but you have an actual concurrency bug in your code that the compiler is catching.

1 Like