Auto merge of #146013 - Jules-Bertholet:from-wrapper, r=Mark-Simulacrum

Add `From` impls for wrapper types





- ~`From<T: Copy> for ManuallyDrop<T>`~
- `From<T: UnwindSafe> for AssertUnwindSafe<T>`
- `From<T> for LazyCell<T, F>`
- `From<T> for LazyLock<T, F>`
- `From<T> for ThinBox<T>` (unstable)
- `From<T> for UniqueRc<T>` (unstable)
- `From<T> for UniqueArc<T>` (unstable)

@rustbot label T-libs-api needs-fcp

Also needs a crater run, as the insta-stable impls are technically breaking changes.
This commit is contained in:
bors
2026-03-17 04:14:51 +00:00
11 changed files with 91 additions and 17 deletions
+9
View File
@@ -430,3 +430,12 @@ fn source(&self) -> Option<&(dyn Error + 'static)> {
self.deref().source()
}
}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "thin_box", issue = "92791")]
impl<T> From<T> for ThinBox<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}
+9
View File
@@ -3980,6 +3980,15 @@ fn as_mut(&mut self) -> &mut T {
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T: ?Sized, A: Allocator> Unpin for UniqueRc<T, A> {}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T> From<T> for UniqueRc<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for UniqueRc<T, A> {
/// Equality for two `UniqueRc`s.
+9
View File
@@ -4424,6 +4424,15 @@ fn as_mut(&mut self) -> &mut T {
}
}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T> From<T> for UniqueArc<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T: ?Sized, A: Allocator> Unpin for UniqueArc<T, A> {}
+10
View File
@@ -366,6 +366,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, F> From<T> for LazyCell<T, F> {
/// 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() -> ! {
+13
View File
@@ -313,3 +313,16 @@ fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
/// 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<T> From<T> for AssertUnwindSafe<T>
where
T: UnwindSafe,
{
#[inline(always)]
fn from(value: T) -> Self {
Self(value)
}
}
+6 -8
View File
@@ -44,10 +44,9 @@ fn generate_fake_frames() -> Vec<BacktraceFrame> {
#[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();
+13 -9
View File
@@ -105,15 +105,6 @@ pub const fn new(f: F) -> LazyLock<T, F> {
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<T, F> {
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.
@@ -404,6 +395,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, F> From<T> for LazyLock<T, F> {
/// 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() -> ! {
+7
View File
@@ -84,6 +84,13 @@ pub const fn new() -> 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.
+5
View File
@@ -75,6 +75,11 @@ pub const fn new() -> 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
@@ -39,6 +39,11 @@ pub const fn new() -> 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
+5
View File
@@ -121,6 +121,11 @@ pub const fn new() -> 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