From 39f4150181b3708a85d48f4f9d0ea00a3a27e980 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 29 Aug 2025 15:44:35 -0400 Subject: [PATCH 1/6] Add `From` impls for wrapper types - `From for ThinBox` - `From for UniqueRc` - `From for UniqueArc` - `From for ManuallyDrop` - `From for AssertUnwindSafe` --- library/alloc/src/boxed/thin.rs | 8 ++++++++ library/alloc/src/rc.rs | 8 ++++++++ library/alloc/src/sync.rs | 8 ++++++++ library/core/src/mem/manually_drop.rs | 8 ++++++++ library/core/src/panic/unwind_safe.rs | 8 ++++++++ 5 files changed, 40 insertions(+) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 1cce36606d2c0..2ebdad4fcd21d 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -430,3 +430,11 @@ impl Error for ThinBox { self.deref().source() } } + +#[unstable(feature = "thin_box", issue = "92791")] +impl From for ThinBox { + #[inline(always)] + fn from(value: T) -> Self { + Self::new(value) + } +} diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 529b583cdd2bc..cee9b7f3b8f44 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -3816,6 +3816,14 @@ impl AsMut for UniqueRc { #[unstable(feature = "unique_rc_arc", issue = "112566")] impl Unpin for UniqueRc {} +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl From for UniqueRc { + #[inline(always)] + fn from(value: T) -> Self { + Self::new(value) + } +} + #[unstable(feature = "unique_rc_arc", issue = "112566")] impl PartialEq for UniqueRc { /// Equality for two `UniqueRc`s. diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a21b6880674c6..0ca4a33a6fa7c 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4242,6 +4242,14 @@ impl AsMut for UniqueArc { } } +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl From for UniqueArc { + #[inline(always)] + fn from(value: T) -> Self { + Self::new(value) + } +} + #[unstable(feature = "unique_rc_arc", issue = "112566")] impl Unpin for UniqueArc {} diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 02bb81792931e..f3d41460bfc20 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -276,3 +276,11 @@ impl DerefMut for ManuallyDrop { #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for ManuallyDrop {} + +#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] +impl From for ManuallyDrop { + #[inline(always)] + fn from(value: T) -> Self { + Self::new(value) + } +} diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index a60f0799c0eae..b07855abb0430 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -311,3 +311,11 @@ impl AsyncIterator for AssertUnwindSafe { self.0.size_hint() } } + +#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] +impl From for AssertUnwindSafe { + #[inline(always)] + fn from(value: T) -> Self { + Self(value) + } +} From 57c36358080f612294d0b3dd20f84ca04c046e13 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 29 Aug 2025 16:03:19 -0400 Subject: [PATCH 2/6] Add `From for Lazy{Cell,Lock}` --- library/core/src/cell/lazy.rs | 10 ++++++++++ library/std/src/backtrace/tests.rs | 14 ++++++------- library/std/src/sync/lazy_lock.rs | 22 ++++++++++++--------- library/std/src/sync/poison/once.rs | 7 +++++++ library/std/src/sys/sync/once/futex.rs | 5 +++++ library/std/src/sys/sync/once/no_threads.rs | 5 +++++ library/std/src/sys/sync/once/queue.rs | 5 +++++ 7 files changed, 51 insertions(+), 17 deletions(-) diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index a1bd4c8571706..affff80210114 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -370,6 +370,16 @@ impl fmt::Debug for LazyCell { } } +#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] +impl From for LazyCell { + /// Constructs a `LazyCell` that starts already initialized + /// with the provided value. + #[inline] + fn from(value: T) -> Self { + Self { state: UnsafeCell::new(State::Init(value)) } + } +} + #[cold] #[inline(never)] const fn panic_poisoned() -> ! { diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs index 174d62813bd58..b68b528c18668 100644 --- a/library/std/src/backtrace/tests.rs +++ b/library/std/src/backtrace/tests.rs @@ -44,10 +44,9 @@ fn generate_fake_frames() -> Vec { #[test] fn test_debug() { let backtrace = Backtrace { - inner: Inner::Captured(LazyLock::preinit(Capture { - actual_start: 1, - frames: generate_fake_frames(), - })), + inner: Inner::Captured( + (Capture { actual_start: 1, frames: generate_fake_frames() }).into(), + ), }; #[rustfmt::skip] @@ -66,10 +65,9 @@ fn test_debug() { #[test] fn test_frames() { let backtrace = Backtrace { - inner: Inner::Captured(LazyLock::preinit(Capture { - actual_start: 1, - frames: generate_fake_frames(), - })), + inner: Inner::Captured( + (Capture { actual_start: 1, frames: generate_fake_frames() }).into(), + ), }; let frames = backtrace.frames(); diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 3231125f7a13a..def40a3d9696b 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -105,15 +105,6 @@ impl T> LazyLock { LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) } } - /// Creates a new lazy value that is already initialized. - #[inline] - #[cfg(test)] - pub(crate) fn preinit(value: T) -> LazyLock { - let once = Once::new(); - once.call_once(|| {}); - LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) } - } - /// Consumes this `LazyLock` returning the stored value. /// /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. @@ -401,6 +392,19 @@ impl fmt::Debug for LazyLock { } } +#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] +impl From for LazyLock { + /// Constructs a `LazyLock` that starts already initialized + /// with the provided value. + #[inline] + fn from(value: T) -> Self { + LazyLock { + once: Once::new_complete(), + data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }), + } + } +} + #[cold] #[inline(never)] fn panic_poisoned() -> ! { diff --git a/library/std/src/sync/poison/once.rs b/library/std/src/sync/poison/once.rs index faf2913c54730..c79f75978cf57 100644 --- a/library/std/src/sync/poison/once.rs +++ b/library/std/src/sync/poison/once.rs @@ -82,6 +82,13 @@ impl Once { Once { inner: sys::Once::new() } } + /// Creates a new `Once` value that starts already completed. + #[inline] + #[must_use] + pub(crate) const fn new_complete() -> Once { + Once { inner: sys::Once::new_complete() } + } + /// Performs an initialization routine once and only once. The given closure /// will be executed if this is the first time `call_once` has been called, /// and otherwise the routine will *not* be invoked. diff --git a/library/std/src/sys/sync/once/futex.rs b/library/std/src/sys/sync/once/futex.rs index 407fdcebcf5cc..ebdf62f6a3851 100644 --- a/library/std/src/sys/sync/once/futex.rs +++ b/library/std/src/sys/sync/once/futex.rs @@ -75,6 +75,11 @@ impl Once { Once { state_and_queued: Futex::new(INCOMPLETE) } } + #[inline] + pub const fn new_complete() -> Once { + Once { state_and_queued: Futex::new(COMPLETE) } + } + #[inline] pub fn is_completed(&self) -> bool { // Use acquire ordering to make all initialization changes visible to the diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs index 2568059cfe3a8..07ae4abdb2457 100644 --- a/library/std/src/sys/sync/once/no_threads.rs +++ b/library/std/src/sys/sync/once/no_threads.rs @@ -39,6 +39,11 @@ impl Once { Once { state: Cell::new(State::Incomplete) } } + #[inline] + pub const fn new_complete() -> Once { + Once { state: Cell::new(State::Complete) } + } + #[inline] pub fn is_completed(&self) -> bool { self.state.get() == State::Complete diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index 49e15d65f25a2..424a4a117f07e 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -121,6 +121,11 @@ impl Once { Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) } } + #[inline] + pub const fn new_complete() -> Once { + Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(COMPLETE)) } + } + #[inline] pub fn is_completed(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization From b38c598658efb0b050714ae7f94ef7dc00529883 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 29 Aug 2025 18:08:03 -0400 Subject: [PATCH 3/6] Add missing `#[cfg(not(no_global_oom_handling))]` --- library/alloc/src/boxed/thin.rs | 1 + library/alloc/src/rc.rs | 1 + library/alloc/src/sync.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 2ebdad4fcd21d..1f6127b84b95b 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -431,6 +431,7 @@ impl Error for ThinBox { } } +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "thin_box", issue = "92791")] impl From for ThinBox { #[inline(always)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index cee9b7f3b8f44..47c962606b198 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -3816,6 +3816,7 @@ impl AsMut for UniqueRc { #[unstable(feature = "unique_rc_arc", issue = "112566")] impl Unpin for UniqueRc {} +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] impl From for UniqueRc { #[inline(always)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 0ca4a33a6fa7c..836e66af2765d 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4242,6 +4242,7 @@ impl AsMut for UniqueArc { } } +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] impl From for UniqueArc { #[inline(always)] From 2a02903f08b7ae7c3fba03c368e6260bdd1a0482 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sun, 7 Sep 2025 15:16:37 -0400 Subject: [PATCH 4/6] Restrict `ManuallyDrop` and `AssertUnwindSafe` impls --- library/core/src/mem/manually_drop.rs | 5 ++++- library/core/src/panic/unwind_safe.rs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index f3d41460bfc20..914fcf304a129 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -278,7 +278,10 @@ impl DerefMut for ManuallyDrop { unsafe impl DerefPure for ManuallyDrop {} #[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] -impl From for ManuallyDrop { +impl From for ManuallyDrop +where + T: Copy, +{ #[inline(always)] fn from(value: T) -> Self { Self::new(value) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index b07855abb0430..cff423f2c18c2 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -313,7 +313,10 @@ impl AsyncIterator for AssertUnwindSafe { } #[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] -impl From for AssertUnwindSafe { +impl From for AssertUnwindSafe +where + T: UnwindSafe, +{ #[inline(always)] fn from(value: T) -> Self { Self(value) From 2f886981502b1296a6432792da3f285ecc335883 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 17 Sep 2025 15:43:46 -0400 Subject: [PATCH 5/6] Document `ManuallyDrop` and `AssertUnwindSafe` impls --- library/core/src/mem/manually_drop.rs | 2 ++ library/core/src/panic/unwind_safe.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 914fcf304a129..bd9c8cd82b669 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -277,6 +277,8 @@ impl DerefMut for ManuallyDrop { #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for ManuallyDrop {} +/// If a value's type is `Copy`, then it has a trivial destructor, +/// so wrapping it in `ManuallyDrop` can never laed to unwanted leaks. #[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] impl From for ManuallyDrop where diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index cff423f2c18c2..283e113c9c5e7 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -312,6 +312,8 @@ impl AsyncIterator for AssertUnwindSafe { } } +/// If a value's type is already `UnwindSafe`, +/// wrapping it in `AssertUnwindSafe` is never incorrect. #[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] impl From for AssertUnwindSafe where From 0ae1c5d3e5e95f0d23b7fd15ef34a2066c77fcb8 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Tue, 23 Sep 2025 17:40:40 -0400 Subject: [PATCH 6/6] Remove ManuallyDrop impl --- library/core/src/mem/manually_drop.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index bd9c8cd82b669..02bb81792931e 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -276,16 +276,3 @@ impl DerefMut for ManuallyDrop { #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for ManuallyDrop {} - -/// If a value's type is `Copy`, then it has a trivial destructor, -/// so wrapping it in `ManuallyDrop` can never laed to unwanted leaks. -#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")] -impl From for ManuallyDrop -where - T: Copy, -{ - #[inline(always)] - fn from(value: T) -> Self { - Self::new(value) - } -}