about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/sync/barrier.rs1
-rw-r--r--library/std/src/sync/lazy_lock.rs3
-rw-r--r--library/std/src/sync/mod.rs56
-rw-r--r--library/std/src/sync/once_lock.rs1
-rw-r--r--library/std/src/sync/poison.rs87
-rw-r--r--library/std/src/sync/poison/condvar.rs (renamed from library/std/src/sync/condvar.rs)4
-rw-r--r--library/std/src/sync/poison/condvar/tests.rs (renamed from library/std/src/sync/condvar/tests.rs)0
-rw-r--r--library/std/src/sync/poison/mutex.rs (renamed from library/std/src/sync/mutex.rs)0
-rw-r--r--library/std/src/sync/poison/mutex/tests.rs (renamed from library/std/src/sync/mutex/tests.rs)0
-rw-r--r--library/std/src/sync/poison/once.rs (renamed from library/std/src/sync/once.rs)0
-rw-r--r--library/std/src/sync/poison/once/tests.rs (renamed from library/std/src/sync/once/tests.rs)0
-rw-r--r--library/std/src/sync/poison/rwlock.rs (renamed from library/std/src/sync/rwlock.rs)0
-rw-r--r--library/std/src/sync/poison/rwlock/tests.rs (renamed from library/std/src/sync/rwlock/tests.rs)0
-rw-r--r--library/std/src/sys/sync/once/futex.rs2
-rw-r--r--library/std/src/sys/sync/once/no_threads.rs2
-rw-r--r--library/std/src/sys/sync/once/queue.rs2
-rw-r--r--tests/debuginfo/mutex.rs6
-rw-r--r--tests/debuginfo/rwlock-read.rs4
-rw-r--r--tests/debuginfo/rwlock-write.rs4
-rw-r--r--tests/ui/traits/const-traits/span-bug-issue-121418.stderr2
-rw-r--r--tests/ui/typeck/assign-non-lval-derefmut.stderr4
21 files changed, 141 insertions, 37 deletions
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index 14e4a9abe6f..862753e4765 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -2,6 +2,7 @@
 mod tests;
 
 use crate::fmt;
+// FIXME(nonpoison_mutex,nonpoison_condvar): switch to nonpoison versions once they are available
 use crate::sync::{Condvar, Mutex};
 
 /// A barrier enables multiple threads to synchronize the beginning
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 40510f56134..1e4f9b79e0f 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -1,4 +1,4 @@
-use super::once::ExclusiveState;
+use super::poison::once::ExclusiveState;
 use crate::cell::UnsafeCell;
 use crate::mem::ManuallyDrop;
 use crate::ops::Deref;
