From 04f86304422cfc74a46ee7d53d04eb1e56572599 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Mon, 23 Oct 2023 16:36:13 -0500 Subject: [PATCH] Add comment about `Mapped(Mutex|RwLockWrite)Guard` variance. --- library/std/src/sync/mutex.rs | 28 +++++++++++-------- library/std/src/sync/rwlock.rs | 50 ++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 18bea6d58fba1..a435fba4f1ea2 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -238,9 +238,13 @@ unsafe impl Sync for MutexGuard<'_, T> {} #[must_not_suspend = "holding a MappedMutexGuard across suspend \ points can cause deadlocks, delays, \ and cause Futures to not implement `Send`"] -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] #[clippy::has_significant_drop] pub struct MappedMutexGuard<'a, T: ?Sized + 'a> { + // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a + // `MappedMutexGuard` argument doesn't hold uniqueness for its whole scope, only until it drops. + // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field + // below for the correct variance over `T` (invariance). data: NonNull, inner: &'a sys::Mutex, poison_flag: &'a poison::Flag, @@ -248,9 +252,9 @@ pub struct MappedMutexGuard<'a, T: ?Sized + 'a> { _variance: PhantomData<&'a mut T>, } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl !Send for MappedMutexGuard<'_, T> {} -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] unsafe impl Sync for MappedMutexGuard<'_, T> {} impl Mutex { @@ -602,7 +606,7 @@ impl<'a, T: ?Sized> MutexGuard<'a, T> { /// This is an associated function that needs to be used as /// `MutexGuard::map(...)`. A method would interfere with methods of the /// same name on the contents of the `MutexGuard` used through `Deref`. - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn map(orig: Self, f: F) -> MappedMutexGuard<'a, U> where F: FnOnce(&mut T) -> &mut U, @@ -629,7 +633,7 @@ impl<'a, T: ?Sized> MutexGuard<'a, T> { /// `MutexGuard::try_map(...)`. A method would interfere with methods of the /// same name on the contents of the `MutexGuard` used through `Deref`. #[doc(alias = "filter_map")] - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn try_map(orig: Self, f: F) -> Result, Self> where F: FnOnce(&mut T) -> Option<&mut U>, @@ -649,7 +653,7 @@ impl<'a, T: ?Sized> MutexGuard<'a, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl Deref for MappedMutexGuard<'_, T> { type Target = T; @@ -658,14 +662,14 @@ impl Deref for MappedMutexGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl DerefMut for MappedMutexGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { unsafe { self.data.as_mut() } } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl Drop for MappedMutexGuard<'_, T> { #[inline] fn drop(&mut self) { @@ -676,14 +680,14 @@ impl Drop for MappedMutexGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl fmt::Debug for MappedMutexGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl fmt::Display for MappedMutexGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) @@ -699,7 +703,7 @@ impl<'a, T: ?Sized> MappedMutexGuard<'a, T> { /// This is an associated function that needs to be used as /// `MutexGuard::map(...)`. A method would interfere with methods of the /// same name on the contents of the `MutexGuard` used through `Deref`. - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn map(orig: Self, f: F) -> MappedMutexGuard<'a, U> where F: FnOnce(&mut T) -> &mut U, @@ -726,7 +730,7 @@ impl<'a, T: ?Sized> MappedMutexGuard<'a, T> { /// `MutexGuard::try_map(...)`. A method would interfere with methods of the /// same name on the contents of the `MutexGuard` used through `Deref`. #[doc(alias = "filter_map")] - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn try_map(orig: Self, f: F) -> Result, Self> where F: FnOnce(&mut T) -> Option<&mut U>, diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 717f40db4c1c6..def0c8a16c7ce 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -158,7 +158,7 @@ unsafe impl Sync for RwLockWriteGuard<'_, T> {} #[must_not_suspend = "holding a MappedRwLockReadGuard across suspend \ points can cause deadlocks, delays, \ and cause Futures to not implement `Send`"] -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] #[clippy::has_significant_drop] pub struct MappedRwLockReadGuard<'a, T: ?Sized + 'a> { // NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a @@ -169,10 +169,10 @@ pub struct MappedRwLockReadGuard<'a, T: ?Sized + 'a> { inner_lock: &'a sys::RwLock, } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl !Send for MappedRwLockReadGuard<'_, T> {} -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] unsafe impl Sync for MappedRwLockReadGuard<'_, T> {} /// RAII structure used to release the exclusive write access of a lock when @@ -187,9 +187,13 @@ unsafe impl Sync for MappedRwLockReadGuard<'_, T> {} #[must_not_suspend = "holding a MappedRwLockWriteGuard across suspend \ points can cause deadlocks, delays, \ and cause Future's to not implement `Send`"] -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] #[clippy::has_significant_drop] pub struct MappedRwLockWriteGuard<'a, T: ?Sized + 'a> { + // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a + // `MappedRwLockWriteGuard` argument doesn't hold uniqueness for its whole scope, only until it drops. + // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field + // below for the correct variance over `T` (invariance). data: NonNull, inner_lock: &'a sys::RwLock, poison_flag: &'a poison::Flag, @@ -197,10 +201,10 @@ pub struct MappedRwLockWriteGuard<'a, T: ?Sized + 'a> { _variance: PhantomData<&'a mut T>, } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl !Send for MappedRwLockWriteGuard<'_, T> {} -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] unsafe impl Sync for MappedRwLockWriteGuard<'_, T> {} impl RwLock { @@ -621,28 +625,28 @@ impl fmt::Display for RwLockWriteGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl fmt::Debug for MappedRwLockReadGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl fmt::Display for MappedRwLockReadGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl fmt::Debug for MappedRwLockWriteGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl fmt::Display for MappedRwLockWriteGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) @@ -677,7 +681,7 @@ impl DerefMut for RwLockWriteGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl Deref for MappedRwLockReadGuard<'_, T> { type Target = T; @@ -688,7 +692,7 @@ impl Deref for MappedRwLockReadGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl Deref for MappedRwLockWriteGuard<'_, T> { type Target = T; @@ -699,7 +703,7 @@ impl Deref for MappedRwLockWriteGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl DerefMut for MappedRwLockWriteGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { // SAFETY: the conditions of `RwLockWriteGuard::new` were satisfied when the original guard @@ -729,7 +733,7 @@ impl Drop for RwLockWriteGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl Drop for MappedRwLockReadGuard<'_, T> { fn drop(&mut self) { // SAFETY: the conditions of `RwLockReadGuard::new` were satisfied when the original guard @@ -740,7 +744,7 @@ impl Drop for MappedRwLockReadGuard<'_, T> { } } -#[unstable(feature = "mapped_lock_guards", issue = "none")] +#[unstable(feature = "mapped_lock_guards", issue = "117108")] impl Drop for MappedRwLockWriteGuard<'_, T> { fn drop(&mut self) { self.poison_flag.done(&self.poison); @@ -762,7 +766,7 @@ impl<'a, T: ?Sized> RwLockReadGuard<'a, T> { /// `RwLockReadGuard::map(...)`. A method would interfere with methods of /// the same name on the contents of the `RwLockReadGuard` used through /// `Deref`. - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn map(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U> where F: FnOnce(&T) -> &U, @@ -784,7 +788,7 @@ impl<'a, T: ?Sized> RwLockReadGuard<'a, T> { /// of the same name on the contents of the `RwLockReadGuard` used through /// `Deref`. #[doc(alias = "filter_map")] - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn try_map(orig: Self, f: F) -> Result, Self> where F: FnOnce(&T) -> Option<&U>, @@ -808,7 +812,7 @@ impl<'a, T: ?Sized> MappedRwLockReadGuard<'a, T> { /// `MappedRwLockReadGuard::map(...)`. A method would interfere with /// methods of the same name on the contents of the `MappedRwLockReadGuard` /// used through `Deref`. - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn map(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U> where F: FnOnce(&T) -> &U, @@ -830,7 +834,7 @@ impl<'a, T: ?Sized> MappedRwLockReadGuard<'a, T> { /// methods of the same name on the contents of the `MappedRwLockReadGuard` /// used through `Deref`. #[doc(alias = "filter_map")] - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn try_map(orig: Self, f: F) -> Result, Self> where F: FnOnce(&T) -> Option<&U>, @@ -854,7 +858,7 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> { /// `RwLockWriteGuard::map(...)`. A method would interfere with methods of /// the same name on the contents of the `RwLockWriteGuard` used through /// `Deref`. - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn map(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U> where F: FnOnce(&mut T) -> &mut U, @@ -882,7 +886,7 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> { /// of the same name on the contents of the `RwLockWriteGuard` used through /// `Deref`. #[doc(alias = "filter_map")] - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn try_map(orig: Self, f: F) -> Result, Self> where F: FnOnce(&mut T) -> Option<&mut U>, @@ -912,7 +916,7 @@ impl<'a, T: ?Sized> MappedRwLockWriteGuard<'a, T> { /// `MappedRwLockWriteGuard::map(...)`. A method would interfere with /// methods of the same name on the contents of the `MappedRwLockWriteGuard` /// used through `Deref`. - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn map(orig: Self, f: F) -> MappedRwLockWriteGuard<'a, U> where F: FnOnce(&mut T) -> &mut U, @@ -940,7 +944,7 @@ impl<'a, T: ?Sized> MappedRwLockWriteGuard<'a, T> { /// methods of the same name on the contents of the `MappedRwLockWriteGuard` /// used through `Deref`. #[doc(alias = "filter_map")] - #[unstable(feature = "mapped_lock_guards", issue = "none")] + #[unstable(feature = "mapped_lock_guards", issue = "117108")] pub fn try_map(orig: Self, f: F) -> Result, Self> where F: FnOnce(&mut T) -> Option<&mut U>,