about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-03 12:17:19 +0000
committerbors <bors@rust-lang.org>2022-07-03 12:17:19 +0000
commitb04bfb4aea99436a62f6a98056e805eb9b0629cc (patch)
treeeef697fac1f57d2430ef72c8261c02311e549d91
parentf99f9e48ed77a99747c6d07b42fdfe500f1a7de0 (diff)
parentcf483a130cdfa1e72678fd98c74b11fedb3ae8dd (diff)
Auto merge of #97437 - jyn514:impl-asrawfd-arc, r=dtolnay
`impl<T: AsRawFd> AsRawFd for {Arc,Box}<T>`

This allows implementing traits that require a raw FD on Arc and Box.

Previously, you'd have to add the function to the trait itself:

```rust
trait MyTrait {
    fn as_raw_fd(&self) -> RawFd;
}

impl<T: MyTrait> MyTrait for Arc<T> {
    fn as_raw_fd(&self) -> RawFd {
        (**self).as_raw_fd()
    }
}
```

In particular, this leads to lots of "multiple applicable items in scope" errors because you have to disambiguate `MyTrait::as_raw_fd` from `AsRawFd::as_raw_fd` at each call site. In generic contexts, when passing the type to a function that takes `impl AsRawFd` it's also sometimes required to use `T: MyTrait + AsRawFd`, which wouldn't be necessary if I could write `MyTrait: AsRawFd`.

After this PR, the code can be simpler:
```rust
trait MyTrait: AsRawFd {}

impl<T: MyTrait> MyTrait for Arc<T> {}
```
-rw-r--r--library/std/src/os/fd/owned.rs31
-rw-r--r--library/std/src/os/fd/raw.rs31
2 files changed, 62 insertions, 0 deletions
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index dd965ddc01e..d661a13edc5 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -355,3 +355,34 @@ impl From<OwnedFd> for crate::net::UdpSocket {
         ))))
     }
 }
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+/// This impl allows implementing traits that require `AsFd` on Arc.
+/// ```
+/// # #[cfg(any(unix, target_os = "wasi"))] mod group_cfg {
+/// # #[cfg(target_os = "wasi")]
+/// # use std::os::wasi::io::AsFd;
+/// # #[cfg(unix)]
+/// # use std::os::unix::io::AsFd;
+/// use std::net::UdpSocket;
+/// use std::sync::Arc;
+///
+/// trait MyTrait: AsFd {}
+/// impl MyTrait for Arc<UdpSocket> {}
+/// impl MyTrait for Box<UdpSocket> {}
+/// # }
+/// ```
+impl<T: AsFd> AsFd for crate::sync::Arc<T> {
+    #[inline]
+    fn as_fd(&self) -> BorrowedFd<'_> {
+        (**self).as_fd()
+    }
+}
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+impl<T: AsFd> AsFd for Box<T> {
+    #[inline]
+    fn as_fd(&self) -> BorrowedFd<'_> {
+        (**self).as_fd()
+    }
+}
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index 47ee88d97fb..345beb1824d 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -222,3 +222,34 @@ impl<'a> AsRawFd for io::StderrLock<'a> {
         libc::STDERR_FILENO
     }
 }
+
+/// This impl allows implementing traits that require `AsRawFd` on Arc.
+/// ```
+/// # #[cfg(any(unix, target_os = "wasi"))] mod group_cfg {
+/// # #[cfg(target_os = "wasi")]
+/// # use std::os::wasi::io::AsRawFd;
+/// # #[cfg(unix)]
+/// # use std::os::unix::io::AsRawFd;
+/// use std::net::UdpSocket;
+/// use std::sync::Arc;
+/// trait MyTrait: AsRawFd {
+/// }
+/// impl MyTrait for Arc<UdpSocket> {}
+/// impl MyTrait for Box<UdpSocket> {}
+/// # }
+/// ```
+#[stable(feature = "asrawfd_ptrs", since = "1.63.0")]
+impl<T: AsRawFd> AsRawFd for crate::sync::Arc<T> {
+    #[inline]
+    fn as_raw_fd(&self) -> RawFd {
+        (**self).as_raw_fd()
+    }
+}
+
+#[stable(feature = "asrawfd_ptrs", since = "1.63.0")]
+impl<T: AsRawFd> AsRawFd for Box<T> {
+    #[inline]
+    fn as_raw_fd(&self) -> RawFd {
+        (**self).as_raw_fd()
+    }
+}