about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--RELEASES.md8
-rw-r--r--compiler/rustc_ast/src/node_id.rs4
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/cargo.sh4
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/config.sh1
-rwxr-xr-xcompiler/rustc_codegen_cranelift/test.sh4
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/expand.rs6
-rw-r--r--compiler/rustc_mir/src/transform/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs18
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/_match.rs120
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs7
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs2
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs1
-rw-r--r--library/alloc/src/collections/btree/mod.rs1
-rw-r--r--library/alloc/src/collections/btree/set/tests.rs1
-rw-r--r--library/core/src/num/int_macros.rs4
-rw-r--r--library/core/src/num/uint_macros.rs4
-rw-r--r--library/std/src/io/buffered/bufreader.rs3
-rw-r--r--library/std/src/io/buffered/bufwriter.rs5
-rw-r--r--library/std/src/sys/hermit/mod.rs2
-rw-r--r--src/bootstrap/setup.rs15
-rw-r--r--src/bootstrap/test.rs1
-rwxr-xr-xsrc/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/build-toolchain.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh2
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh3
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh3
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh2
-rw-r--r--src/ci/docker/host-x86_64/dist-riscv64-linux/crosstool-ng.sh1
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-1/build-rumprun.sh2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh1
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh1
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/shared.sh1
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh3
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh2
-rw-r--r--src/ci/docker/scripts/android-base-apt-get.sh1
-rw-r--r--src/ci/docker/scripts/android-ndk.sh1
-rwxr-xr-xsrc/ci/docker/scripts/android-sdk.sh1
-rw-r--r--src/ci/docker/scripts/cross-apt-packages.sh1
-rw-r--r--src/ci/docker/scripts/crosstool-ng-1.24.sh1
-rw-r--r--src/ci/docker/scripts/crosstool-ng.sh1
-rw-r--r--src/ci/docker/scripts/emscripten.sh3
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh2
-rw-r--r--src/ci/docker/scripts/make3.sh1
-rw-r--r--src/ci/docker/scripts/musl-toolchain.sh3
-rw-r--r--src/ci/docker/scripts/musl.sh5
-rw-r--r--src/ci/docker/scripts/rustbuild-setup.sh1
-rw-r--r--src/ci/docker/scripts/sccache.sh1
-rwxr-xr-xsrc/ci/init_repo.sh1
-rw-r--r--src/ci/shared.sh1
-rw-r--r--src/doc/index.md3
-rw-r--r--src/test/run-make/thumb-none-qemu/script.sh1
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh1
-rw-r--r--src/test/ui/error-codes/E0027.stderr4
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs11
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr12
-rw-r--r--src/test/ui/structs/struct-field-cfg.stderr2
-rw-r--r--src/test/ui/structs/struct-pat-derived-error.stderr2
-rw-r--r--src/tools/compiletest/src/common.rs4
-rw-r--r--src/tools/compiletest/src/header/tests.rs1
-rw-r--r--src/tools/compiletest/src/main.rs32
66 files changed, 251 insertions, 95 deletions
diff --git a/RELEASES.md b/RELEASES.md
index ce11a74b71f..c9ff4928763 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -297,6 +297,7 @@ Compiler
 - [Added the `tiny` value to the `code-model` codegen flag.][72397]
 - [Added tier 3 support\* for the `mipsel-sony-psp` target.][72062]
 - [Added tier 3 support for the `thumbv7a-uwp-windows-msvc` target.][72133]
+- [Upgraded to LLVM 10.][67759]
 
 \* Refer to Rust's [platform support page][forge-platform-support] for more
 information on Rust's tiered platform support.
@@ -396,6 +397,7 @@ Internals Only
 [72062]: https://github.com/rust-lang/rust/pull/72062/
 [72094]: https://github.com/rust-lang/rust/pull/72094/
 [72133]: https://github.com/rust-lang/rust/pull/72133/
+[67759]: https://github.com/rust-lang/rust/pull/67759/
 [71900]: https://github.com/rust-lang/rust/pull/71900/
 [71928]: https://github.com/rust-lang/rust/pull/71928/
 [71662]: https://github.com/rust-lang/rust/pull/71662/
@@ -1270,6 +1272,7 @@ Compiler
   `armv7-unknown-linux-musleabi` targets.][63107]
 - [Added tier 3 support for the `hexagon-unknown-linux-musl` target.][62814]
 - [Added tier 3 support for the `riscv32i-unknown-none-elf` target.][62784]
+- [Upgraded to LLVM 9.][62592]
 
 \* Refer to Rust's [platform support page][forge-platform-support] for more
 information on Rust's tiered platform support.
@@ -1336,6 +1339,7 @@ Compatibility Notes
 [62735]: https://github.com/rust-lang/rust/pull/62735/
 [62766]: https://github.com/rust-lang/rust/pull/62766/
 [62784]: https://github.com/rust-lang/rust/pull/62784/
+[62592]: https://github.com/rust-lang/rust/pull/62592/
 [62785]: https://github.com/rust-lang/rust/issues/62785/
 [62814]: https://github.com/rust-lang/rust/pull/62814/
 [62896]: https://github.com/rust-lang/rust/issues/62896/
@@ -2431,6 +2435,7 @@ Compiler
 --------
 - [Added the `riscv32imc-unknown-none-elf` target.][53822]
 - [Added the `aarch64-unknown-netbsd` target][53165]
