From 12c5b2164a42ba1cf99443aacae72f00c9a12339 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 6 Feb 2025 10:47:51 -0800 Subject: [PATCH] fix(maitake-sync): impl `Future` for `mutex::Lock` with generic `ScopedRawMutex` (#517) This commit fixes the trait bounds on the `mutex::Lock` type's `Future` implementation so that it's present when used with an overridden `ScopedRawMutex`, as well as the default `DefaultMutex`. Thanks to @peterkrull for reporting this issue in [this comment][1]! As noted in #516, I've also added tests for this, which wouldn't have compiled prior to this change. [1]: https://github.com/hawkw/mycelium/pull/515#issuecomment-2639729506 --- maitake-sync/src/mutex.rs | 8 ++++-- maitake-sync/src/mutex/tests.rs | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/maitake-sync/src/mutex.rs b/maitake-sync/src/mutex.rs index af71c6e0..62b98176 100644 --- a/maitake-sync/src/mutex.rs +++ b/maitake-sync/src/mutex.rs @@ -348,8 +348,12 @@ where // === impl Lock === -impl<'a, T> Future for Lock<'a, T> { - type Output = MutexGuard<'a, T>; +impl<'a, T, L> Future for Lock<'a, T, L> +where + T: ?Sized, + L: ScopedRawMutex, +{ + type Output = MutexGuard<'a, T, L>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); diff --git a/maitake-sync/src/mutex/tests.rs b/maitake-sync/src/mutex/tests.rs index 813b7f65..43b7b147 100644 --- a/maitake-sync/src/mutex/tests.rs +++ b/maitake-sync/src/mutex/tests.rs @@ -1,3 +1,5 @@ +use mutex_traits::ScopedRawMutex; + use crate::loom::{self, future}; use crate::Mutex; @@ -54,3 +56,50 @@ fn basic_multi_threaded() { }) }); } + +struct NopRawMutex; + +unsafe impl ScopedRawMutex for NopRawMutex { + fn try_with_lock(&self, _: impl FnOnce() -> R) -> Option { + None + } + + fn with_lock(&self, _: impl FnOnce() -> R) -> R { + unimplemented!("this doesn't actually do anything") + } + + fn is_locked(&self) -> bool { + true + } +} + +fn assert_future(_: F) {} + +#[test] +fn lock_future_impls_future() { + loom::model(|| { + // Mutex with `DefaultMutex` as the `ScopedRawMutex` implementation + let mutex = Mutex::new(()); + assert_future(mutex.lock()); + + // Mutex with a custom `ScopedRawMutex` implementation + let mutex = Mutex::new_with_raw_mutex((), NopRawMutex); + assert_future(mutex.lock()); + }) +} + +#[test] +#[cfg(feature = "alloc")] +fn lock_owned_future_impls_future() { + loom::model(|| { + use alloc::sync::Arc; + + // Mutex with `DefaultMutex` as the `ScopedRawMutex` implementation + let mutex = Arc::new(Mutex::new(())); + assert_future(mutex.lock_owned()); + + // Mutex with a custom `ScopedRawMutex` implementation + let mutex = Arc::new(Mutex::new_with_raw_mutex((), NopRawMutex)); + assert_future(mutex.lock_owned()); + }) +}