在下面的代码中:
use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::{LockResult, PoisonError};
pub struct MutexGuardOptionRef<'a, T: ?Sized> {
pub mutex_guard: MutexGuard<'a, Option<Box<T>>>,
}
pub trait LockableOption<T: ?Sized> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>>;
}
pub type LockableArc<T> = Arc<Mutex<Option<T>>>;
impl<T> LockableOption<T> for LockableArc<Box<T>> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>> {
let mutex_guard = self.lock();
match mutex_guard {
Ok(m) => Ok(MutexGuardOptionRef{
mutex_guard: m
}),
_ => unimplemented!()
}
}
}
我们有
impl<T> LockableOption<T> for LockableArc<Box<T>> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>> {
因为我们正在为 LockableArc<Box<T>>
实现,那么 self: LockableArc<Box<T>>
,所以调用 self.lock()
会调用 LobkcableArc::lock
,它是 Mutex::lock
,它应该给 {{1} },但它说它给了 MutexGuard
:
错误:
MutexGuardOptionRef
发生了什么?
答案 0 :(得分:2)
您看到此问题的原因是您的 self.lock
调用实际上是递归的。即 self.lock()
调用 LockableArc<Box<T>::lock
,而不是 lock
上的 Mutex
方法。因此,m
的类型是 MutexGuardOptionRef
,而不是 MutexGuard<'a, Option<Box<T>>
。如果您将 mutex_guard: m
更改为 mutex_guard: m.mutex_guard
,编译器会警告您此调用是无条件递归的。
显然,该更改将修复编译错误,但由于它总是会递归,因此您实际上不会想要这样做。相反,您可能需要更精确地指定要调用的方法,如 Mutex::lock(self)
,如下所示:
use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::LockResult;
pub struct MutexGuardOptionRef<'a, T: ?Sized> {
pub mutex_guard: MutexGuard<'a, Option<Box<T>>>,
}
pub trait LockableOption<T: ?Sized> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>>;
}
pub type LockableArc<T> = Arc<Mutex<Option<T>>>;
impl<T> LockableOption<T> for LockableArc<Box<T>> {
fn lock(&self) -> LockResult<MutexGuardOptionRef<T>> {
let mutex_guard = Mutex::lock(self);
match mutex_guard {
Ok(m) => Ok(MutexGuardOptionRef{
mutex_guard: m
}),
_ => unimplemented!()
}
}
}
这既修复了无条件递归,又为您提供了您期望的类型的结果。