From 90ff6fcd4ec4a91b9d0a4956d3fd8459931f2de4 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 11 May 2022 07:17:52 -0700 Subject: [PATCH 1/4] 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`, `Option`, `Option`, and `Option` 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 --- library/std/src/os/fd/owned.rs | 2 ++ library/std/src/os/fd/tests.rs | 19 +++++++++++++++++++ library/std/src/os/windows/io/mod.rs | 3 +++ library/std/src/os/windows/io/socket.rs | 2 ++ library/std/src/os/windows/io/tests.rs | 22 ++++++++++++++++++++++ 5 files changed, 48 insertions(+) create mode 100644 library/std/src/os/windows/io/tests.rs diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index bfc5ce0156415..53433823fbd3b 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 26ef93e3d7110..b39863644f116 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::::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::>(), size_of::()); + assert_eq!(size_of::>>(), size_of::()); + 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 2f6f076954809..3325688e661ef 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 c14a1d6192fa2..baae92c19f206 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 0000000000000..541754737070d --- /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::>(), size_of::()); + assert_eq!(size_of::>>(), size_of::(),); + 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 + ); + } +} From 78806d4cfe59b05e41023a7c5363083c323c9bfb Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 11 May 2022 07:41:34 -0700 Subject: [PATCH 2/4] Fix duplicate import on Windows. --- library/std/src/os/windows/io/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/windows/io/tests.rs b/library/std/src/os/windows/io/tests.rs index 541754737070d..b85b57591d418 100644 --- a/library/std/src/os/windows/io/tests.rs +++ b/library/std/src/os/windows/io/tests.rs @@ -2,7 +2,7 @@ fn test_niche_optimizations_socket() { use crate::mem::size_of; use crate::os::windows::io::{ - BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, OwnedSocket, RawSocket, + BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket, }; assert_eq!(size_of::>(), size_of::()); From a5077f13428cc8b950b5b8fb9dc1398f54a6a2ef Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 11 May 2022 09:10:33 -0700 Subject: [PATCH 3/4] RawSocket is unsigned on Windows. --- library/std/src/os/windows/io/tests.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/library/std/src/os/windows/io/tests.rs b/library/std/src/os/windows/io/tests.rs index b85b57591d418..d24250c227e53 100644 --- a/library/std/src/os/windows/io/tests.rs +++ b/library/std/src/os/windows/io/tests.rs @@ -8,15 +8,14 @@ fn test_niche_optimizations_socket() { assert_eq!(size_of::>(), size_of::()); assert_eq!(size_of::>>(), size_of::(),); 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 - ); + #[cfg(target_pointer_size = "32")] + let (min, max) = (i32::MIN as u32, i32::MAX as u32); + #[cfg(target_pointer_size = "64")] + let (min, max) = (i64::MIN as u64, i64::MAX as u64); + + assert_eq!(OwnedSocket::from_raw_socket(min).into_raw_socket(), min); + assert_eq!(OwnedSocket::from_raw_socket(max).into_raw_socket(), max); + assert_eq!(Some(OwnedSocket::from_raw_socket(min)).unwrap().into_raw_socket(), min); + assert_eq!(Some(OwnedSocket::from_raw_socket(max)).unwrap().into_raw_socket(), max); } } From 5c60951344d180f5a21ba550dae77847dcd92de0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 11 May 2022 09:29:08 -0700 Subject: [PATCH 4/4] Fix attribute name. --- library/std/src/os/windows/io/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/windows/io/tests.rs b/library/std/src/os/windows/io/tests.rs index d24250c227e53..41734e52e8cce 100644 --- a/library/std/src/os/windows/io/tests.rs +++ b/library/std/src/os/windows/io/tests.rs @@ -8,9 +8,9 @@ fn test_niche_optimizations_socket() { assert_eq!(size_of::>(), size_of::()); assert_eq!(size_of::>>(), size_of::(),); unsafe { - #[cfg(target_pointer_size = "32")] + #[cfg(target_pointer_width = "32")] let (min, max) = (i32::MIN as u32, i32::MAX as u32); - #[cfg(target_pointer_size = "64")] + #[cfg(target_pointer_width = "64")] let (min, max) = (i64::MIN as u64, i64::MAX as u64); assert_eq!(OwnedSocket::from_raw_socket(min).into_raw_socket(), min);