From 5016467a23c93384ffcb58b9c5ff2f8afc349d54 Mon Sep 17 00:00:00 2001
From: Frank King <frankking1729@gmail.com>
Date: Thu, 28 Nov 2024 21:57:39 +0800
Subject: [PATCH 1/5] Implement `UniqueArc`

---
 library/alloc/src/sync.rs       | 182 +++++++++++++++++++++++++++++++-
 library/alloctests/tests/arc.rs |   5 +-
 library/std/src/sync/mod.rs     |   2 +
 3 files changed, 187 insertions(+), 2 deletions(-)

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index c62f8e5b70f4d..3903303bcea6b 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -20,7 +20,7 @@ use core::iter;
 use core::marker::{PhantomData, Unsize};
 use core::mem::{self, ManuallyDrop, align_of_val_raw};
 use core::num::NonZeroUsize;
-use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver};
+use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
 use core::panic::{RefUnwindSafe, UnwindSafe};
 use core::pin::{Pin, PinCoerceUnsized};
 use core::ptr::{self, NonNull};
@@ -4066,3 +4066,183 @@ impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
         core::error::Error::provide(&**self, req);
     }
 }
+
+/// A uniquely owned [`Arc`].
+///
+/// This represents an `Arc` that is known to be uniquely owned -- that is, have exactly one strong
+/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
+/// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`.
+///
+/// Because they are uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common
+/// use case is to have an object be mutable during its initialization phase but then have it become
+/// immutable and converted to a normal `Arc`.
+///
+/// This can be used as a flexible way to create cyclic data structures, as in the example below.
+///
+/// ```
+/// #![feature(unique_rc_arc)]
+/// use std::sync::{Arc, Weak, UniqueArc};
+///
+/// struct Gadget {
+///     #[allow(dead_code)]
+///     me: Weak<Gadget>,
+/// }
+///
+/// fn create_gadget() -> Option<Arc<Gadget>> {
+///     let mut rc = UniqueArc::new(Gadget {
+///         me: Weak::new(),
+///     });
+///     rc.me = UniqueArc::downgrade(&rc);
+///     Some(UniqueArc::into_arc(rc))
+/// }
+///
+/// create_gadget().unwrap();
+/// ```
+///
+/// An advantage of using `UniqueArc` over [`Arc::new_cyclic`] to build cyclic data structures is that
+/// [`Arc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the
+/// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data,
+/// including fallible or async constructors.
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[derive(Debug)]
+pub struct UniqueArc<
+    T: ?Sized,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+> {
+    ptr: NonNull<ArcInner<T>>,
+    phantom: PhantomData<ArcInner<T>>,
+    alloc: A,
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueArc<U, A>>
+    for UniqueArc<T, A>
+{
+}
+
+// Depends on A = Global
+impl<T> UniqueArc<T> {
+    /// Creates a new `UniqueArc`.
+    ///
+    /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading
+    /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`].
+    /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will
+    /// point to the new [`Arc`].
+    #[cfg(not(no_global_oom_handling))]
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    pub fn new(value: T) -> Self {
+        Self::new_in(value, Global)
+    }
+}
+
+impl<T, A: Allocator> UniqueArc<T, A> {
+    /// Creates a new `UniqueArc` in the provided allocator.
+    ///
+    /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading
+    /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`].
+    /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will
+    /// point to the new [`Arc`].
+    #[cfg(not(no_global_oom_handling))]
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    pub fn new_in(data: T, alloc: A) -> Self {
+        let (ptr, alloc) = Box::into_unique(Box::new_in(
+            ArcInner {
+                strong: atomic::AtomicUsize::new(0),
+                // keep one weak reference so if all the weak pointers that are created are dropped
+                // the UniqueArc still stays valid.
+                weak: atomic::AtomicUsize::new(1),
+                data,
+            },
+            alloc,
+        ));
+        Self { ptr: ptr.into(), phantom: PhantomData, alloc }
+    }
+}
+
+impl<T: ?Sized, A: Allocator> UniqueArc<T, A> {
+    /// Converts the `UniqueArc` into a regular [`Arc`].
+    ///
+    /// This consumes the `UniqueArc` and returns a regular [`Arc`] that contains the `value` that
+    /// is passed to `into_arc`.
+    ///
+    /// Any weak references created before this method is called can now be upgraded to strong
+    /// references.
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    pub fn into_arc(this: Self) -> Arc<T, A> {
+        let this = ManuallyDrop::new(this);
+
+        // Move the allocator out.
+        // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in
+        // a `ManuallyDrop`.
+        let alloc: A = unsafe { ptr::read(&this.alloc) };
+
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        unsafe {
+            // Convert our weak reference into a strong reference
+            (*this.ptr.as_ptr()).strong.store(1, Release);
+            Arc::from_inner_in(this.ptr, alloc)
+        }
+    }
+}
+
+impl<T: ?Sized, A: Allocator + Clone> UniqueArc<T, A> {
+    /// Creates a new weak reference to the `UniqueArc`.
+    ///
+    /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted
+    /// to a [`Arc`] using [`UniqueArc::into_arc`].
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    pub fn downgrade(this: &Self) -> Weak<T, A> {
+        // Using a relaxed ordering is alright here, as knowledge of the
+        // original reference prevents other threads from erroneously deleting
+        // the object or converting the object to a normal `Arc<T, A>`.
+        //
+        // Note that we don't need to test if the weak counter is locked because there
+        // are no such operations like `Arc::get_mut` or `Arc::make_mut` that will lock
+        // the weak counter.
+        //
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        let old_size = unsafe { (*this.ptr.as_ptr()).weak.fetch_add(1, Relaxed) };
+
+        // See comments in Arc::clone() for why we do this (for mem::forget).
+        if old_size > MAX_REFCOUNT {
+            abort();
+        }
+
+        Weak { ptr: this.ptr, alloc: this.alloc.clone() }
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> Deref for UniqueArc<T, A> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        unsafe { &self.ptr.as_ref().data }
+    }
+}
+
+// #[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueArc<T> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> DerefMut for UniqueArc<T, A> {
+    fn deref_mut(&mut self) -> &mut T {
+        // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
+        // have unique ownership and therefore it's safe to make a mutable reference because
+        // `UniqueArc` owns the only strong reference to itself.
+        unsafe { &mut (*self.ptr.as_ptr()).data }
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc<T, A> {
+    fn drop(&mut self) {
+        // See `Arc::drop_slow` which drops an `Arc` with a strong count of 0.
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
+
+        unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) };
+    }
+}
diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs
index 0baa50f439b37..45a145c6271a8 100644
--- a/library/alloctests/tests/arc.rs
+++ b/library/alloctests/tests/arc.rs
@@ -265,7 +265,7 @@ fn make_mut_unsized() {
 
 #[allow(unused)]
 mod pin_coerce_unsized {
-    use alloc::sync::Arc;
+    use alloc::sync::{Arc, UniqueArc};
     use core::pin::Pin;
 
     pub trait MyTrait {}
@@ -275,4 +275,7 @@ mod pin_coerce_unsized {
     pub fn pin_arc(arg: Pin<Arc<String>>) -> Pin<Arc<dyn MyTrait>> {
         arg
     }
+    pub fn pin_unique_arc(arg: Pin<UniqueArc<String>>) -> Pin<UniqueArc<dyn MyTrait>> {
+        arg
+    }
 }
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 5b50a3c6ccf90..e67b4f6f22f5a 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -176,6 +176,8 @@ pub use core::sync::Exclusive;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::sync::atomic;
 
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+pub use alloc_crate::sync::UniqueArc;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::sync::{Arc, Weak};
 

From 9e5cca504988932581fa6c83c8626101013d64cd Mon Sep 17 00:00:00 2001
From: Frank King <frankking1729@gmail.com>
Date: Mon, 3 Mar 2025 10:53:25 +0800
Subject: [PATCH 2/5] Make UniqueArc invariant for soundness

---
 library/alloc/src/sync.rs                   |  8 ++++--
 tests/ui/variance/variance-uniquearc.rs     | 27 +++++++++++++++++++++
 tests/ui/variance/variance-uniquearc.stderr | 15 ++++++++++++
 tests/ui/variance/variance-uniquerc.rs      |  2 +-
 4 files changed, 49 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui/variance/variance-uniquearc.rs
 create mode 100644 tests/ui/variance/variance-uniquearc.stderr

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 3903303bcea6b..5f0133c6c56de 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -4110,7 +4110,11 @@ pub struct UniqueArc<
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
 > {
     ptr: NonNull<ArcInner<T>>,
-    phantom: PhantomData<ArcInner<T>>,
+    // Define the ownership of `ArcInner<T>` for drop-check
+    _marker: PhantomData<ArcInner<T>>,
+    // Invariance is necessary for soundness: once other `Weak`
+    // references exist, we already have a form of shared mutability!
+    _marker2: PhantomData<*mut T>,
     alloc: A,
 }
 
@@ -4155,7 +4159,7 @@ impl<T, A: Allocator> UniqueArc<T, A> {
             },
             alloc,
         ));
