From 90ff6fcd4ec4a91b9d0a4956d3fd8459931f2de4 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 11 May 2022 07:17:52 -0700 Subject: [PATCH 1/7] 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/7] 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/7] 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/7] 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); From 30108ca15c11f011f6d9e4c06a83cb4dc5644313 Mon Sep 17 00:00:00 2001 From: Volker-Weissmann <39418860+Volker-Weissmann@users.noreply.github.com> Date: Fri, 13 May 2022 18:37:07 +0200 Subject: [PATCH 5/7] Added note in documentation I added this note, because if you forget the `--target` flags, you get a really ugly error message. https://github.com/rust-lang/cargo/issues/10666 --- src/doc/unstable-book/src/compiler-flags/sanitizer.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 3f60caffef5b7..e83c4d98cc7a4 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -22,7 +22,10 @@ This feature allows for use of one of following sanitizers: To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`, `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`, -`-Zsanitizer=memtag`, or `-Zsanitizer=thread`. +`-Zsanitizer=memtag`, or `-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags. Example: +```shell +$ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu +``` # AddressSanitizer From 5d84c0c569792e3dd2cb5b5beeba99ff09b22d1e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 May 2022 13:50:52 +0200 Subject: [PATCH 6/7] Add new eslint rule about brace style --- src/librustdoc/html/static/.eslintrc.js | 5 ++ src/librustdoc/html/static/js/main.js | 4 +- .../html/static/js/scrape-examples.js | 4 +- src/librustdoc/html/static/js/search.js | 73 ++++++++++++------- src/librustdoc/html/static/js/settings.js | 4 +- 5 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index 52577b228aa13..7634a15b9bd19 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -29,5 +29,10 @@ module.exports = { "no-var": ["error"], "prefer-const": ["error"], "prefer-arrow-callback": ["error"], + "brace-style": [ + "error", + "1tbs", + { "allowSingleLine": false } + ], } }; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 1e4d58db196ad..454c7f557b9bc 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -709,8 +709,8 @@ function loadCss(cssFileName) { onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { if (e.parentNode.id !== "implementations-list" || (!hasClass(e, "implementors-toggle") && - !hasClass(e, "type-contents-toggle"))) - { + !hasClass(e, "type-contents-toggle")) + ) { e.open = false; } }); diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js index 408b7e19feadd..7b9d86a851b19 100644 --- a/src/librustdoc/html/static/js/scrape-examples.js +++ b/src/librustdoc/html/static/js/scrape-examples.js @@ -98,7 +98,9 @@ // visible. This is necessary since updateScrapedExample calls scrollToLoc which // depends on offsetHeight, a property that requires an element to be visible to // compute correctly. - setTimeout(() => { onEachLazy(moreExamples, updateScrapedExample); }); + setTimeout(() => { + onEachLazy(moreExamples, updateScrapedExample); + }); }, {once: true}); }); })(); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index b596adf32c6fd..0be70d77d06e4 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -320,8 +320,8 @@ window.initSearch = rawSearchIndex => { if (foundExclamation) { throw new Error("Cannot have more than one `!` in an ident"); } else if (parserState.pos + 1 < parserState.length && - isIdentCharacter(parserState.userQuery[parserState.pos + 1])) - { + isIdentCharacter(parserState.userQuery[parserState.pos + 1]) + ) { throw new Error("`!` can only be at the end of an ident"); } foundExclamation = true; @@ -330,12 +330,10 @@ window.initSearch = rawSearchIndex => { } else if ( isStopCharacter(c) || isSpecialStartCharacter(c) || - isSeparatorCharacter(c)) - { + isSeparatorCharacter(c) + ) { break; - } - // If we allow paths ("str::string" for example). - else if (c === ":") { + } else if (c === ":") { // If we allow paths ("str::string" for example). if (!isPathStart(parserState)) { break; } @@ -372,8 +370,8 @@ window.initSearch = rawSearchIndex => { end = getIdentEndPosition(parserState); } if (parserState.pos < parserState.length && - parserState.userQuery[parserState.pos] === "<") - { + parserState.userQuery[parserState.pos] === "<" + ) { if (isInGenerics) { throw new Error("Unexpected `<` after `<`"); } else if (start >= end) { @@ -592,8 +590,8 @@ window.initSearch = rawSearchIndex => { if (elem && elem.value !== "All crates" && - hasOwnPropertyRustdoc(rawSearchIndex, elem.value)) - { + hasOwnPropertyRustdoc(rawSearchIndex, elem.value) + ) { return elem.value; } return null; @@ -786,37 +784,51 @@ window.initSearch = rawSearchIndex => { // sort by exact match with regard to the last word (mismatch goes later) a = (aaa.word !== userQuery); b = (bbb.word !== userQuery); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // Sort by non levenshtein results and then levenshtein results by the distance // (less changes required to match means higher rankings) a = (aaa.lev); b = (bbb.lev); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by crate (non-current crate goes later) a = (aaa.item.crate !== window.currentCrate); b = (bbb.item.crate !== window.currentCrate); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by item name length (longer goes later) a = aaa.word.length; b = bbb.word.length; - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by item name (lexicographically larger goes later) a = aaa.word; b = bbb.word; - if (a !== b) { return (a > b ? +1 : -1); } + if (a !== b) { + return (a > b ? +1 : -1); + } // sort by index of keyword in item name (no literal occurrence goes later) a = (aaa.index < 0); b = (bbb.index < 0); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // (later literal occurrence, if any, goes later) a = aaa.index; b = bbb.index; - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // special precedence for primitive and keyword pages if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) || @@ -831,17 +843,23 @@ window.initSearch = rawSearchIndex => { // sort by description (no description goes later) a = (aaa.item.desc === ""); b = (bbb.item.desc === ""); - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by type (later occurrence in `itemTypes` goes later) a = aaa.item.ty; b = bbb.item.ty; - if (a !== b) { return a - b; } + if (a !== b) { + return a - b; + } // sort by path (lexicographically larger goes later) a = aaa.item.path; b = bbb.item.path; - if (a !== b) { return (a > b ? +1 : -1); } + if (a !== b) { + return (a > b ? +1 : -1); + } // que sera, sera return 0; @@ -1315,16 +1333,15 @@ window.initSearch = rawSearchIndex => { } if (searchWord.indexOf(elem.pathLast) > -1 || - row.normalizedName.indexOf(elem.pathLast) > -1) - { + row.normalizedName.indexOf(elem.pathLast) > -1 + ) { // filter type: ... queries if (!results_others[fullId] !== undefined) { index = row.normalizedName.indexOf(elem.pathLast); } } lev = levenshtein(searchWord, elem.pathLast); - if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1) - { + if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1) { if (elem.pathLast.length < 6) { lev = 1; } else { @@ -1670,8 +1687,8 @@ window.initSearch = rawSearchIndex => { // By default, the search DOM element is "empty" (meaning it has no children not // text content). Once a search has been run, it won't be empty, even if you press // ESC or empty the search input (which also "cancels" the search). - && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText))) - { + && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)) + ) { const elem = document.createElement("a"); elem.href = results.others[0].href; removeClass(elem, "active"); @@ -1766,7 +1783,7 @@ window.initSearch = rawSearchIndex => { let i = 0; for (const elem of elems) { const j = i; - elem.onclick = () => { printTab(j); }; + elem.onclick = () => printTab(j); searchState.focusedByTab.push(null); i += 1; } diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index df828b5ce4c3a..2e2305029cddd 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -254,8 +254,8 @@ function blurHandler(event) { const settingsButton = getSettingsButton(); if (!elemIsInParent(document.activeElement, settingsButton) && - !elemIsInParent(event.relatedTarget, settingsButton)) - { + !elemIsInParent(event.relatedTarget, settingsButton) + ) { window.hideSettings(); } } From 4f637ee30ba1ec9ab15c8b5d12e80e8ae810a811 Mon Sep 17 00:00:00 2001 From: bdbai Date: Sun, 15 May 2022 21:15:45 +0800 Subject: [PATCH 7/7] fix use of SetHandleInformation on UWP --- library/std/src/os/windows/io/handle.rs | 1 + library/std/src/os/windows/io/socket.rs | 1 + library/std/src/sys/windows/handle.rs | 1 + library/std/src/sys/windows/pipe.rs | 13 ++++++++++++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index f27970eaaf122..0ecac6b447570 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -206,6 +206,7 @@ impl OwnedHandle { } /// Allow child processes to inherit the handle. + #[cfg(not(target_vendor = "uwp"))] pub(crate) fn set_inheritable(&self) -> io::Result<()> { cvt(unsafe { c::SetHandleInformation( diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index c14a1d6192fa2..7231fe7d1b622 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -10,6 +10,7 @@ use crate::mem; use crate::mem::forget; use crate::sys; use crate::sys::c; +#[cfg(not(target_vendor = "uwp"))] use crate::sys::cvt; /// A borrowed socket. diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 3b609825a79da..c319cb28630f5 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -221,6 +221,7 @@ impl Handle { Ok(Self(self.0.duplicate(access, inherit, options)?)) } + #[cfg(not(target_vendor = "uwp"))] pub(crate) fn set_inheritable(&self) -> io::Result<()> { self.0.set_inheritable() } diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index 928bf2439c3e1..2c586f1abe433 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -57,10 +57,21 @@ impl Pipes { } else { let (ours, theirs) = if ours_readable { (read, write) } else { (write, read) }; let ours = Handle::from_raw_handle(ours); + #[cfg(not(target_vendor = "uwp"))] let theirs = Handle::from_raw_handle(theirs); + #[cfg(target_vendor = "uwp")] + let mut theirs = Handle::from_raw_handle(theirs); if their_handle_inheritable { - theirs.set_inheritable()?; + #[cfg(not(target_vendor = "uwp"))] + { + theirs.set_inheritable()?; + } + + #[cfg(target_vendor = "uwp")] + { + theirs = theirs.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)?; + } } Ok(Pipes { ours: AnonPipe::Sync(ours), theirs: AnonPipe::Sync(theirs) })