about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_attr/src/builtin.rs12
-rw-r--r--compiler/rustc_lexer/src/tests.rs17
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs11
-rw-r--r--library/core/src/cmp.rs5
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs42
-rw-r--r--library/core/src/iter/adapters/mod.rs3
-rw-r--r--library/core/src/iter/mod.rs2
-rw-r--r--library/core/src/iter/traits/iterator.rs3
-rw-r--r--library/core/tests/cmp.rs13
-rw-r--r--library/core/tests/iter/traits/iterator.rs24
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs6
-rw-r--r--src/bootstrap/test.rs58
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile10
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version1
-rwxr-xr-xsrc/ci/scripts/should-skip-this.sh1
-rw-r--r--src/test/ui/cfg/cfg-path-error.rs19
-rw-r--r--src/test/ui/cfg/cfg-path-error.stderr26
17 files changed, 218 insertions, 35 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 613320087d2..8a134bf7f96 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -603,10 +603,18 @@ pub fn eval_condition(
             match cfg.name_or_empty() {
                 sym::any => mis
                     .iter()
-                    .any(|mi| eval_condition(mi.meta_item().unwrap(), sess, features, eval)),
+                    // We don't use any() here, because we want to evaluate all cfg condition
+                    // as eval_condition can (and does) extra checks
+                    .fold(false, |res, mi| {
+                        res | eval_condition(mi.meta_item().unwrap(), sess, features, eval)
+                    }),
                 sym::all => mis
                     .iter()
-                    .all(|mi| eval_condition(mi.meta_item().unwrap(), sess, features, eval)),
+                    // We don't use all() here, because we want to evaluate all cfg condition
+                    // as eval_condition can (and does) extra checks
+                    .fold(true, |res, mi| {
+                        res & eval_condition(mi.meta_item().unwrap(), sess, features, eval)
+                    }),
                 sym::not => {
                     if mis.len() != 1 {
                         struct_span_err!(
diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs
index 94017b7b286..548de67449a 100644
--- a/compiler/rustc_lexer/src/tests.rs
+++ b/compiler/rustc_lexer/src/tests.rs
@@ -67,6 +67,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
     let input = "#!/usr/bin/rustrun\nlet x = 5;";
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index ef006d5fcda..a907f50a11b 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,9 +1,10 @@
+use super::diagnostics::SnapshotParser;
 use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{
-    AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
+    AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
+    SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
 };
-use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
 use ast::token::DelimToken;
@@ -1105,7 +1106,7 @@ impl<'a> Parser<'a> {
         let snapshot = if self.token.kind == token::OpenDelim(token::Paren)
             && self.look_ahead_type_ascription_as_field()
         {
-            Some((self.clone(), fun.kind.clone()))
+            Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
         } else {
             None
         };
@@ -1130,7 +1131,7 @@ impl<'a> Parser<'a> {
         lo: Span,
         open_paren: Span,
         seq: &mut PResult<'a, P<Expr>>,
-        snapshot: Option<(Self, ExprKind)>,
+        snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
     ) -> Option<P<Expr>> {
         match (seq.as_mut(), snapshot) {
             (Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
@@ -1140,7 +1141,7 @@ impl<'a> Parser<'a> {
                     Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
                         // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
                         // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
-                        *self = snapshot;
+                        self.restore_snapshot(snapshot);
                         let close_paren = self.prev_token.span;
                         let span = lo.to(self.prev_token.span);
                         if !fields.is_empty() {
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index ddaeb9eca97..74328a3607d 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -333,7 +333,7 @@ pub struct AssertParamIsEq<T: Eq + ?Sized> {
 /// 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 {
@@ -862,9 +862,6 @@ pub macro Ord($item:item) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Eq for Ordering {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for Ordering {
     #[inline]
     fn cmp(&self, other: &Ordering) -> Ordering {
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 00000000000..0b5e2a89ef3
--- /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<I: Iterator> Iterator for ByRefSized<'_, I> {
+    type Item = I::Item;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        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::Item> {
+        self.0.nth(n)
+    }
+
+    fn fold<B, F>(self, init: B, f: F) -> B
+    where
+        F: FnMut(B, Self::Item) -> B,
+    {
+        self.0.fold(init, f)
+    }
+
+    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Output = B>,
+    {
+        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 2ae92e89d63..d82fde47520 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 5a987733134..145c5ee109d 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 d980f593081..b62e8dfe1d6 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 {
         <<Self as Iterator>::Item as Try>::Residual: Residual<B>,
         B: FromIterator<<Self::Item as Try>::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 2b234de6795..8d0e59d5a49 100644
--- a/library/core/tests/cmp.rs
+++ b/library/core/tests/cmp.rs
@@ -134,6 +134,19 @@ fn ordering_const() {
 }
 
 #[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 32bd68e3d25..731b1592d41 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>(I);
+    impl<I: Iterator> Iterator for PanicOnNext<I> {
+        type Item = I::Item;
+        fn next(&mut self) -> Option<Self::Item> {
+            panic!("Iterator::next should not be called!")
+        }
+        fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
+        where
+            Self: Sized,
+            F: FnMut(B, Self::Item) -> R,
+            R: std::ops::Try<Output = B>,
+        {
+            self.0.try_fold(init, f)
+        }
+    }
+
+    let it = (0..10).map(Some);
+    let _ = PanicOnNext(it).try_collect::<Vec<_>>();
+    // validation is just that it didn't panic.
+}
+
 // just tests by whether or not this compiles
 fn _empty_impl_all_auto_traits<T>() {
     use std::panic::{RefUnwindSafe, UnwindSafe};
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 9c477e5addc..9d2803b40c4 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -648,11 +648,11 @@ impl ExitStatus {
     }
 
     pub fn code(&self) -> Option<i32> {
-        if self.exited() { Some(libc::WEXITSTATUS(self.0)) } else { None }
+        self.exited().then(|| libc::WEXITSTATUS(self.0))
     }
 
     pub fn signal(&self) -> Option<i32> {
-        if libc::WIFSIGNALED(self.0) { Some(libc::WTERMSIG(self.0)) } else { None }
+        libc::WIFSIGNALED(self.0).then(|| libc::WTERMSIG(self.0))
     }
 
     pub fn core_dumped(&self) -> bool {
@@ -660,7 +660,7 @@ impl ExitStatus {
     }
 
     pub fn stopped_signal(&self) -> Option<i32> {
-        if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None }
+        libc::WIFSTOPPED(self.0).then(|| libc::WSTOPSIG(self.0))
     }
 
     pub fn continued(&self) -> bool {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 58b73ebed50..c8b76809aba 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<String> {
     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<String> {
+    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 d78fc6d2083..2358091a6df 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 00000000000..fab77af2a1a
--- /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 c046a6c8a26..c863f1b68c7 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/test/ui/cfg/cfg-path-error.rs b/src/test/ui/cfg/cfg-path-error.rs
new file mode 100644
index 00000000000..5bf80bd74b8
--- /dev/null
+++ b/src/test/ui/cfg/cfg-path-error.rs
@@ -0,0 +1,19 @@
+// check-fail
+
+#[cfg(any(foo, foo::bar))]
+//~^ERROR `cfg` predicate key must be an identifier
+fn foo1() {}
+
+#[cfg(any(foo::bar, foo))]
+//~^ERROR `cfg` predicate key must be an identifier
+fn foo2() {}
+
+#[cfg(all(foo, foo::bar))]
+//~^ERROR `cfg` predicate key must be an identifier
+fn foo3() {}
+
+#[cfg(all(foo::bar, foo))]
+//~^ERROR `cfg` predicate key must be an identifier
+fn foo4() {}
+
+fn main() {}
diff --git a/src/test/ui/cfg/cfg-path-error.stderr b/src/test/ui/cfg/cfg-path-error.stderr
new file mode 100644
index 00000000000..84b44b2b0c2
--- /dev/null
+++ b/src/test/ui/cfg/cfg-path-error.stderr
@@ -0,0 +1,26 @@
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-path-error.rs:3:16
+   |
+LL | #[cfg(any(foo, foo::bar))]
+   |                ^^^^^^^^
+
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-path-error.rs:7:11
+   |
+LL | #[cfg(any(foo::bar, foo))]
+   |           ^^^^^^^^
+
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-path-error.rs:11:16
+   |
+LL | #[cfg(all(foo, foo::bar))]
+   |                ^^^^^^^^
+
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-path-error.rs:15:11
+   |
+LL | #[cfg(all(foo::bar, foo))]
+   |           ^^^^^^^^
+
+error: aborting due to 4 previous errors
+