@@ -63,6 +63,7 @@ union Data<T, F> {
 /// ```
 #[stable(feature = "lazy_cell", since = "1.80.0")]
 pub struct LazyLock<T, F = fn() -> T> {
+    // FIXME(nonpoison_once): if possible, switch to nonpoison version once it is available
     once: Once,
     data: UnsafeCell<Data<T, F>>,
 }
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 0fb77331293..5b50a3c6ccf 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -167,6 +167,10 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+// No formatting: this file is just re-exports, and their order is worth preserving.
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+// These come from `core` & `alloc` and only in one flavor: no poisoning.
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 pub use core::sync::Exclusive;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -175,40 +179,54 @@ pub use core::sync::atomic;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::sync::{Arc, Weak};
 
+// FIXME(sync_nonpoison,sync_poison_mod): remove all `#[doc(inline)]` once the modules are stabilized.
+
+// These exist only in one flavor: no poisoning.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::barrier::{Barrier, BarrierWaitResult};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::condvar::{Condvar, WaitTimeoutResult};
 #[stable(feature = "lazy_cell", since = "1.80.0")]
 pub use self::lazy_lock::LazyLock;
-#[unstable(feature = "mapped_lock_guards", issue = "117108")]
-pub use self::mutex::MappedMutexGuard;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::mutex::{Mutex, MutexGuard};
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-pub use self::once::{ONCE_INIT, Once, OnceState};
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub use self::once_lock::OnceLock;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
 #[unstable(feature = "reentrant_lock", issue = "121440")]
 pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
-#[unstable(feature = "mapped_lock_guards", issue = "117108")]
-pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
+
+// These make sense and exist only with poisoning.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
+#[doc(inline)]
+pub use self::poison::{LockResult, PoisonError};
+
+// These (should) exist in both flavors: with and without poisoning.
+// FIXME(sync_nonpoison): implement nonpoison versions:
+//  * Mutex (nonpoison_mutex)
+//  * Condvar (nonpoison_condvar)
+//  * Once (nonpoison_once)
+//  * RwLock (nonpoison_rwlock)
+// The historical default is the version with poisoning.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(inline)]
+pub use self::poison::{
+    Mutex, MutexGuard, TryLockError, TryLockResult,
+    Condvar, WaitTimeoutResult,
+    Once, OnceState,
+    RwLock, RwLockReadGuard, RwLockWriteGuard,
+};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(inline)]
+#[expect(deprecated)]
+pub use self::poison::ONCE_INIT;
+#[unstable(feature = "mapped_lock_guards", issue = "117108")]
+#[doc(inline)]
+pub use self::poison::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
 
 #[unstable(feature = "mpmc_channel", issue = "126840")]
 pub mod mpmc;
 pub mod mpsc;
 
+#[unstable(feature = "sync_poison_mod", issue = "134646")]
+pub mod poison;
+
 mod barrier;
-mod condvar;
 mod lazy_lock;
-mod mutex;
-pub(crate) mod once;
 mod once_lock;
-mod poison;
 mod reentrant_lock;