+- [Upgraded to LLVM 8.][53611]
 
 Libraries
 ---------
@@ -2479,6 +2484,7 @@ Misc
 [53033]: https://github.com/rust-lang/rust/pull/53033/
 [53044]: https://github.com/rust-lang/rust/pull/53044/
 [53165]: https://github.com/rust-lang/rust/pull/53165/
+[53611]: https://github.com/rust-lang/rust/pull/53611/
 [53213]: https://github.com/rust-lang/rust/pull/53213/
 [53236]: https://github.com/rust-lang/rust/pull/53236/
 [53272]: https://github.com/rust-lang/rust/pull/53272/
@@ -2537,6 +2543,7 @@ Compiler
 - [Bumped minimum LLVM version to 5.0.][51899]
 - [Added `powerpc64le-unknown-linux-musl` target.][51619]
 - [Added `aarch64-unknown-hermit` and `x86_64-unknown-hermit` targets.][52861]
+- [Upgraded to LLVM 7.][51966]
 
 Libraries
 ---------
@@ -2588,6 +2595,7 @@ Compatibility Notes
 
 [53893]: https://github.com/rust-lang/rust/pull/53893/
 [52861]: https://github.com/rust-lang/rust/pull/52861/
+[51966]: https://github.com/rust-lang/rust/pull/51966/
 [52656]: https://github.com/rust-lang/rust/pull/52656/
 [52239]: https://github.com/rust-lang/rust/pull/52239/
 [52330]: https://github.com/rust-lang/rust/pull/52330/
diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs
index 1035e945538..6e7d2bab287 100644
--- a/compiler/rustc_ast/src/node_id.rs
+++ b/compiler/rustc_ast/src/node_id.rs
@@ -13,8 +13,8 @@ rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId);
 pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
 
 /// When parsing and doing expansions, we initially give all AST nodes this AST
-/// node value. Then later, in the renumber pass, we renumber them to have
-/// small, positive ids.
+/// node value. Then later, during expansion, we renumber them to have small,
+/// positive ids.
 pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
 
 impl NodeId {
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.sh b/compiler/rustc_codegen_cranelift/scripts/cargo.sh
index e63daa40f35..947b4a28798 100755
--- a/compiler/rustc_codegen_cranelift/scripts/cargo.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/cargo.sh
@@ -10,7 +10,7 @@ cmd=$1
 shift || true
 
 if [[ "$cmd" = "jit" ]]; then
-cargo +${TOOLCHAIN} rustc $@ -- --jit
+cargo +${TOOLCHAIN} rustc "$@" -- --jit
 else
-cargo +${TOOLCHAIN} $cmd $@
+cargo +${TOOLCHAIN} $cmd "$@"
 fi
diff --git a/compiler/rustc_codegen_cranelift/scripts/config.sh b/compiler/rustc_codegen_cranelift/scripts/config.sh
index af181f4f724..6120a550a27 100644
--- a/compiler/rustc_codegen_cranelift/scripts/config.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/config.sh
@@ -1,3 +1,4 @@
+#!/usr/bin/env bash
 set -e
 
 unamestr=`uname`
diff --git a/compiler/rustc_codegen_cranelift/test.sh b/compiler/rustc_codegen_cranelift/test.sh
index 3cdd4119d79..c6c4956e481 100755
--- a/compiler/rustc_codegen_cranelift/test.sh
+++ b/compiler/rustc_codegen_cranelift/test.sh
@@ -3,13 +3,13 @@ set -e
 
 export RUSTFLAGS="-Zrun_dsymutil=no"
 
-./build.sh --without-sysroot $@
+./build.sh --without-sysroot "$@"
 
 rm -r target/out || true
 
 scripts/tests.sh no_sysroot
 
-./build.sh $@
+./build.sh "$@"
 
 scripts/tests.sh base_sysroot
 scripts/tests.sh extended_sysroot
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 4353a294cc3..e4a70253144 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -1,3 +1,4 @@
+#![deny(invalid_codeblock_attributes)]
 //! This library is used to gather all error codes into one place,
 //! the goal being to make their maintenance easier.
 
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 3e5762ab992..f6959591b56 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1436,9 +1436,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 item.attrs = attrs;
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
-                    ItemKind::MacCall(mac) => self
-                        .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span })
-                        .make_items(),
+                    ItemKind::MacCall(mac) => {
+                        self.collect_bang(mac, span, AstFragmentKind::Items).make_items()
+                    }
                     _ => unreachable!(),
                 })
             }
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index 3d68b862df2..acec3e8f82f 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -693,7 +693,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 // should only issue a warning for the sake of backwards compatibility.
                 //
                 // The solution those 2 expectations is to always take the minimum of both lints.
-                // This prevent any new errors (unless both lints are explicitely set to `deny`).
+                // This prevent any new errors (unless both lints are explicitly set to `deny`).
                 let lint = if tcx.lint_level_at_node(SAFE_PACKED_BORROWS, lint_root).0
                     <= tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, lint_root).0
                 {
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 5407226e386..4de93739992 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -140,14 +140,6 @@ impl Inliner<'tcx> {
                 continue;
             };
 
