1

I wrote this example (not working):

use std::sync::Mutex;
use std::ops::Deref;

pub struct DBAndCFs {
    db: i32,
    cfs: Vec<i32>,
}

fn main() {
    let x: Mutex<Option<DBAndCFs>> = Mutex::new(Some(DBAndCFs{ db: 0, cfs: Vec::new() } ));
    let DBAndCFs { ref db, ref cfs } = x.lock().unwrap().deref();
}

I have been following the docs but I am still unable to assign the dband cfsfields to the variables on the left.

John Difool
  • 5,572
  • 5
  • 45
  • 80

1 Answers1

4

Mutex::lock() returns Result<MutexGuard, PoisonError>. The first .unwrap() unwraps this Result. You need another .unwrap() to unwrap the Option, and also .as_ref() to not move out of it:

let DBAndCFs { ref db, ref cfs } = x.lock().unwrap().as_ref().unwrap();

You also don't need the ref because of match ergonomics (see What does pattern-matching a non-reference against a reference do in Rust?):

let DBAndCFs { db, cfs } = x.lock().unwrap().as_ref().unwrap();
Jmb
  • 18,893
  • 2
  • 28
  • 55
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
  • as_ref(); ^^^^^^ method not found in `DBAndCFs ` – John Difool Feb 17 '22 at 23:48
  • see above please. as_ref() is not avail in the unwrap type, which seems strange as it's not even a DBAndCFs at this point in the chain. – John Difool Feb 18 '22 at 01:40
  • @JohnDifool [It does work on the playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4e836bfd6a323503e9570760ec96deb0). So if it does not work with your code then your MRE is wrong. The probable reason is that you don't use `std::sync::Mutex` but another mutex (e.g. `parking_lot::Mutex` or `tokio::sync::Mutex`). These do not implement [Lock Poisoning](https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#poisoning) and thus their `lock()` method does not return a `Result` but immediately a guard, so the first `.unwrap()` is redundant. – Chayim Friedman Feb 18 '22 at 06:40
  • You are right. I had to switch to parking_lot::Mutex because the rest of the lib is using it. I am still having an issue with as_ref() as I think the vec is not a vector of int32 but a vec of structs that don't have AsRef trait. I'll update the OP with an EDIT. – John Difool Feb 18 '22 at 06:59
  • Actually, I opted to close this question because the `self.db.lock().as_ref().unwrap()` did the work with `parking_lot::Mutex`. I have another issue with creating a temporary which is freed while still in use, but i decided to post another question about it. – John Difool Feb 18 '22 at 08:09