From 9412a898fa4ed5065a363bd40ad9401469ed3d54 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Wed, 2 Sep 2020 02:35:14 +0200 Subject: [PATCH 01/22] Stabilize `Poll::is_ready` and `is_pending` as const Insta-stabilize the methods `is_ready` and `is_pending` of `Poll`. Possible because of the recent stabilization of const control flow. Also adds a test for these methods in a const context. --- library/core/src/task/poll.rs | 6 ++++-- src/test/ui/consts/std/poll.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/std/poll.rs diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 9383e7c45fa55..a789e4e2593ee 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -39,15 +39,17 @@ impl Poll { /// Returns `true` if this is `Poll::Ready` #[inline] + #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] #[stable(feature = "futures_api", since = "1.36.0")] - pub fn is_ready(&self) -> bool { + pub const fn is_ready(&self) -> bool { matches!(*self, Poll::Ready(_)) } /// Returns `true` if this is `Poll::Pending` #[inline] + #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] #[stable(feature = "futures_api", since = "1.36.0")] - pub fn is_pending(&self) -> bool { + pub const fn is_pending(&self) -> bool { !self.is_ready() } } diff --git a/src/test/ui/consts/std/poll.rs b/src/test/ui/consts/std/poll.rs new file mode 100644 index 0000000000000..28f2ace6715fe --- /dev/null +++ b/src/test/ui/consts/std/poll.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::task::Poll; + +fn main() { + const POLL : Poll = Poll::Pending; + + const IS_READY : bool = POLL.is_ready(); + assert!(!IS_READY); + + const IS_PENDING : bool = POLL.is_pending(); + assert!(IS_PENDING); +} From ce1d5ed31aff33bbbb116fffabd6107491c464bc Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Fri, 4 Sep 2020 01:04:34 +0200 Subject: [PATCH 02/22] Move const tests for `Poll` to `library\core` Part of #76268 --- library/core/tests/lib.rs | 1 + library/core/tests/task.rs | 14 ++++++++++++++ src/test/ui/consts/std/poll.rs | 13 ------------- 3 files changed, 15 insertions(+), 13 deletions(-) create mode 100644 library/core/tests/task.rs delete mode 100644 src/test/ui/consts/std/poll.rs diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 81e621318e141..2c20259fc5855 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -76,5 +76,6 @@ mod result; mod slice; mod str; mod str_lossy; +mod task; mod time; mod tuple; diff --git a/library/core/tests/task.rs b/library/core/tests/task.rs new file mode 100644 index 0000000000000..d71fef9e5c87d --- /dev/null +++ b/library/core/tests/task.rs @@ -0,0 +1,14 @@ +use core::task::Poll; + +#[test] +fn poll_const() { + // test that the methods of `Poll` are usable in a const context + + const POLL: Poll = Poll::Pending; + + const IS_READY: bool = POLL.is_ready(); + assert!(!IS_READY); + + const IS_PENDING: bool = POLL.is_pending(); + assert!(IS_PENDING); +} diff --git a/src/test/ui/consts/std/poll.rs b/src/test/ui/consts/std/poll.rs deleted file mode 100644 index 28f2ace6715fe..0000000000000 --- a/src/test/ui/consts/std/poll.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass - -use std::task::Poll; - -fn main() { - const POLL : Poll = Poll::Pending; - - const IS_READY : bool = POLL.is_ready(); - assert!(!IS_READY); - - const IS_PENDING : bool = POLL.is_pending(); - assert!(IS_PENDING); -} From 91a9f83dd1d73cfd451f81306361df3fafad84a5 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Oct 2020 09:09:20 -0700 Subject: [PATCH 03/22] Define `fs::hard_link` to not follow symlinks. POSIX leaves it implementation-defined whether `link` follows symlinks. In practice, for example, on Linux it does not and on FreeBSD it does. So, switch to `linkat`, so that we can pick a behavior rather than depending on OS defaults. Pick the option to not follow symlinks. This is somewhat arbitrary, but seems the less surprising choice because hard linking is a very low-level feature which requires the source and destination to be on the same mounted filesystem, and following a symbolic link could end up in a different mounted filesystem. --- library/std/src/fs.rs | 7 +++-- library/std/src/fs/tests.rs | 51 ++++++++++++++++++++++++++++++++++ library/std/src/sys/unix/fs.rs | 5 +++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 161bfe3795c2c..c611bf4d74a49 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1701,10 +1701,13 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. /// +/// If `src` names a symbolic link, it is not followed. The created hard link +/// points to the symbolic link itself. +/// /// # Platform-specific behavior /// -/// This function currently corresponds to the `link` function on Unix -/// and the `CreateHardLink` function on Windows. +/// This function currently corresponds to the `linkat` function with no flags +/// on Unix and the `CreateHardLink` function on Windows. /// Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 65a29076fefa8..8a723d3b4ae22 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1337,3 +1337,54 @@ fn metadata_access_times() { } } } + +/// Test creating hard links to symlinks. +#[test] +fn symlink_hard_link() { + let tmpdir = tmpdir(); + + // Create "file", a file. + check!(fs::File::create(tmpdir.join("file"))); + + // Create "symlink", a symlink to "file". + check!(symlink_file("file", tmpdir.join("symlink"))); + + // Create "hard_link", a hard link to "symlink". + check!(fs::hard_link(tmpdir.join("symlink"), tmpdir.join("hard_link"))); + + // "hard_link" should appear as a symlink. + assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); + + // We sould be able to open "file" via any of the above names. + let _ = check!(fs::File::open(tmpdir.join("file"))); + assert!(fs::File::open(tmpdir.join("file.renamed")).is_err()); + let _ = check!(fs::File::open(tmpdir.join("symlink"))); + let _ = check!(fs::File::open(tmpdir.join("hard_link"))); + + // Rename "file" to "file.renamed". + check!(fs::rename(tmpdir.join("file"), tmpdir.join("file.renamed"))); + + // Now, the symlink and the hard link should be dangling. + assert!(fs::File::open(tmpdir.join("file")).is_err()); + let _ = check!(fs::File::open(tmpdir.join("file.renamed"))); + assert!(fs::File::open(tmpdir.join("symlink")).is_err()); + assert!(fs::File::open(tmpdir.join("hard_link")).is_err()); + + // The symlink and the hard link should both still point to "file". + assert!(fs::read_link(tmpdir.join("file")).is_err()); + assert!(fs::read_link(tmpdir.join("file.renamed")).is_err()); + assert_eq!(check!(fs::read_link(tmpdir.join("symlink"))), Path::new("file")); + assert_eq!(check!(fs::read_link(tmpdir.join("hard_link"))), Path::new("file")); + + // Remove "file.renamed". + check!(fs::remove_file(tmpdir.join("file.renamed"))); + + // Now, we can't open the file by any name. + assert!(fs::File::open(tmpdir.join("file")).is_err()); + assert!(fs::File::open(tmpdir.join("file.renamed")).is_err()); + assert!(fs::File::open(tmpdir.join("symlink")).is_err()); + assert!(fs::File::open(tmpdir.join("hard_link")).is_err()); + + // "hard_link" should still appear as a symlink. + assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); +} diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 819e8ef18415b..88693e4786c0f 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1067,7 +1067,10 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; - cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; + // Use `linkat` with `AT_FDCWD` instead of `link` as `link` leaves it + // implmentation-defined whether it follows symlinks. Pass 0 as the + // `linkat` flags argument so that we don't follow symlinks. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; Ok(()) } From 5e80c65102f85700e1a449847dfa603e589df950 Mon Sep 17 00:00:00 2001 From: CDirkx Date: Fri, 16 Oct 2020 21:29:21 +0200 Subject: [PATCH 04/22] Bump version to 1.49.0 Due to the recent release of 1.47.0, this PR will be stabilized in 1.49.0 instead of 1.48.0. --- library/core/src/task/poll.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index a789e4e2593ee..dc405465f5d36 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -39,7 +39,7 @@ impl Poll { /// Returns `true` if this is `Poll::Ready` #[inline] - #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] + #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] pub const fn is_ready(&self) -> bool { matches!(*self, Poll::Ready(_)) @@ -47,7 +47,7 @@ impl Poll { /// Returns `true` if this is `Poll::Pending` #[inline] - #[rustc_const_stable(feature = "const_poll", since = "1.48.0")] + #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] pub const fn is_pending(&self) -> bool { !self.is_ready() From 23a5c214150f462043ab411f87ef297309421d71 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 19 Oct 2020 07:21:41 -0700 Subject: [PATCH 05/22] Fix a typo in a comment. --- library/std/src/sys/unix/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 88693e4786c0f..69f6b88a3bc56 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1068,7 +1068,7 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; // Use `linkat` with `AT_FDCWD` instead of `link` as `link` leaves it - // implmentation-defined whether it follows symlinks. Pass 0 as the + // implementation-defined whether it follows symlinks. Pass 0 as the // `linkat` flags argument so that we don't follow symlinks. cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; Ok(()) From ce00b3e2e0c5c0c88fe59fb45a1c25a8ff9e1836 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 19 Oct 2020 07:47:32 -0700 Subject: [PATCH 06/22] Use `link` on platforms which lack `linkat`. --- library/std/src/sys/unix/fs.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 69f6b88a3bc56..bf4c941928719 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1067,10 +1067,20 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; - // Use `linkat` with `AT_FDCWD` instead of `link` as `link` leaves it - // implementation-defined whether it follows symlinks. Pass 0 as the - // `linkat` flags argument so that we don't follow symlinks. - cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; + cfg_if::cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "redox"))] { + // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX + // leaves it implementation-defined whether `link` follows symlinks, + // so rely on the `symlink_hard_link` test in + // library/std/src/fs/tests.rs to check the behavior. + cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; + } else { + // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives + // us a flag to specify how symlinks should be handled. Pass 0 as + // the flags argument, meaning don't follow symlinks. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; + } + } Ok(()) } From 628fb9ff4a36c706789980276c165c4f013780cf Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 21 Oct 2020 04:44:59 +0200 Subject: [PATCH 07/22] make concurrency helper more pleasant to read --- library/test/src/helpers/concurrency.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs index 7e9bd50f5566e..c39a9b0ec0233 100644 --- a/library/test/src/helpers/concurrency.rs +++ b/library/test/src/helpers/concurrency.rs @@ -1,18 +1,14 @@ //! Helper module which helps to determine amount of threads to be used //! during tests execution. -use std::env; -use std::thread; +use std::{env, num::NonZeroUsize, thread}; -#[allow(deprecated)] pub fn get_concurrency() -> usize { - match env::var("RUST_TEST_THREADS") { - Ok(s) => { - let opt_n: Option = s.parse().ok(); - match opt_n { - Some(n) if n > 0 => n, - _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", s), - } + if let Ok(value) = env::var("RUST_TEST_THREADS") { + match value.parse::().ok() { + Some(n) => n.get(), + _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", value), } - Err(..) => thread::available_concurrency().map(|n| n.get()).unwrap_or(1), + } else { + thread::available_concurrency().map(|n| n.get()).unwrap_or(1) } } From d0178b4f99c70d2443f9b76421429d0d23dadc45 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 20 Oct 2020 16:42:31 -0700 Subject: [PATCH 08/22] Make it platform-specific whether `hard_link` follows symlinks. Also mention that where possible, `hard_link` does not follow symlinks. --- library/std/src/fs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c611bf4d74a49..c256f556b3c8f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1701,8 +1701,9 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. /// -/// If `src` names a symbolic link, it is not followed. The created hard link -/// points to the symbolic link itself. +/// If `src` names a symbolic link, it is platform-specific whether the symbolic +/// link is followed. On platforms where it's possible to not follow it, it is +/// not followed, and the created hard link points to the symbolic link itself. /// /// # Platform-specific behavior /// From 6249cda78f0cd32b60fb11702b7ffef3e3bab0b2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 23 Oct 2020 15:39:02 -0700 Subject: [PATCH 09/22] Disable use of `linkat` on Android as well. According to [the bionic status page], `linkat` has only been available since API level 21. Since Android is based on Linux and Linux's `link` doesn't follow symlinks, just use `link` on Android. [the bionic status page]: https://android.googlesource.com/platform/bionic/+/master/docs/status.md --- library/std/src/sys/unix/fs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index bf4c941928719..ec721fccaa622 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1068,11 +1068,11 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox"))] { - // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX - // leaves it implementation-defined whether `link` follows symlinks, - // so rely on the `symlink_hard_link` test in - // library/std/src/fs/tests.rs to check the behavior. + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] { + // VxWorks, Redox, and old versions of Android lack `linkat`, so use + // `link` instead. POSIX leaves it implementation-defined whether + // `link` follows symlinks, so rely on the `symlink_hard_link` test + // in library/std/src/fs/tests.rs to check the behavior. cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; } else { // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives From e099138eb6274b8450fbbb3c1fec0389337eb992 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 26 Oct 2020 23:31:45 +0100 Subject: [PATCH 10/22] BTreeMap: stop mistaking node for an orderly place --- .../alloc/src/collections/btree/map/tests.rs | 26 +++++++++++-- .../alloc/src/collections/btree/node/tests.rs | 37 ------------------- 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index adb94972f5bb6..f6921e67636d9 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -42,7 +42,7 @@ fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator } } -impl<'a, K: 'a, V: 'a> BTreeMap { +impl BTreeMap { /// Panics if the map (or the code navigating it) is corrupted. fn check(&self) where @@ -54,14 +54,14 @@ impl<'a, K: 'a, V: 'a> BTreeMap { assert!(root_node.ascend().is_err()); root_node.assert_back_pointers(); - let counted = root_node.assert_ascending(); - assert_eq!(self.length, counted); assert_eq!(self.length, root_node.calc_length()); root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 }); } else { assert_eq!(self.length, 0); } + + self.assert_ascending(); } /// Returns the height of the root, if any. @@ -79,10 +79,28 @@ impl<'a, K: 'a, V: 'a> BTreeMap { String::from("not yet allocated") } } + + /// Asserts that the keys are in strictly ascending order. + fn assert_ascending(&self) + where + K: Copy + Debug + Ord, + { + let mut num_seen = 0; + let mut keys = self.keys(); + if let Some(mut previous) = keys.next() { + num_seen = 1; + for next in keys { + assert!(previous < next, "{:?} >= {:?}", previous, next); + previous = next; + num_seen += 1; + } + } + assert_eq!(num_seen, self.len()); + } } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { - pub fn assert_min_len(self, min_len: usize) { + fn assert_min_len(self, min_len: usize) { assert!(self.len() >= min_len, "{} < {}", self.len(), min_len); if let node::ForceResult::Internal(node) = self.force() { for idx in 0..=node.len() { diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index d6527057c5d77..38c75de34eeeb 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -17,43 +17,6 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> } } - /// Asserts that the keys are in strictly ascending order. - /// Returns how many keys it encountered. - pub fn assert_ascending(self) -> usize - where - K: Copy + Debug + Ord, - { - struct SeriesChecker { - num_seen: usize, - previous: Option, - } - impl SeriesChecker { - fn is_ascending(&mut self, next: T) { - if let Some(previous) = self.previous { - assert!(previous < next, "{:?} >= {:?}", previous, next); - } - self.previous = Some(next); - self.num_seen += 1; - } - } - - let mut checker = SeriesChecker { num_seen: 0, previous: None }; - self.visit_nodes_in_order(|pos| match pos { - navigate::Position::Leaf(node) => { - for idx in 0..node.len() { - let key = *unsafe { node.key_at(idx) }; - checker.is_ascending(key); - } - } - navigate::Position::InternalKV(kv) => { - let key = *kv.into_kv().0; - checker.is_ascending(key); - } - navigate::Position::Internal(_) => {} - }); - checker.num_seen - } - pub fn dump_keys(self) -> String where K: Debug, From b0df3f76dc70eba57d6e0665fa6ccac89b25d3aa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Oct 2020 09:05:45 +0100 Subject: [PATCH 11/22] fix some incorrect aliasing in the BTree --- library/alloc/src/collections/btree/node.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index c8d3de9e5cd5c..433074027e7f7 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1608,15 +1608,19 @@ pub mod marker { unsafe fn slice_insert(slice: &mut [T], idx: usize, val: T) { unsafe { - ptr::copy(slice.as_ptr().add(idx), slice.as_mut_ptr().add(idx + 1), slice.len() - idx); - ptr::write(slice.get_unchecked_mut(idx), val); + let len = slice.len(); + let slice_ptr = slice.as_mut_ptr(); + ptr::copy(slice_ptr.add(idx), slice_ptr.add(idx + 1), len - idx); + ptr::write(slice_ptr.add(idx), val); } } unsafe fn slice_remove(slice: &mut [T], idx: usize) -> T { unsafe { - let ret = ptr::read(slice.get_unchecked(idx)); - ptr::copy(slice.as_ptr().add(idx + 1), slice.as_mut_ptr().add(idx), slice.len() - idx - 1); + let len = slice.len(); + let slice_ptr = slice.as_mut_ptr(); + let ret = ptr::read(slice_ptr.add(idx)); + ptr::copy(slice_ptr.add(idx + 1), slice_ptr.add(idx), len - idx - 1); ret } } From 59c6ae615e5547610c3348b466a45ff2a5b3d935 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Fri, 30 Oct 2020 14:05:53 +0100 Subject: [PATCH 12/22] Use SOCK_CLOEXEC and accept4() on more platforms. --- library/std/src/sys/unix/net.rs | 38 +++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 74c7db27226ef..71c6aa5a0e7ea 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -55,9 +55,18 @@ impl Socket { pub fn new_raw(fam: c_int, ty: c_int) -> io::Result { unsafe { cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { - // On Linux we pass the SOCK_CLOEXEC flag to atomically create - // the socket and set it as CLOEXEC, added in 2.6.27. + if #[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "illumos", + target_os = "linux", + target_os = "netbsd", + target_os = "opensbd", + ))] { + // On platforms that support it we pass the SOCK_CLOEXEC + // flag to atomically create the socket and set it as + // CLOEXEC. On Linux this was added in 2.6.27. let fd = cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0))?; Ok(Socket(FileDesc::new(fd))) } else { @@ -83,7 +92,15 @@ impl Socket { let mut fds = [0, 0]; cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { + if #[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "illumos", + target_os = "linux", + target_os = "netbsd", + target_os = "opensbd", + ))] { // Like above, set cloexec atomically cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?; Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1])))) @@ -174,9 +191,18 @@ impl Socket { pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result { // Unfortunately the only known way right now to accept a socket and // atomically set the CLOEXEC flag is to use the `accept4` syscall on - // Linux. This was added in 2.6.28, glibc 2.10 and musl 0.9.5. + // platforms that support it. On Linux, this was added in 2.6.28, + // glibc 2.10 and musl 0.9.5. cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { + if #[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "illumos", + target_os = "linux", + target_os = "netbsd", + target_os = "opensbd", + ))] { let fd = cvt_r(|| unsafe { libc::accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC) })?; From 39103ced582f1111af41326f904966aedd8bc47f Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 3 Nov 2020 16:55:33 +0100 Subject: [PATCH 13/22] Fix run-make tests running when LLVM is disabled --- src/bootstrap/test.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 6c2c05ac7197e..97aad8ed646e8 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1203,17 +1203,6 @@ note: if you're sure you want to do this, please open an issue as to why. In the // Only pass correct values for these flags for the `run-make` suite as it // requires that a C++ compiler was configured which isn't always the case. if !builder.config.dry_run && matches!(suite, "run-make" | "run-make-fulldeps") { - cmd.arg("--cc") - .arg(builder.cc(target)) - .arg("--cxx") - .arg(builder.cxx(target).unwrap()) - .arg("--cflags") - .arg(builder.cflags(target, GitRepo::Rustc).join(" ")); - copts_passed = true; - if let Some(ar) = builder.ar(target) { - cmd.arg("--ar").arg(ar); - } - // The llvm/bin directory contains many useful cross-platform // tools. Pass the path to run-make tests so they can use them. let llvm_bin_path = llvm_config @@ -1239,6 +1228,21 @@ note: if you're sure you want to do this, please open an issue as to why. In the } } + // Only pass correct values for these flags for the `run-make` suite as it + // requires that a C++ compiler was configured which isn't always the case. + if !builder.config.dry_run && matches!(suite, "run-make" | "run-make-fulldeps") { + cmd.arg("--cc") + .arg(builder.cc(target)) + .arg("--cxx") + .arg(builder.cxx(target).unwrap()) + .arg("--cflags") + .arg(builder.cflags(target, GitRepo::Rustc).join(" ")); + copts_passed = true; + if let Some(ar) = builder.ar(target) { + cmd.arg("--ar").arg(ar); + } + } + if !llvm_components_passed { cmd.arg("--llvm-components").arg(""); } From 5fc22f1431e209610040d92ba671966ab2781f0b Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Sun, 1 Nov 2020 19:43:51 -0800 Subject: [PATCH 14/22] Add a tool to run `x.py` from any subdirectory This adds a binary called `x` in `src/tools/x`. All it does is check the current directory and its ancestors for a file called `x.py`, and if it finds one, runs it. By installing x, you can easily `x.py` from any subdirectory. It can be installed globally with `cargo install --path src/tools/x` --- .gitignore | 1 + Cargo.toml | 6 +++ src/tools/x/Cargo.lock | 5 +++ src/tools/x/Cargo.toml | 7 ++++ src/tools/x/README.md | 3 ++ src/tools/x/src/main.rs | 92 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 114 insertions(+) create mode 100644 src/tools/x/Cargo.lock create mode 100644 src/tools/x/Cargo.toml create mode 100644 src/tools/x/README.md create mode 100644 src/tools/x/src/main.rs diff --git a/.gitignore b/.gitignore index 1c50d9b054ddc..5f7135e38d113 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ __pycache__/ /inst/ /llvm/ /mingw-build/ +/src/tools/x/target # Created by default with `src/ci/docker/run.sh`: /obj/ /unicode-downloads diff --git a/Cargo.toml b/Cargo.toml index 02794d1028b50..38fd72ace5385 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,10 +29,16 @@ members = [ "src/tools/unicode-table-generator", "src/tools/expand-yaml-anchors", ] + exclude = [ "build", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", + # The `x` binary is a thin wrapper that calls `x.py`, which initializes + # submodules, before which workspace members cannot be invoked because + # not all `Cargo.toml` files are available, so we exclude the `x` binary, + # so it can be invoked before the current checkout is set up. + "src/tools/x", ] [profile.release.package.compiler_builtins] diff --git a/src/tools/x/Cargo.lock b/src/tools/x/Cargo.lock new file mode 100644 index 0000000000000..723d6cb25ed6a --- /dev/null +++ b/src/tools/x/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "x" +version = "0.1.0" diff --git a/src/tools/x/Cargo.toml b/src/tools/x/Cargo.toml new file mode 100644 index 0000000000000..72c4948c617fa --- /dev/null +++ b/src/tools/x/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "x" +version = "0.1.0" +description = "Run x.py slightly more conveniently" +authors = ["Casey Rodarmor "] +edition = "2018" +publish = false diff --git a/src/tools/x/README.md b/src/tools/x/README.md new file mode 100644 index 0000000000000..3b3cf2847c200 --- /dev/null +++ b/src/tools/x/README.md @@ -0,0 +1,3 @@ +# x + +`x` invokes `x.py` from any subdirectory. diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs new file mode 100644 index 0000000000000..6c0311433d676 --- /dev/null +++ b/src/tools/x/src/main.rs @@ -0,0 +1,92 @@ +//! Run `x.py` from any subdirectory of a rust compiler checkout. +//! +//! We prefer `exec`, to avoid adding an extra process in the process tree. +//! However, since `exec` isn't available on Windows, we indirect through +//! `exec_or_status`, which will call `exec` on unix and `status` on Windows. +//! +//! We use `python`, `python3`, or `python2` as the python interpreter to run +//! `x.py`, in that order of preference. + +use std::{ + env, io, + process::{self, Command, ExitStatus}, +}; + +const PYTHON: &str = "python"; +const PYTHON2: &str = "python2"; +const PYTHON3: &str = "python3"; + +fn python() -> &'static str { + let val = match env::var_os("PATH") { + Some(val) => val, + None => return PYTHON, + }; + + let mut python2 = false; + let mut python3 = false; + + for dir in env::split_paths(&val) { + if dir.join(PYTHON).exists() { + return PYTHON; + } + + python2 |= dir.join(PYTHON2).exists(); + python3 |= dir.join(PYTHON3).exists(); + } + + if python3 { + PYTHON3 + } else if python2 { + PYTHON2 + } else { + PYTHON + } +} + +#[cfg(unix)] +fn exec_or_status(command: &mut Command) -> io::Result { + use std::os::unix::process::CommandExt; + Err(command.exec()) +} + +#[cfg(not(unix))] +fn exec_or_status(command: &mut Command) -> io::Result { + command.status() +} + +fn main() { + let current = match env::current_dir() { + Ok(dir) => dir, + Err(err) => { + eprintln!("Failed to get current directory: {}", err); + process::exit(1); + } + }; + + for dir in current.ancestors() { + let candidate = dir.join("x.py"); + + if candidate.exists() { + let mut python = Command::new(python()); + + python.arg(&candidate).args(env::args().skip(1)).current_dir(dir); + + let result = exec_or_status(&mut python); + + match result { + Err(error) => { + eprintln!("Failed to invoke `{}`: {}", candidate.display(), error); + } + Ok(status) => { + process::exit(status.code().unwrap_or(1)); + } + } + } + } + + eprintln!( + "x.py not found. Please run inside of a checkout of `https://github.com/rust-lang/rust`." + ); + + process::exit(1); +} From 9a12d727df77d086c83167e5f68da2fdc7303f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 4 Nov 2020 11:41:57 +0100 Subject: [PATCH 15/22] Constantify `UnsafeCell::into_inner` and related Also includes: - Cell::into_inner - RefCell::into_inner - Atomic*::into_inner --- library/core/src/cell.rs | 11 ++++++----- library/core/src/lib.rs | 1 + library/core/src/sync/atomic.rs | 9 ++++++--- library/core/tests/cell.rs | 12 ++++++++++++ library/core/tests/lib.rs | 1 + 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 7140218fa9101..d753b2a02f7a2 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -406,7 +406,8 @@ impl Cell { /// assert_eq!(five, 5); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] - pub fn into_inner(self) -> T { + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + pub const fn into_inner(self) -> T { self.value.into_inner() } } @@ -668,12 +669,11 @@ impl RefCell { /// let five = c.into_inner(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] #[inline] - pub fn into_inner(self) -> T { + pub const fn into_inner(self) -> T { // Since this function takes `self` (the `RefCell`) by value, the // compiler statically verifies that it is not currently borrowed. - // Therefore the following assertion is just a `debug_assert!`. - debug_assert!(self.borrow.get() == UNUSED); self.value.into_inner() } @@ -1682,7 +1682,8 @@ impl UnsafeCell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_inner(self) -> T { + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + pub const fn into_inner(self) -> T { self.value } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index b89ec93834fcc..ee63f1ab1f657 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -70,6 +70,7 @@ #![feature(cfg_target_has_atomic)] #![feature(const_alloc_layout)] #![feature(const_discriminant)] +#![feature(const_cell_into_inner)] #![feature(const_checked_int_methods)] #![feature(const_euclidean_int_methods)] #![feature(const_float_classify)] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 2edeb81011af9..3283736c4feda 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -365,7 +365,8 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - pub fn into_inner(self) -> bool { + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + pub const fn into_inner(self) -> bool { self.v.into_inner() != 0 } @@ -941,7 +942,8 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - pub fn into_inner(self) -> *mut T { + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + pub const fn into_inner(self) -> *mut T { self.p.into_inner() } @@ -1462,7 +1464,8 @@ assert_eq!(some_var.into_inner(), 5); ```"), #[inline] #[$stable_access] - pub fn into_inner(self) -> $int_type { + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + pub const fn into_inner(self) -> $int_type { self.v.into_inner() } } diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs index 40be01f443931..77517879dd250 100644 --- a/library/core/tests/cell.rs +++ b/library/core/tests/cell.rs @@ -422,3 +422,15 @@ fn refcell_format() { let msg = format!("{name} {}", &*what.borrow(), name = &*name.borrow()); assert_eq!(msg, "rust rocks".to_string()); } + +#[allow(dead_code)] +fn const_cells() { + const UNSAFE_CELL: UnsafeCell = UnsafeCell::new(3); + const _: i32 = UNSAFE_CELL.into_inner(); + + const REF_CELL: RefCell = RefCell::new(3); + const _: i32 = REF_CELL.into_inner(); + + const CELL: Cell = Cell::new(3); + const _: i32 = CELL.into_inner(); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 0c4ce867f542d..31aa46305641a 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -9,6 +9,7 @@ #![feature(box_syntax)] #![feature(cell_update)] #![feature(const_assume)] +#![feature(const_cell_into_inner)] #![feature(core_intrinsics)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] From 795bbfe056de9acd0ada4a401b128f23dd368868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 4 Nov 2020 11:58:41 +0100 Subject: [PATCH 16/22] Add tracking issue --- library/core/src/cell.rs | 6 +++--- library/core/src/sync/atomic.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d753b2a02f7a2..d4096d60ca07a 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -406,7 +406,7 @@ impl Cell { /// assert_eq!(five, 5); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] - #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] pub const fn into_inner(self) -> T { self.value.into_inner() } @@ -669,7 +669,7 @@ impl RefCell { /// let five = c.into_inner(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] #[inline] pub const fn into_inner(self) -> T { // Since this function takes `self` (the `RefCell`) by value, the @@ -1682,7 +1682,7 @@ impl UnsafeCell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] pub const fn into_inner(self) -> T { self.value } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 3283736c4feda..dd6dfcfa7f6a9 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -365,7 +365,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] pub const fn into_inner(self) -> bool { self.v.into_inner() != 0 } @@ -942,7 +942,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] pub const fn into_inner(self) -> *mut T { self.p.into_inner() } @@ -1464,7 +1464,7 @@ assert_eq!(some_var.into_inner(), 5); ```"), #[inline] #[$stable_access] - #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "none")] + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] pub const fn into_inner(self) -> $int_type { self.v.into_inner() } From eed0cebea3d16d82f5517e17ab498b340001fe01 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 19 Oct 2020 14:20:14 -0400 Subject: [PATCH 17/22] Recognize `private_intra_doc_links` as a lint Previously, trying to allow this would give another error! ``` warning: unknown lint: `private_intra_doc_links` --> private.rs:1:10 | 1 | #![allow(private_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `broken_intra_doc_links` | = note: `#[warn(unknown_lints)]` on by default warning: public documentation for `DocMe` links to private item `DontDocMe` --> private.rs:2:11 | 2 | /// docs [DontDocMe] | ^^^^^^^^^ this item is private | = note: `#[warn(private_intra_doc_links)]` on by default = note: this link will resolve properly if you pass `--document-private-items` ``` --- compiler/rustc_lint_defs/src/builtin.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a1b7c13e4c0f0..7176a66cdc1bd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2790,6 +2790,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, IRREFUTABLE_LET_PATTERNS, BROKEN_INTRA_DOC_LINKS, + PRIVATE_INTRA_DOC_LINKS, INVALID_CODEBLOCK_ATTRIBUTES, MISSING_CRATE_LEVEL_DOCS, MISSING_DOC_CODE_EXAMPLES, From 47b21b84f3ed88cff31fccc78a57a66241a26496 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 5 Nov 2020 13:11:50 -0500 Subject: [PATCH 18/22] Add PRIVATE_INTRA_DOC_LINKS to rustdoc special-casing This is really starting to get out of hand. Rustdoc should instead allow all lints in the rustdoc lint group. --- src/librustdoc/core.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 45a84c4fb30d3..285a3bf8204bb 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -322,7 +322,8 @@ pub fn run_core( let cpath = Some(input.clone()); let input = Input::File(input); - let intra_link_resolution_failure_name = lint::builtin::BROKEN_INTRA_DOC_LINKS.name; + let broken_intra_doc_links = lint::builtin::BROKEN_INTRA_DOC_LINKS.name; + let private_intra_doc_links = lint::builtin::PRIVATE_INTRA_DOC_LINKS.name; let missing_docs = rustc_lint::builtin::MISSING_DOCS.name; let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name; let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name; @@ -335,7 +336,8 @@ pub fn run_core( // In addition to those specific lints, we also need to allow those given through // command line, otherwise they'll get ignored and we don't want that. let lints_to_show = vec![ - intra_link_resolution_failure_name.to_owned(), + broken_intra_doc_links.to_owned(), + private_intra_doc_links.to_owned(), missing_docs.to_owned(), missing_doc_example.to_owned(), private_doc_tests.to_owned(), @@ -347,9 +349,8 @@ pub fn run_core( ]; let (lint_opts, lint_caps) = init_lints(lints_to_show, lint_opts, |lint| { - if lint.name == intra_link_resolution_failure_name - || lint.name == invalid_codeblock_attributes_name - { + // FIXME: why is this necessary? + if lint.name == broken_intra_doc_links || lint.name == invalid_codeblock_attributes_name { None } else { Some((lint.name_lower(), lint::Allow)) From 3bee37c290fdd362fd4fd393606cc53acf1e7375 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Sat, 31 Oct 2020 14:20:18 +0100 Subject: [PATCH 19/22] Disable accept4 on Android. --- library/std/src/sys/unix/net.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 71c6aa5a0e7ea..378d690f8bfd7 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -195,7 +195,6 @@ impl Socket { // glibc 2.10 and musl 0.9.5. cfg_if::cfg_if! { if #[cfg(any( - target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "illumos", @@ -207,6 +206,13 @@ impl Socket { libc::accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC) })?; Ok(Socket(FileDesc::new(fd))) + // While the Android kernel supports the syscall, + // it is not included in all versions of Android's libc. + } else if #[cfg(target_os = "android")] { + let fd = cvt_r(|| unsafe { + libc::syscall(libc::SYS_accept4, self.0.raw(), storage, len, libc::SOCK_CLOEXEC) + })?; + Ok(Socket(FileDesc::new(fd as c_int))) } else { let fd = cvt_r(|| unsafe { libc::accept(self.0.raw(), storage, len) })?; let fd = FileDesc::new(fd); From e8b5be5dffef9ef6a15a085e4b06c4a0471f360d Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 30 Aug 2020 10:35:50 +0800 Subject: [PATCH 20/22] Stabilize hint::spin_loop Partially fix #55002, deprecate in another release Co-authored-by: Ashley Mannix Update stable version for stabilize_spin_loop Co-authored-by: Joshua Nelson Use better example for spinlock As suggested by KodrAus Remove renamed_spin_loop already available in master Fix spin loop example --- library/alloc/src/lib.rs | 1 - library/core/src/hint.rs | 62 ++++++++++++++++++++++++++++----- library/core/src/sync/atomic.rs | 16 ++------- library/std/src/lib.rs | 1 - 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 0fe15958076c5..ccabc336acc16 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -119,7 +119,6 @@ #![feature(raw_ref_op)] #![feature(rustc_attrs)] #![feature(receiver_trait)] -#![feature(renamed_spin_loop)] #![feature(min_specialization)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 454fb34e77e49..979a5f8cf5075 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -1,6 +1,7 @@ #![stable(feature = "core_hint", since = "1.27.0")] //! Hints to compiler that affects how code should be emitted or optimized. +//! Hints may be compile time or runtime. use crate::intrinsics; @@ -24,7 +25,6 @@ use crate::intrinsics; /// Otherwise, consider using the [`unreachable!`] macro, which does not allow /// optimizations but will panic when executed. /// -/// /// # Example /// /// ``` @@ -51,18 +51,62 @@ pub const unsafe fn unreachable_unchecked() -> ! { unsafe { intrinsics::unreachable() } } -/// Emits a machine instruction hinting to the processor that it is running in busy-wait -/// spin-loop ("spin lock"). +/// Emits a machine instruction to signal the processor that it is running in +/// a busy-wait spin-loop ("spin lock"). +/// +/// Upon receiving the spin-loop signal the processor can optimize its behavior by, +/// for example, saving power or switching hyper-threads. +/// +/// This function is different from [`thread::yield_now`] which directly +/// yields to the system's scheduler, whereas `spin_loop` does not interact +/// with the operating system. +/// +/// A common use case for `spin_loop` is implementing bounded optimistic +/// spinning in a CAS loop in synchronization primitives. To avoid problems +/// like priority inversion, it is strongly recommended that the spin loop is +/// terminated after a finite amount of iterations and an appropriate blocking +/// syscall is made. +/// +/// **Note**: On platforms that do not support receiving spin-loop hints this +/// function does not do anything at all. +/// +/// # Examples /// -/// For a discussion of different locking strategies and their trade-offs, see -/// [`core::sync::atomic::spin_loop_hint`]. +/// ``` +/// use std::sync::atomic::{AtomicBool, Ordering}; +/// use std::sync::Arc; +/// use std::{hint, thread}; +/// +/// // A shared atomic value that threads will use to coordinate +/// let live = Arc::new(AtomicBool::new(false)); +/// +/// // In a background thread we'll eventually set the value +/// let bg_work = { +/// let live = live.clone(); +/// thread::spawn(move || { +/// // Do some work, then make the value live +/// do_some_work(); +/// live.store(true, Ordering::Release); +/// }) +/// }; /// -/// **Note**: On platforms that do not support receiving spin-loop hints this function does not -/// do anything at all. +/// // Back on our current thread, we wait for the value to be set +/// while live.load(Ordering::Acquire) { +/// // The spin loop is a hint to the CPU that we're waiting, but probably +/// // not for very long +/// hint::spin_loop(); +/// } +/// +/// // The value is now set +/// # fn do_some_work() {} +/// do_some_work(); +/// bg_work.join()?; +/// # Ok::<(), Box>(()) +/// ``` /// -/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint +/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html #[inline] -#[unstable(feature = "renamed_spin_loop", issue = "55002")] +#[stable(feature = "renamed_spin_loop", since = "1.49.0")] pub fn spin_loop() { #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))] { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 5c9cfe27101f0..5dbea6e71aa4f 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -115,23 +115,13 @@ use crate::hint::spin_loop; /// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). /// -/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving -/// power or switching hyper-threads. -/// -/// This function is different from [`std::thread::yield_now`] which directly yields to the -/// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system. -/// -/// A common use case for `spin_loop_hint` is implementing bounded optimistic spinning in a CAS -/// loop in synchronization primitives. To avoid problems like priority inversion, it is strongly -/// recommended that the spin loop is terminated after a finite amount of iterations and an -/// appropriate blocking syscall is made. +/// This function is expected to be deprecated in favor of +/// [`hint::spin_loop`]. /// /// **Note**: On platforms that do not support receiving spin-loop hints this function does not /// do anything at all. /// -/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html -/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html -/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html +/// [`hint::spin_loop`]: crate::hint::spin_loop #[inline] #[stable(feature = "spin_loop_hint", since = "1.24.0")] pub fn spin_loop_hint() { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 96a7755c68821..1636fe5e2575a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -296,7 +296,6 @@ #![feature(raw)] #![feature(raw_ref_macros)] #![feature(ready_macro)] -#![feature(renamed_spin_loop)] #![feature(rustc_attrs)] #![feature(rustc_private)] #![feature(shrink_to)] From ae059b532fcc504b75388d043d56ce12fdb055a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 6 Nov 2020 17:46:56 +0100 Subject: [PATCH 21/22] Make some std::io functions `const` Includes: - io::Cursor::new - io::Cursor::get_ref - io::Cursor::position - io::empty - io::repeat - io::sink --- library/std/src/io/cursor.rs | 9 ++++++--- library/std/src/io/cursor/tests.rs | 7 +++++++ library/std/src/io/util.rs | 9 ++++++--- library/std/src/io/util/tests.rs | 9 ++++++++- library/std/src/lib.rs | 1 + 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 5733735dc4ab4..43f5da0a9bbfe 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -94,7 +94,8 @@ impl Cursor { /// # force_inference(&buff); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn new(inner: T) -> Cursor { + #[rustc_const_unstable(feature = "const_io_structs", issue = "none")] + pub const fn new(inner: T) -> Cursor { Cursor { pos: 0, inner } } @@ -130,7 +131,8 @@ impl Cursor { /// let reference = buff.get_ref(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn get_ref(&self) -> &T { + #[rustc_const_unstable(feature = "const_io_structs", issue = "none")] + pub const fn get_ref(&self) -> &T { &self.inner } @@ -175,7 +177,8 @@ impl Cursor { /// assert_eq!(buff.position(), 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn position(&self) -> u64 { + #[rustc_const_unstable(feature = "const_io_structs", issue = "none")] + pub const fn position(&self) -> u64 { self.pos } diff --git a/library/std/src/io/cursor/tests.rs b/library/std/src/io/cursor/tests.rs index 80d88ca66f669..5da31ce0ba761 100644 --- a/library/std/src/io/cursor/tests.rs +++ b/library/std/src/io/cursor/tests.rs @@ -514,3 +514,10 @@ fn test_eq() { let _: AssertEq>> = AssertEq(Cursor::new(Vec::new())); } + +#[allow(dead_code)] +fn const_cursor() { + const CURSOR: Cursor<&[u8]> = Cursor::new(&[0]); + const _: &&[u8] = CURSOR.get_ref(); + const _: u64 = CURSOR.position(); +} diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index dc05b9648fd6b..4aaf2070d3b34 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -102,7 +102,8 @@ pub struct Empty { /// assert!(buffer.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn empty() -> Empty { +#[rustc_const_unstable(feature = "const_io_structs", issue = "none")] +pub const fn empty() -> Empty { Empty { _priv: () } } @@ -159,7 +160,8 @@ pub struct Repeat { /// assert_eq!(buffer, [0b101, 0b101, 0b101]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn repeat(byte: u8) -> Repeat { +#[rustc_const_unstable(feature = "const_io_structs", issue = "none")] +pub const fn repeat(byte: u8) -> Repeat { Repeat { byte } } @@ -226,7 +228,8 @@ pub struct Sink { /// assert_eq!(num_bytes, 5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn sink() -> Sink { +#[rustc_const_unstable(feature = "const_io_structs", issue = "none")] +pub const fn sink() -> Sink { Sink { _priv: () } } diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index e5e32ecb40531..9450b1ee1240c 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,5 +1,5 @@ use crate::io::prelude::*; -use crate::io::{copy, empty, repeat, sink}; +use crate::io::{copy, empty, repeat, sink, Empty, Repeat, Sink}; #[test] fn copy_copies() { @@ -43,3 +43,10 @@ fn take_some_bytes() { assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); } + +#[allow(dead_code)] +fn const_utils() { + const _: Empty = empty(); + const _: Repeat = repeat(b'c'); + const _: Sink = sink(); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 96a7755c68821..060d6042df03c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -242,6 +242,7 @@ #![feature(const_fn_transmute)] #![feature(const_fn)] #![feature(const_fn_fn_ptr_basics)] +#![feature(const_io_structs)] #![feature(const_ip)] #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] From 001dd7e6a578e25ba4a82ed6291bb5989a484bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 6 Nov 2020 18:04:52 +0100 Subject: [PATCH 22/22] Add tracking issue --- library/std/src/io/cursor.rs | 6 +++--- library/std/src/io/util.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 43f5da0a9bbfe..bbee2cc98425e 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -94,7 +94,7 @@ impl Cursor { /// # force_inference(&buff); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_io_structs", issue = "none")] + #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn new(inner: T) -> Cursor { Cursor { pos: 0, inner } } @@ -131,7 +131,7 @@ impl Cursor { /// let reference = buff.get_ref(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_io_structs", issue = "none")] + #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn get_ref(&self) -> &T { &self.inner } @@ -177,7 +177,7 @@ impl Cursor { /// assert_eq!(buff.position(), 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_io_structs", issue = "none")] + #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn position(&self) -> u64 { self.pos } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 4aaf2070d3b34..2b1f371129eaf 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -102,7 +102,7 @@ pub struct Empty { /// assert!(buffer.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_io_structs", issue = "none")] +#[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn empty() -> Empty { Empty { _priv: () } } @@ -160,7 +160,7 @@ pub struct Repeat { /// assert_eq!(buffer, [0b101, 0b101, 0b101]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_io_structs", issue = "none")] +#[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn repeat(byte: u8) -> Repeat { Repeat { byte } } @@ -228,7 +228,7 @@ pub struct Sink { /// assert_eq!(num_bytes, 5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_io_structs", issue = "none")] +#[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn sink() -> Sink { Sink { _priv: () } }