-            // Copy only unevaluated constants from the callee_body into the caller_body.
-            // Although we are only pushing `ConstKind::Unevaluated` consts to
-            // `required_consts`, here we may not only have `ConstKind::Unevaluated`
-            // because we are calling `subst_and_normalize_erasing_regions`.
-            caller_body.required_consts.extend(callee_body.required_consts.iter().copied().filter(
-                |&constant| matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _)),
-            ));
-
             let start = caller_body.basic_blocks().len();
             debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body);
             if !self.inline_call(callsite, caller_body, callee_body) {
@@ -522,6 +514,16 @@ impl Inliner<'tcx> {
                     kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) },
                 });
 
+                // Copy only unevaluated constants from the callee_body into the caller_body.
+                // Although we are only pushing `ConstKind::Unevaluated` consts to
+                // `required_consts`, here we may not only have `ConstKind::Unevaluated`
+                // because we are calling `subst_and_normalize_erasing_regions`.
+                caller_body.required_consts.extend(
+                    callee_body.required_consts.iter().copied().filter(|&constant| {
+                        matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _))
+                    }),
+                );
+
                 true
             }
             kind => {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/_match.rs b/compiler/rustc_mir_build/src/thir/pattern/_match.rs
index bc85d45d867..5e7e81eba62 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/_match.rs
@@ -1,5 +1,11 @@
-//! Note: most of the tests relevant to this file can be found (at the time of writing) in
-//! src/tests/ui/pattern/usefulness.
+//! Note: tests specific to this file can be found in:
+//!     - ui/pattern/usefulness
+//!     - ui/or-patterns
+//!     - ui/consts/const_in_pattern
+//!     - ui/rfc-2008-non-exhaustive
+//!     - probably many others
+//! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific
+//! reason not to, for example if they depend on a particular feature like or_patterns.
 //!
 //! This file includes the logic for exhaustiveness and usefulness checking for
 //! pattern-matching. Specifically, given a list of patterns for a type, we can
@@ -1361,8 +1367,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
 
 #[derive(Clone, Debug)]
 crate enum Usefulness<'tcx> {
-    /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
-    Useful(Vec<Span>),
+    /// Carries, for each column in the matrix, a set of sub-branches that have been found to be
+    /// unreachable. Used only in the presence of or-patterns, otherwise it stays empty.
+    Useful(Vec<FxHashSet<Span>>),
     /// Carries a list of witnesses of non-exhaustiveness.
     UsefulWithWitness(Vec<Witness<'tcx>>),
     NotUseful,
@@ -1410,6 +1417,23 @@ impl<'tcx> Usefulness<'tcx> {
                 };
                 UsefulWithWitness(new_witnesses)
             }
+            Useful(mut unreachables) => {
+                if !unreachables.is_empty() {
+                    // When we apply a constructor, there are `arity` columns of the matrix that
+                    // corresponded to its arguments. All the unreachables found in these columns
+                    // will, after `apply`, come from the first column. So we take the union of all
+                    // the corresponding sets and put them in the first column.
+                    // Note that `arity` may be 0, in which case we just push a new empty set.
+                    let len = unreachables.len();
+                    let arity = ctor_wild_subpatterns.len();
+                    let mut unioned = FxHashSet::default();
+                    for set in unreachables.drain((len - arity)..) {
+                        unioned.extend(set)
+                    }
+                    unreachables.push(unioned);
+                }
+                Useful(unreachables)
+            }
             x => x,
         }
     }