-        Self { ptr: ptr.into(), phantom: PhantomData, alloc }
+        Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc }
     }
 }
 
diff --git a/tests/ui/variance/variance-uniquearc.rs b/tests/ui/variance/variance-uniquearc.rs
new file mode 100644
index 0000000000000..0358951238869
--- /dev/null
+++ b/tests/ui/variance/variance-uniquearc.rs
@@ -0,0 +1,27 @@
+// regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164
+// see also the test for UniqueRc` in variance-uniquerc.rs
+//
+// inline comments explain how this code *would* compile if UniqueArc was still covariant
+
+#![feature(unique_rc_arc)]
+
+use std::sync::UniqueArc;
+
+fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
+    let r = UniqueArc::new(""); // UniqueArc<&'static str>
+    let w = UniqueArc::downgrade(&r); // Weak<&'static str>
+    let mut r = r; // [IF COVARIANT]: ==>> UniqueArc<&'a str>
+    *r = x; // assign the &'a str
+    let _r = UniqueArc::into_arc(r); // Arc<&'a str>, but we only care to activate the weak
+    let r = w.upgrade().unwrap(); // Arc<&'static str>
+    *r // &'static str, coerces to &'b str
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    let s = String::from("Hello World!");
+    let r = extend_lifetime(&s);
+    println!("{r}");
+    drop(s);
+    println!("{r}");
+}
diff --git a/tests/ui/variance/variance-uniquearc.stderr b/tests/ui/variance/variance-uniquearc.stderr
new file mode 100644
index 0000000000000..55076dae7324b
--- /dev/null
+++ b/tests/ui/variance/variance-uniquearc.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+  --> $DIR/variance-uniquearc.rs:17:5
+   |
+LL | fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
+   |                    --  -- lifetime `'b` defined here
+   |                    |
+   |                    lifetime `'a` defined here
+...
+LL |     *r // &'static str, coerces to &'b str
+   |     ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/variance/variance-uniquerc.rs b/tests/ui/variance/variance-uniquerc.rs
index 0c395ab06eaa3..2e9738f66dcb8 100644
--- a/tests/ui/variance/variance-uniquerc.rs
+++ b/tests/ui/variance/variance-uniquerc.rs
@@ -1,5 +1,5 @@
 // regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164
