about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDan Gohman <dev@sunfishcode.online>2022-05-11 07:17:52 -0700
committerDan Gohman <dev@sunfishcode.online>2022-05-11 07:26:49 -0700
commit90ff6fcd4ec4a91b9d0a4956d3fd8459931f2de4 (patch)
tree1658c667bcc8a8245c9d24d591cbc4c74e35fb11
parentecd44958e0a21110d09862ee080d95a4ca6c52f8 (diff)
downloadrust-90ff6fcd4ec4a91b9d0a4956d3fd8459931f2de4.tar.gz
rust-90ff6fcd4ec4a91b9d0a4956d3fd8459931f2de4.zip
Add rustc_nonnull_optimization_guaranteed to Owned/Borrowed Fd/Socket
PR #94586 added support for using
`rustc_nonnull_optimization_guaranteed` on values where the "null" value
is the all-ones bitpattern.

Now that #94586 has made it to the stage0 compiler, add
`rustc_nonnull_optimization_guaranteed` to `OwnedFd`, `BorrowedFd`,
`OwnedSocket`, and `BorrowedSocket`, since these types all exclude
all-ones bitpatterns.

This allows `Option<OwnedFd>`, `Option<BorrowedFd>`, `Option<OwnedSocket>`,
and `Option<BorrowedSocket>` to be used in FFI declarations, as described
in the [I/O safety RFC].

[I/O safety RFC]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md#ownedfd-and-borrowedfdfd-1
-rw-r--r--library/std/src/os/fd/owned.rs2
-rw-r--r--library/std/src/os/fd/tests.rs19
-rw-r--r--library/std/src/os/windows/io/mod.rs3
-rw-r--r--library/std/src/os/windows/io/socket.rs2
-rw-r--r--library/std/src/os/windows/io/tests.rs22
5 files changed, 48 insertions, 0 deletions
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index bfc5ce01564..53433823fbd 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -32,6 +32,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 // 32-bit c_int. Below is -2, in two's complement, but that only works out
 // because c_int is 32 bits.
 #[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
+#[rustc_nonnull_optimization_guaranteed]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct BorrowedFd<'fd> {
     fd: RawFd,
@@ -52,6 +53,7 @@ pub struct BorrowedFd<'fd> {
 // 32-bit c_int. Below is -2, in two's complement, but that only works out
 // because c_int is 32 bits.
 #[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
+#[rustc_nonnull_optimization_guaranteed]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct OwnedFd {
     fd: RawFd,
diff --git a/library/std/src/os/fd/tests.rs b/library/std/src/os/fd/tests.rs
index 26ef93e3d71..b39863644f1 100644
--- a/library/std/src/os/fd/tests.rs
+++ b/library/std/src/os/fd/tests.rs
@@ -32,3 +32,22 @@ fn test_fd() {
     assert_eq!(stdin_as_file.as_fd().as_raw_fd(), raw_fd);
     assert_eq!(Into::<OwnedFd>::into(stdin_as_file).into_raw_fd(), raw_fd);
 }
+
+#[cfg(any(unix, target_os = "wasi"))]
+#[test]
+fn test_niche_optimizations() {
+    use crate::mem::size_of;
+    #[cfg(unix)]
+    use crate::os::unix::io::{BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+    #[cfg(target_os = "wasi")]
+    use crate::os::wasi::io::{BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+
+    assert_eq!(size_of::<Option<OwnedFd>>(), size_of::<RawFd>());
+    assert_eq!(size_of::<Option<BorrowedFd<'static>>>(), size_of::<RawFd>());
+    unsafe {
+        assert_eq!(OwnedFd::from_raw_fd(RawFd::MIN).into_raw_fd(), RawFd::MIN);
+        assert_eq!(OwnedFd::from_raw_fd(RawFd::MAX).into_raw_fd(), RawFd::MAX);
+        assert_eq!(Some(OwnedFd::from_raw_fd(RawFd::MIN)).unwrap().into_raw_fd(), RawFd::MIN);
+        assert_eq!(Some(OwnedFd::from_raw_fd(RawFd::MAX)).unwrap().into_raw_fd(), RawFd::MAX);
+    }
+}
diff --git a/library/std/src/os/windows/io/mod.rs b/library/std/src/os/windows/io/mod.rs
index 2f6f0769548..3325688e661 100644
--- a/library/std/src/os/windows/io/mod.rs
+++ b/library/std/src/os/windows/io/mod.rs
@@ -54,3 +54,6 @@ pub use handle::*;
 pub use raw::*;
 #[unstable(feature = "io_safety", issue = "87074")]
 pub use socket::*;
+
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index c14a1d6192f..baae92c19f2 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -34,6 +34,7 @@ use crate::sys::cvt;
     target_pointer_width = "64",
     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
 )]
+#[rustc_nonnull_optimization_guaranteed]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct BorrowedSocket<'socket> {
     socket: RawSocket,
@@ -56,6 +57,7 @@ pub struct BorrowedSocket<'socket> {
     target_pointer_width = "64",
     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
 )]
+#[rustc_nonnull_optimization_guaranteed]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct OwnedSocket {
     socket: RawSocket,
diff --git a/library/std/src/os/windows/io/tests.rs b/library/std/src/os/windows/io/tests.rs
new file mode 100644
index 00000000000..54175473707
--- /dev/null
+++ b/library/std/src/os/windows/io/tests.rs
@@ -0,0 +1,22 @@
+#[test]
+fn test_niche_optimizations_socket() {
+    use crate::mem::size_of;
+    use crate::os::windows::io::{
+        BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, OwnedSocket, RawSocket,
+    };
+
+    assert_eq!(size_of::<Option<OwnedSocket>>(), size_of::<RawSocket>());
+    assert_eq!(size_of::<Option<BorrowedSocket<'static>>>(), size_of::<RawSocket>(),);
+    unsafe {
+        assert_eq!(OwnedSocket::from_raw_socket(RawSocket::MIN).into_raw_socket(), RawSocket::MIN);
+        assert_eq!(OwnedSocket::from_raw_socket(RawSocket::MAX).into_raw_socket(), RawSocket::MAX);
+        assert_eq!(
+            Some(OwnedSocket::from_raw_socket(RawSocket::MIN)).unwrap().into_raw_socket(),
+            RawSocket::MIN
+        );
+        assert_eq!(
+            Some(OwnedSocket::from_raw_socket(RawSocket::MAX)).unwrap().into_raw_socket(),
+            RawSocket::MAX
+        );
+    }
+}