-mod rwlock;
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index 0ae3cf4df36..49f2dafd8fd 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -101,6 +101,7 @@ use crate::sync::Once;
 /// ```
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub struct OnceLock<T> {
+    // FIXME(nonpoison_once): switch to nonpoison version once it is available
     once: Once,
     // Whether or not the value is initialized is tracked by `once.is_completed()`.
     value: UnsafeCell<MaybeUninit<T>>,
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index 9eb900c2103..1b8809734b8 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -1,3 +1,78 @@
+//! Synchronization objects that employ poisoning.
+//!
+//! # Poisoning
+//!
+//! All synchronization objects in this module implement a strategy called "poisoning"
+//! where if a thread panics while holding the exclusive access granted by the primitive,
+//! the state of the primitive is set to "poisoned".
+//! This information is then propagated to all other threads
+//! to signify that the data protected by this primitive is likely tainted
+//! (some invariant is not being upheld).
+//!
+//! The specifics of how this "poisoned" state affects other threads
+//! depend on the primitive. See [#Overview] bellow.
+//!
+//! For the alternative implementations that do not employ poisoning,
+//! see `std::sys::nonpoisoning`.
+//!
+//! # Overview
+//!
+//! Below is a list of synchronization objects provided by this module
+//! with a high-level overview for each object and a description
+//! of how it employs "poisoning".
+//!
+//! - [`Condvar`]: Condition Variable, providing the ability to block
+//!   a thread while waiting for an event to occur.
+//!
+//!   Condition variables are typically associated with
+//!   a boolean predicate (a condition) and a mutex.
+//!   This implementation is associated with [`poison::Mutex`](Mutex),
+//!   which employs poisoning.
+//!   For this reason, [`Condvar::wait()`] will return a [`LockResult`],
+//!   just like [`poison::Mutex::lock()`](Mutex::lock) does.
+//!
+//! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at
+//!   most one thread at a time is able to access some data.
+//!
+//!   [`Mutex::lock()`] returns a [`LockResult`],
+//!   providing a way to deal with the poisoned state.
+//!   See [`Mutex`'s documentation](Mutex#poisoning) for more.
+//!
+//! - [`Once`]: A thread-safe way to run a piece of code only once.
+//!   Mostly useful for implementing one-time global initialization.
+//!
+//!   [`Once`] is poisoned if the piece of code passed to
+//!   [`Once::call_once()`] or [`Once::call_once_force()`] panics.
+//!   When in poisoned state, subsequent calls to [`Once::call_once()`] will panic too.
+//!   [`Once::call_once_force()`] can be used to clear the poisoned state.
+//!
+//! - [`RwLock`]: Provides a mutual exclusion mechanism which allows
+//!   multiple readers at the same time, while allowing only one
+//!   writer at a time. In some cases, this can be more efficient than
+//!   a mutex.
+//!
+//!   This implementation, like [`Mutex`], will become poisoned on a panic.
+//!   Note, however, that an `RwLock` may only be poisoned if a panic occurs
+//!   while it is locked exclusively (write mode). If a panic occurs in any reader,
+//!   then the lock will not be poisoned.
+
+// FIXME(sync_nonpoison) add links to sync::nonpoison to the doc comment above.
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::condvar::{Condvar, WaitTimeoutResult};
+#[unstable(feature = "mapped_lock_guards", issue = "117108")]
+pub use self::mutex::MappedMutexGuard;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::mutex::{Mutex, MutexGuard};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[expect(deprecated)]
+pub use self::once::ONCE_INIT;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::once::{Once, OnceState};
+#[unstable(feature = "mapped_lock_guards", issue = "117108")]
+pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 use crate::error::Error;
 use crate::fmt;
 #[cfg(panic = "unwind")]
@@ -5,7 +80,13 @@ use crate::sync::atomic::{AtomicBool, Ordering};
 #[cfg(panic = "unwind")]
 use crate::thread;
 
-pub struct Flag {
+mod condvar;
+#[stable(feature = "rust1", since = "1.0.0")]
+mod mutex;
+pub(crate) mod once;
+mod rwlock;
+
+pub(crate) struct Flag {
     #[cfg(panic = "unwind")]
     failed: AtomicBool,
 }
@@ -78,7 +159,7 @@ impl Flag {
 }
 
 #[derive(Clone)]
-pub struct Guard {
+pub(crate) struct Guard {
     #[cfg(panic = "unwind")]
     panicking: bool,
 }
@@ -316,7 +397,7 @@ impl<T> Error for TryLockError<T> {
     }
 }
 
-pub fn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>
+pub(crate) fn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>
 where
     F: FnOnce(T) -> U,
 {
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/poison/condvar.rs
index 44ffcb528d9..a6e2389c93b 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/poison/condvar.rs
@@ -2,7 +2,7 @@
 mod tests;
 
 use crate::fmt;
-use crate::sync::{LockResult, MutexGuard, PoisonError, mutex, poison};
+use crate::sync::poison::{self, LockResult, MutexGuard, PoisonError, mutex};
 use crate::sys::sync as sys;
 use crate::time::{Duration, Instant};
 
@@ -16,6 +16,8 @@ use crate::time::{Duration, Instant};
 #[stable(feature = "wait_timeout", since = "1.5.0")]
 pub struct WaitTimeoutResult(bool);
 
+// FIXME(sync_nonpoison): `WaitTimeoutResult` is actually poisoning-agnostic, it seems.
+// Should we take advantage of this fact?
 impl WaitTimeoutResult {
     /// Returns `true` if the wait was known to have timed out.
     ///
diff --git a/library/std/src/sync/condvar/tests.rs b/library/std/src/sync/poison/condvar/tests.rs
index f9e9066bc92..f9e9066bc92 100644
--- a/library/std/src/sync/condvar/tests.rs
+++ b/library/std/src/sync/poison/condvar/tests.rs
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/poison/mutex.rs
index e28c2090afe..e28c2090afe 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/poison/mutex.rs
diff --git a/library/std/src/sync/mutex/tests.rs b/library/std/src/sync/poison/mutex/tests.rs
index 395c8aada08..395c8aada08 100644
--- a/library/std/src/sync/mutex/tests.rs
+++ b/library/std/src/sync/poison/mutex/tests.rs
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/poison/once.rs
index 27db4b634fb..27db4b634fb 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/poison/once.rs
diff --git a/library/std/src/sync/once/tests.rs b/library/std/src/sync/poison/once/tests.rs
index ce96468aeb6..ce96468aeb6 100644
--- a/library/std/src/sync/once/tests.rs
+++ b/library/std/src/sync/poison/once/tests.rs
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/poison/rwlock.rs
index 1519baf99a8..1519baf99a8 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/poison/rwlock.rs
diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/poison/rwlock/tests.rs
index 057c2f1a5d7..057c2f1a5d7 100644
--- a/library/std/src/sync/rwlock/tests.rs
+++ b/library/std/src/sync/poison/rwlock/tests.rs
diff --git a/library/std/src/sys/sync/once/futex.rs b/library/std/src/sys/sync/once/futex.rs
index 10bfa81a6d7..539f0fe89ea 100644
--- a/library/std/src/sys/sync/once/futex.rs
+++ b/library/std/src/sys/sync/once/futex.rs
@@ -1,7 +1,7 @@
 use crate::cell::Cell;
 use crate::sync as public;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::once::ExclusiveState;
+use crate::sync::poison::once::ExclusiveState;
 use crate::sys::futex::{Futex, Primitive, futex_wait, futex_wake_all};
 
 // On some platforms, the OS is very nice and handles the waiter queue for us.
diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs
index 88a1d50361e..2568059cfe3 100644
--- a/library/std/src/sys/sync/once/no_threads.rs
+++ b/library/std/src/sys/sync/once/no_threads.rs
@@ -1,6 +1,6 @@
 use crate::cell::Cell;
 use crate::sync as public;
-use crate::sync::once::ExclusiveState;
+use crate::sync::poison::once::ExclusiveState;
 
 pub struct Once {
     state: Cell<State>,
diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs
index 5beff4ce683..fde1e0ca510 100644
--- a/library/std/src/sys/sync/once/queue.rs
+++ b/library/std/src/sys/sync/once/queue.rs
@@ -58,7 +58,7 @@
 use crate::cell::Cell;
 use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release};
 use crate::sync::atomic::{AtomicBool, AtomicPtr};
-use crate::sync::once::ExclusiveState;
+use crate::sync::poison::once::ExclusiveState;
 use crate::thread::{self, Thread};
 use crate::{fmt, ptr, sync as public};
 
diff --git a/tests/debuginfo/mutex.rs b/tests/debuginfo/mutex.rs
index 4f458c0d7e0..c47e3ac6dce 100644
--- a/tests/debuginfo/mutex.rs
+++ b/tests/debuginfo/mutex.rs
@@ -9,7 +9,7 @@
 // cdb-command:g
 //
 // cdb-command:dx m,d
-// cdb-check:m,d              [Type: std::sync::mutex::Mutex<i32>]
+// cdb-check:m,d              [Type: std::sync::poison::mutex::Mutex<i32>]
 // cdb-check:    [...] inner            [Type: std::sys::sync::mutex::futex::Mutex]
 // cdb-check:    [...] poison           [Type: std::sync::poison::Flag]
 // cdb-check:    [...] data             : 0 [Type: core::cell::UnsafeCell<i32>]
@@ -21,8 +21,8 @@
 
 //
 // cdb-command:dx _lock,d
-// cdb-check:_lock,d          : Ok [Type: enum2$<core::result::Result<std::sync::mutex::MutexGuard<i32>,enum2$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> > > > >]
-// cdb-check:    [...] __0              [Type: std::sync::mutex::MutexGuard<i32>]
+// cdb-check:_lock,d          : Ok [Type: enum2$<core::result::Result<std::sync::poison::mutex::MutexGuard<i32>,enum2$<std::sync::poison::TryLockError<std::sync::poison::mutex::MutexGuard<i32> > > > >]
+// cdb-check:    [...] __0              [Type: std::sync::poison::mutex::MutexGuard<i32>]
 
 use std::sync::Mutex;
 
diff --git a/tests/debuginfo/rwlock-read.rs b/tests/debuginfo/rwlock-read.rs
index 3fd6ac33726..825cdbe5510 100644
--- a/tests/debuginfo/rwlock-read.rs
+++ b/tests/debuginfo/rwlock-read.rs
@@ -9,12 +9,12 @@
 // cdb-command:g
 //
 // cdb-command:dx l
-// cdb-check:l                [Type: std::sync::rwlock::RwLock<i32>]
+// cdb-check:l                [Type: std::sync::poison::rwlock::RwLock<i32>]
 // cdb-check:    [...] poison           [Type: std::sync::poison::Flag]
 // cdb-check:    [...] data             : 0 [Type: core::cell::UnsafeCell<i32>]
 //
 // cdb-command:dx r
-// cdb-check:r                [Type: std::sync::rwlock::RwLockReadGuard<i32>]
+// cdb-check:r                [Type: std::sync::poison::rwlock::RwLockReadGuard<i32>]
 // cdb-check:    [...] data             : NonNull([...]: 0) [Type: core::ptr::non_null::NonNull<i32>]
 // cdb-check:    [...] inner_lock       : [...] [Type: std::sys::sync::rwlock::futex::RwLock *]
 
diff --git a/tests/debuginfo/rwlock-write.rs b/tests/debuginfo/rwlock-write.rs
index d7864303666..aaca048b8a7 100644
--- a/tests/debuginfo/rwlock-write.rs
+++ b/tests/debuginfo/rwlock-write.rs
@@ -9,8 +9,8 @@
 // cdb-command:g
 //
 // cdb-command:dx w
-// cdb-check:w                [Type: std::sync::rwlock::RwLockWriteGuard<i32>]
-// cdb-check:    [...] lock             : [...] [Type: std::sync::rwlock::RwLock<i32> *]
+// cdb-check:w                [Type: std::sync::poison::rwlock::RwLockWriteGuard<i32>]
+// cdb-check:    [...] lock             : [...] [Type: std::sync::poison::rwlock::RwLock<i32> *]
 // cdb-check:    [...] poison           [Type: std::sync::poison::Guard]
 
 #[allow(unused_variables)]
diff --git a/tests/ui/traits/const-traits/span-bug-issue-121418.stderr b/tests/ui/traits/const-traits/span-bug-issue-121418.stderr
index fe1e5e558b2..f41c19b4573 100644
--- a/tests/ui/traits/const-traits/span-bug-issue-121418.stderr
+++ b/tests/ui/traits/const-traits/span-bug-issue-121418.stderr
@@ -27,7 +27,7 @@ LL |     pub const fn new() -> std::sync::Mutex<dyn T> {}
    |
    = help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`
 note: required because it appears within the type `Mutex<(dyn T + 'static)>`
-  --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
+  --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
    = note: the return type of a function must have a statically known size
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/typeck/assign-non-lval-derefmut.stderr b/tests/ui/typeck/assign-non-lval-derefmut.stderr
index ce0ff1d957b..16fb1e9c5c3 100644
--- a/tests/ui/typeck/assign-non-lval-derefmut.stderr
+++ b/tests/ui/typeck/assign-non-lval-derefmut.stderr
@@ -20,7 +20,7 @@ LL |     x.lock().unwrap() += 1;
    |     cannot use `+=` on type `MutexGuard<'_, usize>`
    |
 note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
-  --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
+  --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
    |
    = note: not implement `AddAssign<{integer}>`
 help: `+=` can be used on `usize` if you dereference the left-hand side
@@ -52,7 +52,7 @@ LL |     y += 1;
    |     cannot use `+=` on type `MutexGuard<'_, usize>`
    |
 note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
-  --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
+  --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
    |
    = note: not implement `AddAssign<{integer}>`
 help: `+=` can be used on `usize` if you dereference the left-hand side