-// we should also test UniqueArc once implemented
+// see also the test for UniqueArc in variance-uniquearc.rs
 //
 // inline comments explain how this code *would* compile if UniqueRc was still covariant
 

From b542a2bd4bbef0221a78ecbd31d4a4ea9fb22f64 Mon Sep 17 00:00:00 2001
From: Frank King <frankking1729@gmail.com>
Date: Mon, 3 Mar 2025 15:51:05 +0800
Subject: [PATCH 3/5] Add more APIs for UniqueArc

---
 library/alloc/src/sync.rs | 255 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 250 insertions(+), 5 deletions(-)

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 5f0133c6c56de..b883f84d68eed 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -4073,7 +4073,7 @@ impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
 /// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
 /// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`.
 ///
-/// Because they are uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common
+/// Because it is uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common
 /// use case is to have an object be mutable during its initialization phase but then have it become
 /// immutable and converted to a normal `Arc`.
 ///
@@ -4084,7 +4084,6 @@ impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
 /// use std::sync::{Arc, Weak, UniqueArc};
 ///
 /// struct Gadget {
-///     #[allow(dead_code)]
 ///     me: Weak<Gadget>,
 /// }
 ///
@@ -4104,7 +4103,6 @@ impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
 /// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data,
 /// including fallible or async constructors.
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
-#[derive(Debug)]
 pub struct UniqueArc<
     T: ?Sized,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
@@ -4119,13 +4117,248 @@ pub struct UniqueArc<
 }
 
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<T: ?Sized + Sync + Send, A: Allocator + Send> Send for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<T: ?Sized + Sync + Send, A: Allocator + Sync> Sync for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+// #[unstable(feature = "coerce_unsized", issue = "18598")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueArc<U, A>>
     for UniqueArc<T, A>
 {
 }
 