@@ -2091,13 +2115,14 @@ crate fn is_useful<'p, 'tcx>(
 
     // If the first pattern is an or-pattern, expand it.
     if let Some(vs) = v.expand_or_pat() {
-        // We need to push the already-seen patterns into the matrix in order to detect redundant
-        // branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns.
-        let mut matrix = matrix.clone();
-        // `Vec` of all the unreachable branches of the current or-pattern.
-        let mut unreachable_branches = Vec::new();
-        // Subpatterns that are unreachable from all branches. E.g. in the following case, the last
-        // `true` is unreachable only from one branch, so it is overall reachable.
+        // We expand the or pattern, trying each of its branches in turn and keeping careful track
+        // of possible unreachable sub-branches.
+        //
+        // If two branches have detected some unreachable sub-branches, we need to be careful. If
+        // they were detected in columns that are not the current one, we want to keep only the
+        // sub-branches that were unreachable in _all_ branches. Eg. in the following, the last
+        // `true` is unreachable in the second branch of the first or-pattern, but not otherwise.
+        // Therefore we don't want to lint that it is unreachable.
         //
         // ```
         // match (true, true) {
@@ -2105,41 +2130,72 @@ crate fn is_useful<'p, 'tcx>(
         //     (false | true, false | true) => {}
         // }
         // ```
-        let mut unreachable_subpats = FxHashSet::default();
-        // Whether any branch at all is useful.
+        // If however the sub-branches come from the current column, they come from the inside of
+        // the current or-pattern, and we want to keep them all. Eg. in the following, we _do_ want
+        // to lint that the last `false` is unreachable.
+        // ```
+        // match None {
+        //     Some(false) => {}
+        //     None | Some(true | false) => {}
+        // }
+        // ```
+
+        let mut matrix = matrix.clone();
+        // We keep track of sub-branches separately depending on whether they come from this column
+        // or from others.
+        let mut unreachables_this_column: FxHashSet<Span> = FxHashSet::default();
+        let mut unreachables_other_columns: Vec<FxHashSet<Span>> = Vec::default();
+        // Whether at least one branch is reachable.
         let mut any_is_useful = false;
 
         for v in vs {
             let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
             match res {
-                Useful(pats) => {
-                    if !any_is_useful {
-                        any_is_useful = true;
-                        // Initialize with the first set of unreachable subpatterns encountered.
-                        unreachable_subpats = pats.into_iter().collect();
-                    } else {
-                        // Keep the patterns unreachable from both this and previous branches.
-                        unreachable_subpats =
-                            pats.into_iter().filter(|p| unreachable_subpats.contains(p)).collect();
+                Useful(unreachables) => {
+                    if let Some((this_column, other_columns)) = unreachables.split_last() {
+                        // We keep the union of unreachables found in the first column.
+                        unreachables_this_column.extend(this_column);
+                        // We keep the intersection of unreachables found in other columns.
+                        if unreachables_other_columns.is_empty() {
+                            unreachables_other_columns = other_columns.to_vec();
+                        } else {
+                            unreachables_other_columns = unreachables_other_columns
+                                .into_iter()
+                                .zip(other_columns)
+                                .map(|(x, y)| x.intersection(&y).copied().collect())
+                                .collect();
+                        }
                     }
+                    any_is_useful = true;
                 }
-                NotUseful => unreachable_branches.push(v.head().span),
-                UsefulWithWitness(_) => {
-                    bug!("Encountered or-pat in `v` during exhaustiveness checking")
+                NotUseful => {
+                    unreachables_this_column.insert(v.head().span);
                 }
+                UsefulWithWitness(_) => bug!(
+                    "encountered or-pat in the expansion of `_` during exhaustiveness checking"
+                ),
             }
-            // If pattern has a guard don't add it to the matrix
+
+            // If pattern has a guard don't add it to the matrix.
             if !is_under_guard {
+                // We push the already-seen patterns into the matrix in order to detect redundant
+                // branches like `Some(_) | Some(0)`.
                 matrix.push(v);
             }
         }
-        if any_is_useful {
-            // Collect all the unreachable patterns.
-            unreachable_branches.extend(unreachable_subpats);
-            return Useful(unreachable_branches);
+
+        return if any_is_useful {
+            let mut unreachables = if unreachables_other_columns.is_empty() {
+                let n_columns = v.len();
+                (0..n_columns - 1).map(|_| FxHashSet::default()).collect()
+            } else {
+                unreachables_other_columns
+            };
+            unreachables.push(unreachables_this_column);
+            Useful(unreachables)
         } else {
-            return NotUseful;
-        }
+            NotUseful
+        };
     }
 
     // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 30b700a1d4f..205ad850c0c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -389,8 +389,11 @@ fn check_arms<'p, 'tcx>(
                     hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {}
                 }
             }
-            Useful(unreachable_subpatterns) => {
-                for span in unreachable_subpatterns {
+            Useful(unreachables) => {
+                let mut unreachables: Vec<_> = unreachables.into_iter().flatten().collect();
+                // Emit lints in the order in which they occur in the file.
+                unreachables.sort_unstable();
+                for span in unreachables {
                     unreachable_pattern(cx.tcx, span, id, None);
                 }
             }
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 53bc2069b76..f76f42dea1e 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -1500,7 +1500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.span_suggestion(
             sp,
             &format!(
-                "if you don't care about {} missing field{}, you can explicitely ignore {}",
+                "if you don't care about {} missing field{}, you can explicitly ignore {}",
                 if len == 1 { "this" } else { "these" },
                 if len == 1 { "" } else { "s" },
                 if len == 1 { "it" } else { "them" },
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 09aabdcd0fb..d5b1c600d93 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1668,6 +1668,7 @@ create_append_test!(test_append_239, 239);
 create_append_test!(test_append_1700, 1700);
 
 fn rand_data(len: usize) -> Vec<(u32, u32)> {
+    assert!(len * 2 <= 70029); // from that point on numbers repeat
     let mut rng = DeterministicRng::new();
     Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
 }
diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs
index 4c07795bd70..7bf1706dd6d 100644
--- a/library/alloc/src/collections/btree/mod.rs
+++ b/library/alloc/src/collections/btree/mod.rs
@@ -49,6 +49,7 @@ impl DeterministicRng {
         DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
     }
 
+    /// Guarantees that the first 70029 results are unique.
     fn next(&mut self) -> u32 {
         let x = self.x;
         let t = x ^ (x << 11);
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index 2069cde4dba..52cde8299e4 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -687,6 +687,7 @@ fn test_first_last() {
 }
 
 fn rand_data(len: usize) -> Vec<u32> {
+    assert!(len <= 70029); // from that point on numbers repeat
     let mut rng = DeterministicRng::new();
     Vec::from_iter((0..len).map(|_| rng.next()))
 }
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 295a876773c..728381b658f 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -274,7 +274,8 @@ assert_eq!(m, ", $swapped, ");
         }
 
         doc_comment! {
-            concat!("Reverses the bit pattern of the integer.
+            concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
+                second least-significant bit becomes second most-significant bit, etc.
 
 # Examples
 
@@ -285,6 +286,7 @@ let n = ", $swap_op, stringify!($SelfT), ";
 let m = n.reverse_bits();
 
 assert_eq!(m, ", $reversed, ");
+assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());
 ```"),
             #[stable(feature = "reverse_bits", since = "1.37.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index bdea0ea3b08..adcbbf91433 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -272,7 +272,8 @@ assert_eq!(m, ", $swapped, ");
         }
 
         doc_comment! {
-            concat!("Reverses the bit pattern of the integer.
+            concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
+                second least-significant bit becomes second most-significant bit, etc.
 
 # Examples
 
@@ -283,6 +284,7 @@ let n = ", $swap_op, stringify!($SelfT), ";
 let m = n.reverse_bits();
 
 assert_eq!(m, ", $reversed, ");
+assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());
 ```"),
             #[stable(feature = "reverse_bits", since = "1.37.0")]
             #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index 8fe29f08a7b..16c18d6e146 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -21,7 +21,8 @@ use crate::io::{self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, DE
 /// unwrapping the `BufReader<R>` with [`BufReader::into_inner`] can also cause
 /// data loss.
 ///
-/// [`TcpStream::read`]: Read::read
+// HACK(#78696): can't use `crate` for associated items
+/// [`TcpStream::read`]: super::super::super::net::TcpStream::read
 /// [`TcpStream`]: crate::net::TcpStream
 ///
 /// # Examples
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 3ec272fea66..067ed6ba7ff 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -59,9 +59,10 @@ use crate::io::{
 /// together by the buffer and will all be written out in one system call when
 /// the `stream` is flushed.
 ///
-/// [`TcpStream::write`]: Write::write
+// HACK(#78696): can't use `crate` for associated items
+/// [`TcpStream::write`]: super::super::super::net::TcpStream::write
 /// [`TcpStream`]: crate::net::TcpStream
-/// [`flush`]: Write::flush
+/// [`flush`]: BufWriter::flush
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufWriter<W: Write> {
     inner: Option<W>,
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index af05310a8d3..f185635b7a0 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -13,6 +13,8 @@
 //! compiling for wasm. That way it's a compile time error for something that's
 //! guaranteed to be a runtime error!
 
+#![allow(unsafe_op_in_unsafe_fn)]
+
 use crate::intrinsics;
 use crate::os::raw::c_char;
 
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index f5ce45a5bd1..55d2445fc49 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -127,14 +127,17 @@ pub fn setup(src_path: &Path, profile: Profile) {
 
 // Used to get the path for `Subcommand::Setup`
 pub fn interactive_path() -> io::Result<Profile> {
-    fn abbrev_all() -> impl Iterator<Item = (String, Profile)> {
-        ('a'..).map(|c| c.to_string()).zip(Profile::all())
+    fn abbrev_all() -> impl Iterator<Item = ((String, String), Profile)> {
+        ('a'..)
+            .zip(1..)
+            .map(|(letter, number)| (letter.to_string(), number.to_string()))
+            .zip(Profile::all())
     }
 
     fn parse_with_abbrev(input: &str) -> Result<Profile, String> {
         let input = input.trim().to_lowercase();
-        for (letter, profile) in abbrev_all() {
-            if input == letter {
+        for ((letter, number), profile) in abbrev_all() {
+            if input == letter || input == number {
                 return Ok(profile);
             }
         }
@@ -142,13 +145,13 @@ pub fn interactive_path() -> io::Result<Profile> {
     }
 
     println!("Welcome to the Rust project! What do you want to do with x.py?");
-    for (letter, profile) in abbrev_all() {
+    for ((letter, _), profile) in abbrev_all() {
         println!("{}) {}: {}", letter, profile, profile.purpose());
     }
     let template = loop {
         print!(
             "Please choose one ({}): ",
-            abbrev_all().map(|(l, _)| l).collect::<Vec<_>>().join("/")
+            abbrev_all().map(|((l, _), _)| l).collect::<Vec<_>>().join("/")
         );
         io::stdout().flush()?;
         let mut input = String::new();
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 5a73f583045..b48e9696c9a 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1040,6 +1040,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite));
         cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
         cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
+        cmd.arg("--suite").arg(suite);
         cmd.arg("--mode").arg(mode);
         cmd.arg("--target").arg(target.rustc_target_arg());
         cmd.arg("--host").arg(&*compiler.host.triple);
diff --git a/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh b/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh
index 112d747fe4e..409bca45c94 100755
--- a/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh
+++ b/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh
@@ -17,7 +17,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   set -x
diff --git a/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/build-toolchain.sh b/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/build-toolchain.sh
index faf30f36a20..189e537ecae 100755
--- a/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/build-toolchain.sh
+++ b/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/build-toolchain.sh
@@ -22,7 +22,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   set -x
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh
index 390ba1a1ddf..f15a7081612 100755
--- a/src/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh
+++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh
@@ -11,7 +11,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh
index 2e790b77a96..3fd88252199 100755
--- a/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh
@@ -12,7 +12,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh
index a01c2e0eb0a..f425efd6057 100755
--- a/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh
+++ b/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh
@@ -12,7 +12,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh
index 28f8ba2437b..17dda2dbd16 100755
--- a/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh
+++ b/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh
@@ -12,7 +12,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh b/src/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh
index d2e39834d6e..264d0764f29 100755
--- a/src/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh
@@ -11,7 +11,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh b/src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh
index b8735692789..dc86dddd464 100644
--- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh
+++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 hide_output() {
   set +x
   on_err="
@@ -8,7 +9,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   set -x
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh
index b8735692789..dc86dddd464 100644
--- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh
+++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 hide_output() {
   set +x
   on_err="
@@ -8,7 +9,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   set -x
diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh
index 6a7c022d01a..a7025b2b754 100755
--- a/src/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh
+++ b/src/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh
@@ -12,7 +12,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/crosstool-ng.sh b/src/ci/docker/host-x86_64/dist-riscv64-linux/crosstool-ng.sh
index fb067a79a5c..3a40f6cddb3 100644
--- a/src/ci/docker/host-x86_64/dist-riscv64-linux/crosstool-ng.sh
+++ b/src/ci/docker/host-x86_64/dist-riscv64-linux/crosstool-ng.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 # Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh b/src/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh
index df9529da8a1..6f8d6be842b 100755
--- a/src/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh
@@ -11,7 +11,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/host-x86_64/dist-various-1/build-rumprun.sh b/src/ci/docker/host-x86_64/dist-various-1/build-rumprun.sh
index 9c7aaef4f43..103dbbe6fda 100755
--- a/src/ci/docker/host-x86_64/dist-various-1/build-rumprun.sh
+++ b/src/ci/docker/host-x86_64/dist-various-1/build-rumprun.sh
@@ -11,7 +11,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   rm /tmp/build.log
diff --git a/src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh b/src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh
index 9584258d234..abab1809346 100755
--- a/src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh
+++ b/src/ci/docker/host-x86_64/dist-various-1/install-mips-musl.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 mkdir /usr/local/mips-linux-musl
diff --git a/src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh b/src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh
index 50a8e554b16..779acb2d841 100755
--- a/src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh
+++ b/src/ci/docker/host-x86_64/dist-various-1/install-mipsel-musl.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 mkdir /usr/local/mipsel-linux-musl
diff --git a/src/ci/docker/host-x86_64/dist-various-2/shared.sh b/src/ci/docker/host-x86_64/dist-various-2/shared.sh
index 7abace65b9c..267d8b79cc2 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/shared.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/shared.sh
@@ -1,3 +1,4 @@
+#!/usr/bin/env bash
 hide_output() {
   { set +x; } 2>/dev/null
   on_err="
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh
index b8735692789..dc86dddd464 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 hide_output() {
   set +x
   on_err="
@@ -8,7 +9,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   set -x
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh
index f8697c698b9..5dfa47b4eed 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh
@@ -13,7 +13,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   rm /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
diff --git a/src/ci/docker/scripts/android-base-apt-get.sh b/src/ci/docker/scripts/android-base-apt-get.sh
index 1795b1696d3..f1761f80643 100644
--- a/src/ci/docker/scripts/android-base-apt-get.sh
+++ b/src/ci/docker/scripts/android-base-apt-get.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 apt-get update
diff --git a/src/ci/docker/scripts/android-ndk.sh b/src/ci/docker/scripts/android-ndk.sh
index dafcb3cb7a7..ba70c62ea30 100644
--- a/src/ci/docker/scripts/android-ndk.sh
+++ b/src/ci/docker/scripts/android-ndk.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 URL=https://dl.google.com/android/repository
diff --git a/src/ci/docker/scripts/android-sdk.sh b/src/ci/docker/scripts/android-sdk.sh
index e35be697a8d..23360d30951 100755
--- a/src/ci/docker/scripts/android-sdk.sh
+++ b/src/ci/docker/scripts/android-sdk.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 export ANDROID_HOME=/android/sdk
diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh
index 2de376443ad..57cb6d5cda8 100644
--- a/src/ci/docker/scripts/cross-apt-packages.sh
+++ b/src/ci/docker/scripts/cross-apt-packages.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 apt-get update && apt-get install -y --no-install-recommends \
   automake \
   bison \
diff --git a/src/ci/docker/scripts/crosstool-ng-1.24.sh b/src/ci/docker/scripts/crosstool-ng-1.24.sh
index fb067a79a5c..3a40f6cddb3 100644
--- a/src/ci/docker/scripts/crosstool-ng-1.24.sh
+++ b/src/ci/docker/scripts/crosstool-ng-1.24.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 # Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz
diff --git a/src/ci/docker/scripts/crosstool-ng.sh b/src/ci/docker/scripts/crosstool-ng.sh
index 2773e687ebe..1d0c28c8e58 100644
--- a/src/ci/docker/scripts/crosstool-ng.sh
+++ b/src/ci/docker/scripts/crosstool-ng.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.22.0.tar.gz"
diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh
index 9481ee95399..56dc96283ed 100644
--- a/src/ci/docker/scripts/emscripten.sh
+++ b/src/ci/docker/scripts/emscripten.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 hide_output() {
@@ -10,7 +11,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   rm -f /tmp/build.log
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index b10263d5a26..c7ff78ca90c 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -19,7 +19,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   local ping_loop_pid=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $ping_loop_pid
   set -x
diff --git a/src/ci/docker/scripts/make3.sh b/src/ci/docker/scripts/make3.sh
index 47cb4158229..283700d06f6 100644
--- a/src/ci/docker/scripts/make3.sh
+++ b/src/ci/docker/scripts/make3.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 curl -f https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf -
diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh
index c56338a4f95..59fc921ec26 100644
--- a/src/ci/docker/scripts/musl-toolchain.sh
+++ b/src/ci/docker/scripts/musl-toolchain.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 # This script runs `musl-cross-make` to prepare C toolchain (Binutils, GCC, musl itself)
 # and builds static libunwind that we distribute for static target.
 #
@@ -19,7 +20,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   rm /tmp/build.log
diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh
index 58393a5719a..65e15950559 100644
--- a/src/ci/docker/scripts/musl.sh
+++ b/src/ci/docker/scripts/musl.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 hide_output() {
@@ -10,7 +11,7 @@ exit 1
   trap "$on_err" ERR
   bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
   PING_LOOP_PID=$!
-  $@ &> /tmp/build.log
+  "$@" &> /tmp/build.log
   trap - ERR
   kill $PING_LOOP_PID
   rm /tmp/build.log
@@ -32,7 +33,7 @@ if [ ! -d $MUSL ]; then
 fi
 
 cd $MUSL
-./configure --enable-optimize --enable-debug --disable-shared --prefix=/musl-$TAG $@
+./configure --enable-optimize --enable-debug --disable-shared --prefix=/musl-$TAG "$@"
 if [ "$TAG" = "i586" -o "$TAG" = "i686" ]; then
   hide_output make -j$(nproc) AR=ar RANLIB=ranlib
 else
diff --git a/src/ci/docker/scripts/rustbuild-setup.sh b/src/ci/docker/scripts/rustbuild-setup.sh
index 94d7e600eac..baf2a686871 100644
--- a/src/ci/docker/scripts/rustbuild-setup.sh
+++ b/src/ci/docker/scripts/rustbuild-setup.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild
diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh
index cebba57344b..292b3c1d562 100644
--- a/src/ci/docker/scripts/sccache.sh
+++ b/src/ci/docker/scripts/sccache.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -ex
 
 case "$(uname -m)" in
diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh
index 92c6e546a38..060b3079dad 100755
--- a/src/ci/init_repo.sh
+++ b/src/ci/init_repo.sh
@@ -53,6 +53,7 @@ modules=($modules)
 use_git=""
 urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)"
 urls=($urls)
+# shellcheck disable=SC2068
 for i in ${!modules[@]}; do
     module=${modules[$i]}
     if [[ " $included " = *" $module "* ]]; then
diff --git a/src/ci/shared.sh b/src/ci/shared.sh
index c93d4774e39..3c196c9478c 100644
--- a/src/ci/shared.sh
+++ b/src/ci/shared.sh
@@ -1,4 +1,5 @@
 #!/bin/false
+# shellcheck shell=bash
 
 # This file is intended to be sourced with `. shared.sh` or
 # `source shared.sh`, hence the invalid shebang and not being
diff --git a/src/doc/index.md b/src/doc/index.md
index 2d10230ffcf..2c92d5e2a18 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -26,7 +26,7 @@ h2 {
 }
 </style>
 
-Welcome to an overview of the documentation provided by the Rust project.
+Welcome to an overview of the documentation provided by the [Rust project].
 All of these projects are managed by the Docs Team; there are other
 unofficial documentation resources as well!
 
@@ -139,3 +139,4 @@ When developing for Bare Metal or Embedded Linux systems, you may find these res
 [The Embedded Rust Book] is targeted at developers familiar with embedded development and familiar with Rust, but have not used Rust for embedded development.
 
 [The Embedded Rust Book]: embedded-book/index.html
+[Rust project]: https://www.rust-lang.org
diff --git a/src/test/run-make/thumb-none-qemu/script.sh b/src/test/run-make/thumb-none-qemu/script.sh
index 045d02a8ed2..a8aa72af184 100644
--- a/src/test/run-make/thumb-none-qemu/script.sh
+++ b/src/test/run-make/thumb-none-qemu/script.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -exuo pipefail
 
 CRATE=example
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
index ec93c980160..54645e9e257 100644
--- a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
@@ -1,3 +1,4 @@
+#!/bin/sh
 set -exuo pipefail
 
 function build {
diff --git a/src/test/ui/error-codes/E0027.stderr b/src/test/ui/error-codes/E0027.stderr
index c09f1ff1f2a..cf0ff631148 100644
--- a/src/test/ui/error-codes/E0027.stderr
+++ b/src/test/ui/error-codes/E0027.stderr
@@ -8,7 +8,7 @@ help: include the missing field in the pattern
    |
 LL |         Dog { age: x, name } => {}
    |                     ^^^^^^
-help: if you don't care about this missing field, you can explicitely ignore it
+help: if you don't care about this missing field, you can explicitly ignore it
    |
 LL |         Dog { age: x, .. } => {}
    |                     ^^^^
@@ -23,7 +23,7 @@ help: include the missing fields in the pattern
    |
 LL |         Dog { name, age } => {}
    |             ^^^^^^^^^^^^^
-help: if you don't care about these missing fields, you can explicitely ignore them
+help: if you don't care about these missing fields, you can explicitly ignore them
    |
 LL |         Dog { .. } => {}
    |             ^^^^^^
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
index a1147cb5cfc..512f1e283cb 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
@@ -77,10 +77,17 @@ fn main() {
         (false | true, false | true) => {}
     }
     match (true, true) {
-        (true, false) => {}
-        (false, true) => {}
+        (true, true) => {}
+        (false, false) => {}
         (false | true, false | true) => {}
     }
+    // https://github.com/rust-lang/rust/issues/76836
+    match None {
+        Some(false) => {}
+        None | Some(true
+                | false) => {} //~ ERROR unreachable
+    }
+
     // A subpattern that is unreachable in all branches is overall unreachable.
     match (true, true) {
         (false, true) => {}
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
index d92b545a869..e968310d108 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
@@ -101,16 +101,22 @@ LL |         Some(0
    |              ^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:89:15
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:88:19
+   |
+LL |                 | false) => {}
+   |                   ^^^^^
+
+error: unreachable pattern
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:96:15
    |
 LL |             | true) => {}
    |               ^^^^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:95:15
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:102:15
    |
 LL |             | true,
    |               ^^^^
 
-error: aborting due to 18 previous errors
+error: aborting due to 19 previous errors
 
diff --git a/src/test/ui/structs/struct-field-cfg.stderr b/src/test/ui/structs/struct-field-cfg.stderr
index b913b929079..740ea3829dc 100644
--- a/src/test/ui/structs/struct-field-cfg.stderr
+++ b/src/test/ui/structs/struct-field-cfg.stderr
@@ -22,7 +22,7 @@ help: include the missing field in the pattern
    |
 LL |     let Foo { present } = foo;
    |             ^^^^^^^^^^^
-help: if you don't care about this missing field, you can explicitely ignore it
+help: if you don't care about this missing field, you can explicitly ignore it
    |
 LL |     let Foo { .. } = foo;
    |             ^^^^^^
diff --git a/src/test/ui/structs/struct-pat-derived-error.stderr b/src/test/ui/structs/struct-pat-derived-error.stderr
index f3e9ce76f1e..921d060faa3 100644
--- a/src/test/ui/structs/struct-pat-derived-error.stderr
+++ b/src/test/ui/structs/struct-pat-derived-error.stderr
@@ -20,7 +20,7 @@ help: include the missing fields in the pattern
    |
 LL |         let A { x, y, b, c } = self.d;
    |                     ^^^^^^
-help: if you don't care about these missing fields, you can explicitely ignore them
+help: if you don't care about these missing fields, you can explicitly ignore them
    |
 LL |         let A { x, y, .. } = self.d;
    |                     ^^^^
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 2f832b53a90..24ef98cd784 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -224,6 +224,10 @@ pub struct Config {
     /// The test mode, compile-fail, run-fail, ui
     pub mode: Mode,
 
+    /// The test suite (essentially which directory is running, but without the
+    /// directory prefix such as src/test)
+    pub suite: String,
+
     /// The debugger to use in debuginfo mode. Unset otherwise.
     pub debugger: Option<Debugger>,
 
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 1f82b137ee6..4bcbd89f095 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -39,6 +39,7 @@ fn config() -> Config {
     let args = &[
         "compiletest",
         "--mode=ui",
+        "--suite=ui",
         "--compile-lib-path=",
         "--run-lib-path=",
         "--rustc-path=",
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 2b2a6cfa8bd..2b167ac8e9f 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -70,6 +70,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "compile-fail | run-fail | run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
              codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
         )
+        .reqopt(
+            "",
+            "suite",
+            "which suite of compile tests to run. used for nicer error reporting.",
+            "SUITE",
+        )
         .optopt(
             "",
             "pass",
@@ -201,6 +207,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         build_base: opt_path(matches, "build-base"),
         stage_id: matches.opt_str("stage-id").unwrap(),
         mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"),
+        suite: matches.opt_str("suite").unwrap(),
         debugger: None,
         run_ignored,
         filter: matches.free.first().cloned(),
@@ -340,7 +347,7 @@ pub fn run_tests(config: Config) {
             configs.extend(configure_lldb(&config));
         }
     } else {
-        configs.push(config);
+        configs.push(config.clone());
     };
 
     let mut tests = Vec::new();
@@ -351,11 +358,32 @@ pub fn run_tests(config: Config) {
     let res = test::run_tests_console(&opts, tests);
     match res {
         Ok(true) => {}
-        Ok(false) => panic!("Some tests failed"),
+        Ok(false) => {
+            // We want to report that the tests failed, but we also want to give
+            // some indication of just what tests we were running. Especially on
+            // CI, where there can be cross-compiled tests for a lot of
+            // architectures, without this critical information it can be quite
+            // easy to miss which tests failed, and as such fail to reproduce
+            // the failure locally.
+
+            eprintln!(
+                "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
+                config.suite,
+                config.compare_mode.map(|c| format!(" compare_mode={:?}", c)).unwrap_or_default(),
+                config.mode,
+                config.host,
+                config.target
+            );
+
+            std::process::exit(1);
+        }
         Err(e) => {
             // We don't know if tests passed or not, but if there was an error
             // during testing we don't want to just suceeed (we may not have
             // tested something), so fail.
+            //
+            // This should realistically "never" happen, so don't try to make
+            // this a pretty error message.
             panic!("I/O failure during tests: {:?}", e);
         }
     }