Repository: crossbeam-rs/crossbeam (rust)

Issue:
Use own unix::JoinHandleExt trait
The standard library's extension traits are not intended to be implemented for types other than the standard library.
Actually, there are discussions about sealing them: rust-lang/rust#81213, rust-lang/rust#80634
As long as we actually have a crate that depends on it, the standard library won't seal it, but it seems preferable to use our own extension trait anyway.

https://github.com/crossbeam-rs/crossbeam/blob/a95c02ea75d236a3560cd85075f71f8982bbf307/crossbeam-utils/src/thread.rs#L550



Pull request:
Use own unix::JoinHandleExt trait
Closes #651

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 347c303..9b51b28 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -61,7 +61,7 @@ jobs:
           # Test 32-bit target that does not have AtomicU64/AtomicI64.
           - rust: nightly
             os: ubuntu-latest
-            target: mips-unknown-linux-gnu
+            target: armv5te-unknown-linux-gnueabi
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v3
diff --git a/crossbeam-deque/src/deque.rs b/crossbeam-deque/src/deque.rs
index 8afe15f..c37de2d 100644
--- a/crossbeam-deque/src/deque.rs
+++ b/crossbeam-deque/src/deque.rs
@@ -80,10 +80,7 @@ impl<T> Buffer<T> {
 
 impl<T> Clone for Buffer<T> {
     fn clone(&self) -> Buffer<T> {
-        Buffer {
-            ptr: self.ptr,
-            cap: self.cap,
-        }
+        *self
     }
 }
 
diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs
index b33a8ac..9ea07eb 100644
--- a/crossbeam-epoch/src/atomic.rs
+++ b/crossbeam-epoch/src/atomic.rs
@@ -1169,10 +1169,7 @@ pub struct Shared<'g, T: 'g + ?Sized + Pointable> {
 
 impl<T: ?Sized + Pointable> Clone for Shared<'_, T> {
     fn clone(&self) -> Self {
-        Self {
-            data: self.data,
-            _marker: PhantomData,
-        }
+        *self
     }
 }
 
diff --git a/crossbeam-utils/src/thread.rs b/crossbeam-utils/src/thread.rs
index 2985790..71856eb 100644
--- a/crossbeam-utils/src/thread.rs
+++ b/crossbeam-utils/src/thread.rs
@@ -120,7 +120,6 @@ use std::sync::{Arc, Mutex};
 use std::thread;
 
 use crate::sync::WaitGroup;
-use cfg_if::cfg_if;
 
 type SharedVec<T> = Arc<Mutex<Vec<T>>>;
 type SharedOption<T> = Arc<Mutex<Option<T>>>;
@@ -548,37 +547,63 @@ impl<T> ScopedJoinHandle<'_, T> {
     }
 }
 
-cfg_if! {
-    if #[cfg(unix)] {
-        use std::os::unix::thread::{JoinHandleExt, RawPthread};
+/// Unix-specific extensions.
+#[cfg(unix)]
+pub mod unix {
+    use super::ScopedJoinHandle;
+    use std::os::unix::thread::JoinHandleExt as _;
 
-        impl<T> JoinHandleExt for ScopedJoinHandle<'_, T> {
-            fn as_pthread_t(&self) -> RawPthread {
-                // Borrow the handle. The handle will surely be available because the root scope waits
-                // for nested scopes before joining remaining threads.
-                let handle = self.handle.lock().unwrap();
-                handle.as_ref().unwrap().as_pthread_t()
-            }
-            fn into_pthread_t(self) -> RawPthread {
-                self.as_pthread_t()
-            }
+    #[doc(no_inline)]
+    pub use std::os::unix::thread::RawPthread;
+
+    mod sealed {
+        pub trait Sealed {}
+    }
+
+    /// Unix-specific extensions to [`ScopedJoinHandle`].
+    pub trait JoinHandleExt: sealed::Sealed {
+        /// Extracts the raw pthread_t without taking ownership
+        fn as_pthread_t(&self) -> RawPthread;
+
+        /// Consumes the thread, returning the raw pthread_t
+        ///
+        /// This function **transfers ownership** of the underlying pthread_t to
+        /// the caller. Callers are then the unique owners of the pthread_t and
+        /// must either detach or join the pthread_t once it's no longer needed.
+        fn into_pthread_t(self) -> RawPthread;
+    }
+
+    impl<T> sealed::Sealed for ScopedJoinHandle<'_, T> {}
+    impl<T> JoinHandleExt for ScopedJoinHandle<'_, T> {
+        fn as_pthread_t(&self) -> RawPthread {
+            // Borrow the handle. The handle will surely be available because the root scope waits
+            // for nested scopes before joining remaining threads.
+            let handle = self.handle.lock().unwrap();
+            handle.as_ref().unwrap().as_pthread_t()
         }
-    } else if #[cfg(windows)] {
-        use std::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle};
-
-        impl<T> AsRawHandle for ScopedJoinHandle<'_, T> {
-            fn as_raw_handle(&self) -> RawHandle {
-                // Borrow the handle. The handle will surely be available because the root scope waits
-                // for nested scopes before joining remaining threads.
-                let handle = self.handle.lock().unwrap();
-                handle.as_ref().unwrap().as_raw_handle()
-            }
+        fn into_pthread_t(self) -> RawPthread {
+            self.as_pthread_t()
+        }
+    }
+}
+/// Windows-specific extensions.
+#[cfg(windows)]
+mod windows {
+    use super::ScopedJoinHandle;
+    use std::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle};
+
+    impl<T> AsRawHandle for ScopedJoinHandle<'_, T> {
+        fn as_raw_handle(&self) -> RawHandle {
+            // Borrow the handle. The handle will surely be available because the root scope waits
+            // for nested scopes before joining remaining threads.
+            let handle = self.handle.lock().unwrap();
+            handle.as_ref().unwrap().as_raw_handle()
         }
+    }
 
-        impl<T> IntoRawHandle for ScopedJoinHandle<'_, T> {
-            fn into_raw_handle(self) -> RawHandle {
-                self.as_raw_handle()
-            }
+    impl<T> IntoRawHandle for ScopedJoinHandle<'_, T> {
+        fn into_raw_handle(self) -> RawHandle {
+            self.as_raw_handle()
         }
     }
 }


Test patch:
diff --git a/crossbeam-utils/tests/thread.rs b/crossbeam-utils/tests/thread.rs
index 0dfad90..467454c 100644
--- a/crossbeam-utils/tests/thread.rs
+++ b/crossbeam-utils/tests/thread.rs
@@ -187,7 +187,7 @@ fn scope_returns_ok() {
 #[cfg(unix)]
 #[test]
 fn as_pthread_t() {
-    use std::os::unix::thread::JoinHandleExt;
+    use thread::unix::JoinHandleExt;
     thread::scope(|scope| {
         let handle = scope.spawn(|_scope| {
             sleep(Duration::from_millis(100));