-// Depends on A = Global
-impl<T> UniqueArc<T> {
+//#[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<UniqueArc<U>> for UniqueArc<T> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + fmt::Display, A: Allocator> fmt::Display for UniqueArc<T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + fmt::Debug, A: Allocator> fmt::Debug for UniqueArc<T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> fmt::Pointer for UniqueArc<T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Pointer::fmt(&(&raw const **self), f)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> borrow::Borrow<T> for UniqueArc<T, A> {
+    fn borrow(&self) -> &T {
+        &**self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> borrow::BorrowMut<T> for UniqueArc<T, A> {
+    fn borrow_mut(&mut self) -> &mut T {
+        &mut **self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> AsRef<T> for UniqueArc<T, A> {
+    fn as_ref(&self) -> &T {
+        &**self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> AsMut<T> for UniqueArc<T, A> {
+    fn as_mut(&mut self) -> &mut T {
+        &mut **self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> Unpin for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for UniqueArc<T, A> {
+    /// Equality for two `UniqueArc`s.
+    ///
+    /// Two `UniqueArc`s are equal if their inner values are equal.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five == UniqueArc::new(5));
+    /// ```
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        PartialEq::eq(&**self, &**other)
+    }
+
+    /// Inequality for two `UniqueArc`s.
+    ///
+    /// Two `UniqueArc`s are not equal if their inner values are not equal.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five != UniqueArc::new(6));
+    /// ```
+    #[inline]
+    fn ne(&self, other: &Self) -> bool {
+        PartialEq::ne(&**self, &**other)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for UniqueArc<T, A> {
+    /// Partial comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `partial_cmp()` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    /// use std::cmp::Ordering;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&UniqueArc::new(6)));
+    /// ```
+    #[inline(always)]
+    fn partial_cmp(&self, other: &UniqueArc<T, A>) -> Option<Ordering> {
+        (**self).partial_cmp(&**other)
+    }
+
+    /// Less-than comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `<` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five < UniqueArc::new(6));
+    /// ```
+    #[inline(always)]
+    fn lt(&self, other: &UniqueArc<T, A>) -> bool {
+        **self < **other
+    }
+
+    /// 'Less than or equal to' comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `<=` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five <= UniqueArc::new(5));
+    /// ```
+    #[inline(always)]
+    fn le(&self, other: &UniqueArc<T, A>) -> bool {
+        **self <= **other
+    }
+
+    /// Greater-than comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `>` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five > UniqueArc::new(4));
+    /// ```
+    #[inline(always)]
+    fn gt(&self, other: &UniqueArc<T, A>) -> bool {
+        **self > **other
+    }
+
+    /// 'Greater than or equal to' comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `>=` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five >= UniqueArc::new(5));
+    /// ```
+    #[inline(always)]
+    fn ge(&self, other: &UniqueArc<T, A>) -> bool {
+        **self >= **other
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Ord, A: Allocator> Ord for UniqueArc<T, A> {
+    /// Comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `cmp()` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    /// use std::cmp::Ordering;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert_eq!(Ordering::Less, five.cmp(&UniqueArc::new(6)));
+    /// ```
+    #[inline]
+    fn cmp(&self, other: &UniqueArc<T, A>) -> Ordering {
+        (**self).cmp(&**other)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Eq, A: Allocator> Eq for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Hash, A: Allocator> Hash for UniqueArc<T, A> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        (**self).hash(state);
+    }
+}
+
+impl<T> UniqueArc<T, Global> {
     /// Creates a new `UniqueArc`.
     ///
     /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading
@@ -4134,6 +4367,7 @@ impl<T> UniqueArc<T> {
     /// point to the new [`Arc`].
     #[cfg(not(no_global_oom_handling))]
     #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
     pub fn new(value: T) -> Self {
         Self::new_in(value, Global)
     }
@@ -4148,6 +4382,8 @@ impl<T, A: Allocator> UniqueArc<T, A> {
     /// point to the new [`Arc`].
     #[cfg(not(no_global_oom_handling))]
     #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
+    // #[unstable(feature = "allocator_api", issue = "32838")]
     pub fn new_in(data: T, alloc: A) -> Self {
         let (ptr, alloc) = Box::into_unique(Box::new_in(
             ArcInner {
@@ -4172,6 +4408,7 @@ impl<T: ?Sized, A: Allocator> UniqueArc<T, A> {
     /// Any weak references created before this method is called can now be upgraded to strong
     /// references.
     #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
     pub fn into_arc(this: Self) -> Arc<T, A> {
         let this = ManuallyDrop::new(this);
 
@@ -4195,6 +4432,7 @@ impl<T: ?Sized, A: Allocator + Clone> UniqueArc<T, A> {
     /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted
     /// to a [`Arc`] using [`UniqueArc::into_arc`].
     #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
     pub fn downgrade(this: &Self) -> Weak<T, A> {
         // Using a relaxed ordering is alright here, as knowledge of the
         // original reference prevents other threads from erroneously deleting
@@ -4236,10 +4474,17 @@ impl<T: ?Sized, A: Allocator> DerefMut for UniqueArc<T, A> {
         // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
         // have unique ownership and therefore it's safe to make a mutable reference because
         // `UniqueArc` owns the only strong reference to itself.
+        // We also need to be careful to only create a mutable reference to the `data` field,
+        // as a mutable reference to the entire `ArcInner` would assert uniqueness over the
+        // ref count fields too, invalidating any attempt by `Weak`s to access the ref count.
         unsafe { &mut (*self.ptr.as_ptr()).data }
     }
 }
 
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+// #[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized, A: Allocator> DerefPure for UniqueArc<T, A> {}
+
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
 unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc<T, A> {
     fn drop(&mut self) {

From eb094ed7b4c600de21d1ace851349c9c38298fa8 Mon Sep 17 00:00:00 2001
From: Frank King <frankking1729@gmail.com>
Date: Thu, 6 Mar 2025 22:15:58 +0800
Subject: [PATCH 4/5] Remove `PartialEq::ne` for `UniqueArc`

---
 library/alloc/src/sync.rs | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index b883f84d68eed..be581661f4ce3 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -4205,25 +4205,6 @@ impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for UniqueArc<T, A> {
     fn eq(&self, other: &Self) -> bool {
         PartialEq::eq(&**self, &**other)
     }
-
-    /// Inequality for two `UniqueArc`s.
-    ///
-    /// Two `UniqueArc`s are not equal if their inner values are not equal.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(unique_rc_arc)]
-    /// use std::sync::UniqueArc;
-    ///
-    /// let five = UniqueArc::new(5);
-    ///
-    /// assert!(five != UniqueArc::new(6));
-    /// ```
-    #[inline]
-    fn ne(&self, other: &Self) -> bool {
-        PartialEq::ne(&**self, &**other)
-    }
 }
 
 #[unstable(feature = "unique_rc_arc", issue = "112566")]

From 5004e10ceb5c02a7170d81adb551a25f6f9e3565 Mon Sep 17 00:00:00 2001
From: Frank King <frankking1729@gmail.com>
Date: Sat, 29 Mar 2025 12:13:38 +0800
Subject: [PATCH 5/5] Add a test for `Weak` created from `UniqueArc::downgrade`

---
 library/alloctests/tests/arc.rs | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs
index 45a145c6271a8..00bdf527133f7 100644
--- a/library/alloctests/tests/arc.rs
+++ b/library/alloctests/tests/arc.rs
@@ -1,7 +1,7 @@
 use std::any::Any;
 use std::cell::{Cell, RefCell};
 use std::iter::TrustedLen;
-use std::sync::{Arc, Weak};
+use std::sync::{Arc, UniqueArc, Weak};
 
 #[test]
 fn uninhabited() {
@@ -263,6 +263,27 @@ fn make_mut_unsized() {
     assert_eq!(*other_data, [110, 20, 30]);
 }
 
+#[test]
+fn test_unique_arc_weak() {
+    let data = UniqueArc::new(32);
+
+    // Test that `Weak` downgraded from `UniqueArc` cannot be upgraded.
+    let weak = UniqueArc::downgrade(&data);
+    assert_eq!(weak.strong_count(), 0);
+    assert_eq!(weak.weak_count(), 0);
+    assert!(weak.upgrade().is_none());
+
+    // Test that `Weak` can now be upgraded after the `UniqueArc` being converted to `Arc`.
+    let strong = UniqueArc::into_arc(data);
+    assert_eq!(*strong, 32);
+    assert_eq!(weak.strong_count(), 1);
+    assert_eq!(weak.weak_count(), 1);
+    let upgraded = weak.upgrade().unwrap();
+    assert_eq!(*upgraded, 32);
+    assert_eq!(weak.strong_count(), 2);
+    assert_eq!(weak.weak_count(), 1);
+}
+
 #[allow(unused)]
 mod pin_coerce_unsized {
     use alloc::sync::{Arc, UniqueArc};