diff --git a/Cargo.lock b/Cargo.lock index dce5357b12d33..ca898d60fef8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1965,9 +1965,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.116" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" dependencies = [ "rustc-std-workspace-core", ] diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs index 94017b7b286e2..548de67449abf 100644 --- a/compiler/rustc_lexer/src/tests.rs +++ b/compiler/rustc_lexer/src/tests.rs @@ -66,6 +66,23 @@ fn test_unterminated_no_pound() { ); } +#[test] +fn test_too_many_hashes() { + let max_count = u16::MAX; + let mut hashes: String = "#".repeat(max_count.into()); + + // Valid number of hashes (65535 = 2^16 - 1), but invalid string. + check_raw_str(&hashes, max_count, Some(RawStrError::InvalidStarter { bad_char: '\u{0}' })); + + // One more hash sign (65536 = 2^16) becomes too many. + hashes.push('#'); + check_raw_str( + &hashes, + 0, + Some(RawStrError::TooManyDelimiters { found: usize::from(max_count) + 1 }), + ); +} + #[test] fn test_valid_shebang() { // https://github.com/rust-lang/rust/issues/70528 diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index ddaeb9eca975c..74328a3607d64 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -333,7 +333,7 @@ pub struct AssertParamIsEq { /// let result = 2.cmp(&1); /// assert_eq!(Ordering::Greater, result); /// ``` -#[derive(Clone, Copy, PartialEq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] #[stable(feature = "rust1", since = "1.0.0")] #[repr(i8)] pub enum Ordering { @@ -861,9 +861,6 @@ pub macro Ord($item:item) { /* compiler built-in */ } -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Ordering {} - #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ordering { #[inline] diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs new file mode 100644 index 0000000000000..0b5e2a89ef3de --- /dev/null +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -0,0 +1,42 @@ +use crate::ops::Try; + +/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. +/// +/// Ideally this will no longer be required, eventually, but as can be seen in +/// the benchmarks (as of Feb 2022 at least) `by_ref` can have performance cost. +pub(crate) struct ByRefSized<'a, I>(pub &'a mut I); + +impl Iterator for ByRefSized<'_, I> { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.0.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + self.0.advance_by(n) + } + + fn nth(&mut self, n: usize) -> Option { + self.0.nth(n) + } + + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.0.fold(init, f) + } + + fn try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.0.try_fold(init, f) + } +} diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 2ae92e89d63b5..d82fde4752020 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,6 +1,7 @@ use crate::iter::{InPlaceIterable, Iterator}; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try}; +mod by_ref_sized; mod chain; mod cloned; mod copied; @@ -31,6 +32,8 @@ pub use self::{ scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, take_while::TakeWhile, zip::Zip, }; +pub(crate) use self::by_ref_sized::ByRefSized; + #[stable(feature = "iter_cloned", since = "1.1.0")] pub use self::cloned::Cloned; diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 5a987733134a4..145c5ee109d7f 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -417,7 +417,7 @@ pub use self::adapters::{ #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub use self::adapters::{Intersperse, IntersperseWith}; -pub(crate) use self::adapters::try_process; +pub(crate) use self::adapters::{try_process, ByRefSized}; mod adapters; mod range; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index d980f5930810b..b62e8dfe1d610 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2,6 +2,7 @@ use crate::cmp::{self, Ordering}; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; use super::super::try_process; +use super::super::ByRefSized; use super::super::TrustedRandomAccessNoCoerce; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; use super::super::{FlatMap, Flatten}; @@ -1861,7 +1862,7 @@ pub trait Iterator { <::Item as Try>::Residual: Residual, B: FromIterator<::Output>, { - try_process(self, |i| i.collect()) + try_process(ByRefSized(self), |i| i.collect()) } /// Collects all the items from an iterator into a collection. diff --git a/library/core/tests/cmp.rs b/library/core/tests/cmp.rs index 2b234de6795eb..8d0e59d5a4972 100644 --- a/library/core/tests/cmp.rs +++ b/library/core/tests/cmp.rs @@ -133,6 +133,19 @@ fn ordering_const() { assert_eq!(THEN, Greater); } +#[test] +fn ordering_structural_eq() { + // test that consts of type `Ordering` are usable in patterns + + const ORDERING: Ordering = Greater; + + const REVERSE: Ordering = ORDERING.reverse(); + match Ordering::Less { + REVERSE => {} + _ => unreachable!(), + }; +} + #[test] fn cmp_default() { // Test default methods in PartialOrd and PartialEq diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 32bd68e3d2554..731b1592d4193 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -551,6 +551,30 @@ fn test_collect_into() { assert!(a == b); } +#[test] +fn iter_try_collect_uses_try_fold_not_next() { + // This makes sure it picks up optimizations, and doesn't use the `&mut I` impl. + struct PanicOnNext(I); + impl Iterator for PanicOnNext { + type Item = I::Item; + fn next(&mut self) -> Option { + panic!("Iterator::next should not be called!") + } + fn try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: std::ops::Try, + { + self.0.try_fold(init, f) + } + } + + let it = (0..10).map(Some); + let _ = PanicOnNext(it).try_collect::>(); + // validation is just that it didn't panic. +} + // just tests by whether or not this compiles fn _empty_impl_all_auto_traits() { use std::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index dd9b035e86df1..61caad29a37d9 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,7 +15,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.116", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.119", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.69" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 59ddd1aa92f81..9a8634aa33327 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -114,7 +114,7 @@ impl Hash for Timespec { } } -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios"))] mod inner { use crate::fmt; use crate::sync::atomic::{AtomicU64, Ordering}; @@ -263,7 +263,7 @@ mod inner { } } -#[cfg(not(any(target_os = "macos", target_os = "ios")))] +#[cfg(not(any(all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios")))] mod inner { use crate::fmt; use crate::sys::cvt; @@ -285,7 +285,11 @@ mod inner { impl Instant { pub fn now() -> Instant { - Instant { t: now(libc::CLOCK_MONOTONIC) } + #[cfg(target_os = "macos")] + const clock_id: clock_t = libc::CLOCK_UPTIME_RAW; + #[cfg(not(target_os = "macos"))] + const clock_id: clock_t = libc::CLOCK_MONOTONIC; + Instant { t: now(clock_id) } } pub fn checked_sub_instant(&self, other: &Instant) -> Option { @@ -343,10 +347,12 @@ mod inner { } } - #[cfg(not(any(target_os = "dragonfly", target_os = "espidf")))] + #[cfg(not(any(target_os = "dragonfly", target_os = "espidf", target_os = "macos")))] pub type clock_t = libc::c_int; #[cfg(any(target_os = "dragonfly", target_os = "espidf"))] pub type clock_t = libc::c_ulong; + #[cfg(target_os = "macos")] + pub type clock_t = libc::clockid_t; fn now(clock: clock_t) -> Timespec { let mut t = Timespec { t: libc::timespec { tv_sec: 0, tv_nsec: 0 } }; diff --git a/library/std/src/time/tests.rs b/library/std/src/time/tests.rs index d710a574465ce..dda19410e404f 100644 --- a/library/std/src/time/tests.rs +++ b/library/std/src/time/tests.rs @@ -12,6 +12,14 @@ macro_rules! assert_almost_eq { }}; } +#[test] +fn macos_resolution_regression() { + let t0 = Instant::now(); + let t1 = t0 + Duration::from_nanos(50); + let d = t1 - t0; + assert_eq!(t0 + d, t1); +} + #[test] fn instant_monotonic() { let a = Instant::now(); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 58b73ebed5000..c8b76809abad7 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -836,9 +836,9 @@ impl Step for RustdocJSNotStd { } } -fn check_if_browser_ui_test_is_installed_global(npm: &Path, global: bool) -> bool { +fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option { let mut command = Command::new(&npm); - command.arg("list").arg("--depth=0"); + command.arg("list").arg("--parseable").arg("--long").arg("--depth=0"); if global { command.arg("--global"); } @@ -846,12 +846,29 @@ fn check_if_browser_ui_test_is_installed_global(npm: &Path, global: bool) -> boo .output() .map(|output| String::from_utf8_lossy(&output.stdout).into_owned()) .unwrap_or(String::new()); - lines.contains(&" browser-ui-test@") + lines.lines().find_map(|l| l.split(":browser-ui-test@").skip(1).next()).map(|v| v.to_owned()) } -fn check_if_browser_ui_test_is_installed(npm: &Path) -> bool { - check_if_browser_ui_test_is_installed_global(npm, false) - || check_if_browser_ui_test_is_installed_global(npm, true) +fn get_browser_ui_test_version(npm: &Path) -> Option { + get_browser_ui_test_version_inner(npm, false) + .or_else(|| get_browser_ui_test_version_inner(npm, true)) +} + +fn compare_browser_ui_test_version(installed_version: &str, src: &Path) { + match fs::read_to_string( + src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"), + ) { + Ok(v) => { + if v.trim() != installed_version { + eprintln!( + "⚠️ Installed version of browser-ui-test (`{}`) is different than the \ + one used in the CI (`{}`)", + installed_version, v + ); + } + } + Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e), + } } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] @@ -874,7 +891,7 @@ impl Step for RustdocGUI { .config .npm .as_ref() - .map(|p| check_if_browser_ui_test_is_installed(p)) + .map(|p| get_browser_ui_test_version(p).is_some()) .unwrap_or(false) })) } @@ -892,16 +909,23 @@ impl Step for RustdocGUI { // The goal here is to check if the necessary packages are installed, and if not, we // panic. - if !check_if_browser_ui_test_is_installed(&npm) { - eprintln!( - "error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \ - dependency is missing", - ); - eprintln!( - "If you want to install the `{0}` dependency, run `npm install {0}`", - "browser-ui-test", - ); - panic!("Cannot run rustdoc-gui tests"); + match get_browser_ui_test_version(&npm) { + Some(version) => { + // We also check the version currently used in CI and emit a warning if it's not the + // same one. + compare_browser_ui_test_version(&version, &builder.build.src); + } + None => { + eprintln!( + "error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \ + dependency is missing", + ); + eprintln!( + "If you want to install the `{0}` dependency, run `npm install {0}`", + "browser-ui-test", + ); + panic!("Cannot run rustdoc-gui tests"); + } } let out_dir = builder.test_out(self.target).join("rustdoc-gui"); diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index d78fc6d208330..2358091a6dfbf 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -65,14 +65,20 @@ RUN /scripts/cmake.sh COPY host-x86_64/x86_64-gnu-tools/checktools.sh /tmp/ RUN curl -sL https://nodejs.org/dist/v14.4.0/node-v14.4.0-linux-x64.tar.xz | tar -xJ -ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" +ENV NODE_FOLDER=/node-v14.4.0-linux-x64/bin +ENV PATH="$NODE_FOLDER:${PATH}" + +COPY host-x86_64/x86_64-gnu-tools/browser-ui-test.version /tmp/ # For now, we need to use `--unsafe-perm=true` to go around an issue when npm tries # to create a new folder. For reference: # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.8.3 --unsafe-perm=true +# +# The `browser-ui-test.version` file is also used by bootstrap to emit warnings in case +# the local version of the package is different than the one used by the CI. +RUN npm install -g browser-ui-test@$(head -n 1 /tmp/browser-ui-test.version) --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version new file mode 100644 index 0000000000000..fab77af2a1a73 --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -0,0 +1 @@ +0.8.3 \ No newline at end of file diff --git a/src/ci/scripts/should-skip-this.sh b/src/ci/scripts/should-skip-this.sh index c046a6c8a26f3..c863f1b68c7fc 100755 --- a/src/ci/scripts/should-skip-this.sh +++ b/src/ci/scripts/should-skip-this.sh @@ -26,6 +26,7 @@ if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then src/test/rustdoc-gui \ src/librustdoc \ src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile \ + src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version \ src/tools/rustdoc-gui); then # There was a change in either rustdoc or in its GUI tests. echo "Rustdoc was updated" diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 3f2cd3ae232ba..503b624114a2a 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -487,11 +487,6 @@ fn configure_lldb(config: &Config) -> Option { return None; } - // Some older versions of LLDB seem to have problems with multiple - // instances running in parallel, so only run one test thread at a - // time. - env::set_var("RUST_TEST_THREADS", "1"); - Some(Config { debugger: Some(Debugger::Lldb), ..config.clone() }) }