about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/ci.yml9
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/failures.yml5
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/m68k.yml9
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/release.yml9
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml12
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock4
-rwxr-xr-xcompiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh4
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/build.rs6
-rw-r--r--compiler/rustc_codegen_gcc/failing-ui-tests12.txt2
-rw-r--r--compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch14
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs16
-rw-r--r--compiler/rustc_codegen_gcc/src/int.rs25
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs54
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs6
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs23
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs15
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs4
-rw-r--r--compiler/rustc_infer/src/traits/util.rs5
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs9
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs20
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs96
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs14
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs40
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs27
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs3
-rw-r--r--library/std/src/os/linux/process.rs6
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs76
-rw-r--r--library/std/src/sys/unix/process/process_unix/tests.rs19
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_shl2.rs9
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_shl2.stderr15
-rw-r--r--tests/ui/associated-types/missing-associated-types.stderr4
-rw-r--r--tests/ui/coherence/negative-coherence-check-placeholder-outlives.rs14
-rw-r--r--tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr11
-rw-r--r--tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr19
-rw-r--r--tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs25
-rw-r--r--tests/ui/consts/const-int-unchecked.stderr40
-rw-r--r--tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs19
-rw-r--r--tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr54
-rw-r--r--tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs9
-rw-r--r--tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr26
-rw-r--r--tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr26
-rw-r--r--tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr26
-rw-r--r--tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs22
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs3
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr17
54 files changed, 795 insertions, 147 deletions
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
index 65e7a697ab0..308bc55ead7 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
@@ -99,8 +99,10 @@ jobs:
     - name: Build
       run: |
         ./y.sh prepare --only-libcore
-        ./y.sh build
-        cargo test
+        # TODO: remove --features master when it is back to the default.
+        ./y.sh build --features master
+        # TODO: remove --features master when it is back to the default.
+        cargo test --features master
         ./clean_all.sh
 
     - name: Prepare dependencies
@@ -121,7 +123,8 @@ jobs:
 
     - name: Run tests
       run: |
-        ./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
+        # TODO: remove --features master when it is back to the default.
+        ./test.sh --features master --release --clean --build-sysroot ${{ matrix.commands }}
 
   duplicates:
     runs-on: ubuntu-latest
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
index 27864dcadd0..ae8de79b773 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
@@ -21,11 +21,14 @@ jobs:
         libgccjit_version:
           - gcc: "libgccjit.so"
             artifacts_branch: "master"
+            # TODO: switch back to --no-default-features in the case of libgccjit 12 when the default is to enable
+            # master again.
+            extra: "--features master"
           - gcc: "libgccjit_without_int128.so"
             artifacts_branch: "master-without-128bit-integers"
+            extra: "--features master"
           - gcc: "libgccjit12.so"
             artifacts_branch: "gcc12"
-            extra: "--no-default-features"
             # FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
             # Not sure why it's not found otherwise.
             env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/"
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
index 55ee0a21214..4d9d7e23dc2 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
@@ -114,8 +114,10 @@ jobs:
     - name: Build
       run: |
         ./y.sh prepare --only-libcore --cross
-        ./y.sh build --target-triple m68k-unknown-linux-gnu
-        CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test
+        # TODO: remove --features master when it is back to the default.
+        ./y.sh build --target-triple m68k-unknown-linux-gnu --features master
+        # TODO: remove --features master when it is back to the default.
+        CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test --features master
         ./clean_all.sh
 
     - name: Prepare dependencies
@@ -136,4 +138,5 @@ jobs:
 
     - name: Run tests
       run: |
-        ./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
+        # TODO: remove --features master when it is back to the default.
+        ./test.sh --release --features master --clean --build-sysroot ${{ matrix.commands }}
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
index ae1134177a7..43b90fcec93 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/release.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
@@ -78,8 +78,10 @@ jobs:
     - name: Build
       run: |
         ./y.sh prepare --only-libcore
-        EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot
-        cargo test
+        # TODO: remove --features master when it is back to the default.
+        EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot --features master
+        # TODO: remove --features master when it is back to the default.
+        cargo test --features master
         ./clean_all.sh
 
     - name: Prepare dependencies
@@ -102,4 +104,5 @@ jobs:
 
     - name: Run tests
       run: |
-        EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }}
+        # TODO: remove --features master when it is back to the default.
+        EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} --features master
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
index 28ac3cb6542..42109ba3e02 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
@@ -92,8 +92,10 @@ jobs:
     - name: Build
       run: |
         ./y.sh prepare --only-libcore
-        ./y.sh build --release --release-sysroot
-        cargo test
+        # TODO: remove `--features master` when it is back to the default.
+        ./y.sh build --release --release-sysroot --features master
+        # TODO: remove --features master when it is back to the default.
+        cargo test --features master
 
     - name: Clean
       if: ${{ !matrix.cargo_runner }}
@@ -111,12 +113,14 @@ jobs:
       uses: actions-rs/cargo@v1.0.3
       with:
         command: build
-        args: --release
+        # TODO: remove `--features master` when it is back to the default.
+        args: --release --features master
 
     - name: Run tests
       if: ${{ !matrix.cargo_runner }}
       run: |
-        ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore
+        # TODO: remove `--features master` when it is back to the default.
+        ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore --features master
 
     - name: Run stdarch tests
       if: ${{ !matrix.cargo_runner }}
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index b8e2e5d8080..7c186336927 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -74,7 +74,7 @@ dependencies = [
 [[package]]
 name = "gccjit"
 version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
+source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421"
 dependencies = [
  "gccjit_sys",
 ]
@@ -82,7 +82,7 @@ dependencies = [
 [[package]]
 name = "gccjit_sys"
 version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
+source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421"
 dependencies = [
  "libc",
 ]
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
index 116fd36e7a7..ebc7dc375b1 100755
--- a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
+++ b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
@@ -28,3 +28,7 @@ fi
 # Copy files to sysroot
 mkdir -p sysroot/lib/rustlib/$TARGET_TRIPLE/lib/
 cp -r target/$TARGET_TRIPLE/$sysroot_channel/deps/* sysroot/lib/rustlib/$TARGET_TRIPLE/lib/
+# Copy the source files to the sysroot (Rust for Linux needs this).
+source_dir=sysroot/lib/rustlib/src/rust
+mkdir -p $source_dir
+cp -r sysroot_src/library/ $source_dir
diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs
index eaca7a987d6..f1c3701a946 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/build.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs
@@ -194,6 +194,12 @@ fn build_sysroot(
         copier,
     )?;
 
+    // Copy the source files to the sysroot (Rust for Linux needs this).
+    let sysroot_src_path = "sysroot/lib/rustlib/src/rust";
+    fs::create_dir_all(&sysroot_src_path)
+        .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_src_path, error))?;
+    run_command(&[&"cp", &"-r", &"sysroot_src/library/", &sysroot_src_path], None)?;
+
     Ok(())
 }
 
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
index f91aa925318..4af93939b06 100644
--- a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
+++ b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
@@ -38,3 +38,5 @@ tests/ui/target-feature/missing-plusminus.rs
 tests/ui/sse2.rs
 tests/ui/codegen/issue-79865-llvm-miscompile.rs
 tests/ui/intrinsics/intrinsics-integer.rs
+tests/ui/std-backtrace.rs
+tests/ui/mir/alignment/packed.rs
diff --git a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
index 9520a5a39ed..914ae986b50 100644
--- a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
+++ b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
@@ -1,6 +1,6 @@
-From 7bcd24ec6d4a96121874cb1ae5a23ea274aeff34 Mon Sep 17 00:00:00 2001
+From a5663265f797a43c502915c356fe7899c16cee92 Mon Sep 17 00:00:00 2001
 From: None <none@example.com>
-Date: Thu, 19 Oct 2023 13:12:51 -0400
+Date: Sat, 18 Nov 2023 10:50:36 -0500
 Subject: [PATCH] [core] Disable portable-simd test
 
 ---
@@ -8,18 +8,18 @@ Subject: [PATCH] [core] Disable portable-simd test
  1 file changed, 2 deletions(-)
 
 diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
-index 5814ed4..194ad4c 100644
+index d0a119c..76fdece 100644
 --- a/library/core/tests/lib.rs
 +++ b/library/core/tests/lib.rs
-@@ -90,7 +90,6 @@
+@@ -89,7 +89,6 @@
+ #![feature(never_type)]
  #![feature(unwrap_infallible)]
- #![feature(pointer_byte_offsets)]
  #![feature(pointer_is_aligned)]
 -#![feature(portable_simd)]
  #![feature(ptr_metadata)]
  #![feature(lazy_cell)]
  #![feature(unsized_tuple_coercion)]
-@@ -157,7 +156,6 @@ mod pin;
+@@ -155,7 +154,6 @@ mod pin;
  mod pin_macro;
  mod ptr;
  mod result;
@@ -28,5 +28,5 @@ index 5814ed4..194ad4c 100644
  mod str;
  mod str_lossy;
 -- 
-2.42.0
+2.42.1
 
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index 205ec53b425..1962c217258 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-10-21"
+channel = "nightly-2023-11-17"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index 5073066c138..b0788718da4 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -3,7 +3,6 @@ use std::env;
 use std::time::Instant;
 
 use gccjit::{
-    Context,
     FunctionType,
     GlobalKind,
 };
@@ -18,8 +17,9 @@ use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::DebugInfoMethods;
 use rustc_session::config::DebugInfo;
 use rustc_span::Symbol;
+use rustc_target::spec::PanicStrategy;
 
-use crate::{LockedTargetInfo, gcc_util};
+use crate::{LockedTargetInfo, gcc_util, new_context};
 use crate::GccContext;
 use crate::builder::Builder;
 use crate::context::CodegenCx;
@@ -88,20 +88,18 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
     fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTargetInfo)) -> ModuleCodegen<GccContext> {
         let cgu = tcx.codegen_unit(cgu_name);
         // Instantiate monomorphizations without filling out definitions yet...
-        let context = Context::default();
+        let context = new_context(tcx);
 
-        context.add_command_line_option("-fexceptions");
-        context.add_driver_option("-fexceptions");
+        if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
+            context.add_command_line_option("-fexceptions");
+            context.add_driver_option("-fexceptions");
+        }
 
         let disabled_features: HashSet<_> = tcx.sess.opts.cg.target_feature.split(',')
             .filter(|feature| feature.starts_with('-'))
             .map(|string| &string[1..])
             .collect();
 
-        if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
-            context.add_command_line_option("-masm=intel");
-        }
-
         if !disabled_features.contains("avx") && tcx.sess.target.arch == "x86_64" {
             // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for
             // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead.
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index ea8550d20f3..9b9b3ea4f87 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -76,6 +76,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 a >> b
             }
         }
+        else if a_type.is_vector() && a_type.is_vector() {
+            a >> b
+        }
         else if a_native && !b_native {
             self.gcc_lshr(a, self.gcc_int_cast(b, a_type))
         }
@@ -144,7 +147,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     fn additive_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
         let a_type = a.get_type();
         let b_type = b.get_type();
-        if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
+        if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) {
             if a_type != b_type {
                 if a_type.is_vector() {
                     // Vector types need to be bitcast.
@@ -158,6 +161,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             self.context.new_binary_op(None, operation, a_type, a, b)
         }
         else {
+            debug_assert!(a_type.dyncast_array().is_some());
+            debug_assert!(b_type.dyncast_array().is_some());
             let signed = a_type.is_compatible_with(self.i128_type);
             let func_name =
                 match (operation, signed) {
@@ -189,10 +194,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     fn multiplicative_operation(&self, operation: BinaryOp, operation_name: &str, signed: bool, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         let a_type = a.get_type();
         let b_type = b.get_type();
-        if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
+        if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) {
             self.context.new_binary_op(None, operation, a_type, a, b)
         }
         else {
+            debug_assert!(a_type.dyncast_array().is_some());
+            debug_assert!(b_type.dyncast_array().is_some());
             let sign =
                 if signed {
                     ""
@@ -337,6 +344,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
         let a_type = lhs.get_type();
         let b_type = rhs.get_type();
+        debug_assert!(a_type.dyncast_array().is_some());
+        debug_assert!(b_type.dyncast_array().is_some());
         let param_a = self.context.new_parameter(None, a_type, "a");
         let param_b = self.context.new_parameter(None, b_type, "b");
         let result_field = self.context.new_field(None, a_type, "result");
@@ -496,7 +505,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     pub fn gcc_xor(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         let a_type = a.get_type();
         let b_type = b.get_type();
-        if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
+        if a_type.is_vector() && b_type.is_vector() {
+            let b = self.bitcast_if_needed(b, a_type);
+            a ^ b
+        }
+        else if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
             a ^ b
         }
         else {
@@ -527,6 +540,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 a << b
             }
         }
+        else if a_type.is_vector() && a_type.is_vector() {
+            a << b
+        }
         else if a_native && !b_native {
             self.gcc_shl(a, self.gcc_int_cast(b, a_type))
         }
@@ -690,6 +706,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         let a_native = self.is_native_int_type_or_bool(a_type);
         let b_native = self.is_native_int_type_or_bool(b_type);
         if a_type.is_vector() && b_type.is_vector() {
+            let b = self.bitcast_if_needed(b, a_type);
             self.context.new_binary_op(None, operation, a_type, a, b)
         }
         else if a_native && b_native {
@@ -748,6 +765,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             return self.context.new_cast(None, value, dest_typ);
         }
 
+        debug_assert!(value_type.dyncast_array().is_some());
         let name_suffix =
             match self.type_kind(dest_typ) {
                 TypeKind::Float => "tisf",
@@ -781,6 +799,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             return self.context.new_cast(None, value, dest_typ);
         }
 
+        debug_assert!(value_type.dyncast_array().is_some());
         let name_suffix =
             match self.type_kind(value_type) {
                 TypeKind::Float => "sfti",
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index fd4af984bc0..8c7bae0c886 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -39,6 +39,8 @@ extern crate rustc_errors;
 extern crate rustc_fluent_macro;
 extern crate rustc_fs_util;
 extern crate rustc_hir;
+#[cfg(feature="master")]
+extern crate rustc_interface;
 extern crate rustc_macros;
 extern crate rustc_metadata;
 extern crate rustc_middle;
@@ -86,7 +88,7 @@ use std::sync::atomic::Ordering;
 
 use gccjit::{Context, OptimizationLevel};
 #[cfg(feature="master")]
-use gccjit::TargetInfo;
+use gccjit::{TargetInfo, Version};
 #[cfg(not(feature="master"))]
 use gccjit::CType;
 use errors::LTONotSupported;
@@ -244,17 +246,33 @@ impl CodegenBackend for GccCodegenBackend {
     }
 }
 
+fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
+    let context = Context::default();
+    if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
+        context.add_command_line_option("-masm=intel");
+    }
+    #[cfg(feature="master")]
+    {
+        let version = Version::get();
+        let version = format!("{}.{}.{}", version.major, version.minor, version.patch);
+        context.set_output_ident(&format!("rustc version {} with libgccjit {}",
+                rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
+                version,
+        ));
+    }
+    // TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n.
+    context.add_command_line_option("-fno-asynchronous-unwind-tables");
+    context
+}
+
 impl ExtraBackendMethods for GccCodegenBackend {
     fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module {
         let mut mods = GccContext {
-            context: Context::default(),
+            context: new_context(tcx),
             should_combine_object_files: false,
             temp_dir: None,
         };
 
-        if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
-            mods.context.add_command_line_option("-masm=intel");
-        }
         unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
         mods
     }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 198e5696357..23054975548 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -322,8 +322,13 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     if lhs_sz < rhs_sz {
         bx.trunc(rhs, lhs_llty)
     } else if lhs_sz > rhs_sz {
-        // FIXME (#1877: If in the future shifting by negative
-        // values is no longer undefined then this is wrong.
+        // We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the
+        // RHS to `255i32`. But then we mask the shift amount to be within the size of the LHS
+        // anyway so the result is `31` as it should be. All the extra bits introduced by zext
+        // are masked off so their value does not matter.
+        // FIXME: if we ever support 512bit integers, this will be wrong! For such large integers,
+        // the extra bits introduced by zext are *not* all masked away any more.
+        assert!(lhs_sz <= 256);
         bx.zext(rhs, lhs_llty)
     } else {
         rhs
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 128b548f43d..538077a0b77 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -156,41 +156,35 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         // Shift ops can have an RHS with a different numeric type.
         if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
-            let size = u128::from(left_layout.size.bits());
-            // Even if `r` is signed, we treat it as if it was unsigned (i.e., we use its
-            // zero-extended form). This matches the codegen backend:
-            // <https://github.com/rust-lang/rust/blob/c274e4969f058b1c644243181ece9f829efa7594/compiler/rustc_codegen_ssa/src/base.rs#L315-L317>.
-            // The overflow check is also ignorant to the sign:
-            // <https://github.com/rust-lang/rust/blob/c274e4969f058b1c644243181ece9f829efa7594/compiler/rustc_codegen_ssa/src/mir/rvalue.rs#L728>.
-            // This would behave rather strangely if we had integer types of size 256: a shift by
-            // -1i8 would actually shift by 255, but that would *not* be considered overflowing. A
-            // shift by -1i16 though would be considered overflowing. If we had integers of size
-            // 512, then a shift by -1i8 would even produce a different result than one by -1i16:
-            // the first shifts by 255, the latter by u16::MAX % 512 = 511. Lucky enough, our
-            // integers are maximally 128bits wide, so negative shifts *always* overflow and we have
-            // consistent results for the same value represented at different bit widths.
-            assert!(size <= 128);
-            let original_r = r;
-            let overflow = r >= size;
-            // The shift offset is implicitly masked to the type size, to make sure this operation
-            // is always defined. This is the one MIR operator that does *not* directly map to a
-            // single LLVM operation. See
-            // <https://github.com/rust-lang/rust/blob/c274e4969f058b1c644243181ece9f829efa7594/compiler/rustc_codegen_ssa/src/common.rs#L131-L158>
-            // for the corresponding truncation in our codegen backends.
-            let r = r % size;
-            let r = u32::try_from(r).unwrap(); // we masked so this will always fit
+            let size = left_layout.size.bits();
+            // The shift offset is implicitly masked to the type size. (This is the one MIR operator
+            // that does *not* directly map to a single LLVM operation.) Compute how much we
+            // actually shift and whether there was an overflow due to shifting too much.
+            let (shift_amount, overflow) = if right_layout.abi.is_signed() {
+                let shift_amount = self.sign_extend(r, right_layout) as i128;
+                let overflow = shift_amount < 0 || shift_amount >= i128::from(size);
+                let masked_amount = (shift_amount as u128) % u128::from(size);
+                debug_assert_eq!(overflow, shift_amount != (masked_amount as i128));
+                (masked_amount, overflow)
+            } else {
+                let shift_amount = r;
+                let masked_amount = shift_amount % u128::from(size);
+                (masked_amount, shift_amount != masked_amount)
+            };
+            let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit
+            // Compute the shifted result.
             let result = if left_layout.abi.is_signed() {
                 let l = self.sign_extend(l, left_layout) as i128;
                 let result = match bin_op {
-                    Shl | ShlUnchecked => l.checked_shl(r).unwrap(),
-                    Shr | ShrUnchecked => l.checked_shr(r).unwrap(),
+                    Shl | ShlUnchecked => l.checked_shl(shift_amount).unwrap(),
+                    Shr | ShrUnchecked => l.checked_shr(shift_amount).unwrap(),
                     _ => bug!(),
                 };
                 result as u128
             } else {
                 match bin_op {
-                    Shl | ShlUnchecked => l.checked_shl(r).unwrap(),
-                    Shr | ShrUnchecked => l.checked_shr(r).unwrap(),
+                    Shl | ShlUnchecked => l.checked_shl(shift_amount).unwrap(),
+                    Shr | ShrUnchecked => l.checked_shr(shift_amount).unwrap(),
                     _ => bug!(),
                 }
             };
@@ -199,7 +193,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
                 throw_ub_custom!(
                     fluent::const_eval_overflow_shift,
-                    val = original_r,
+                    val = if right_layout.abi.is_signed() {
+                        (self.sign_extend(r, right_layout) as i128).to_string()
+                    } else {
+                        r.to_string()
+                    },
                     name = intrinsic_name
                 );
             }
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 7ced37e5694..8f4b83966df 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -4,7 +4,7 @@ use crate::errors::{
     ParenthesizedFnTraitExpansion,
 };
 use crate::traits::error_reporting::report_object_safety_error;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -16,8 +16,6 @@ use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, Symbol, DUMMY_SP};
 use rustc_trait_selection::traits::object_safety_violations_for_assoc_item;
 
-use std::collections::BTreeSet;
-
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
     /// the type parameter's name as a placeholder.
@@ -504,7 +502,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// emit a generic note suggesting using a `where` clause to constraint instead.
     pub(crate) fn complain_about_missing_associated_types(
         &self,
-        associated_types: FxHashMap<Span, BTreeSet<DefId>>,
+        associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
         potential_assoc_types: Vec<Span>,
         trait_bounds: &[hir::PolyTraitRef<'_>],
     ) {
@@ -514,13 +512,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let tcx = self.tcx();
         // FIXME: Marked `mut` so that we can replace the spans further below with a more
         // appropriate one, but this should be handled earlier in the span assignment.
-        let mut associated_types: FxHashMap<Span, Vec<_>> = associated_types
+        let mut associated_types: FxIndexMap<Span, Vec<_>> = associated_types
             .into_iter()
             .map(|(span, def_ids)| {
                 (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
             })
             .collect();
-        let mut names: FxHashMap<String, Vec<Symbol>> = Default::default();
+        let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default();
         let mut names_len = 0;
 
         // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index 00ff3f836ad..78c5809f8b4 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -1,7 +1,7 @@
 use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
 use crate::bounds::Bounds;
 use crate::errors::TraitObjectDeclaredWithNoTraits;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -14,7 +14,6 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 use rustc_trait_selection::traits::{self, astconv_object_safety_violations};
 
 use smallvec::{smallvec, SmallVec};
-use std::collections::BTreeSet;
 
 use super::AstConv;
 
@@ -148,8 +147,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        // Use a `BTreeSet` to keep output in a more consistent order.
-        let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
+        let mut associated_types: FxIndexMap<Span, FxIndexSet<DefId>> = FxIndexMap::default();
 
         let regular_traits_refs_spans = trait_bounds
             .into_iter()
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 218f658b061..8077acea52e 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -80,6 +80,10 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
                             .or_insert(span);
                     }
 
+                    Component::Placeholder(_) => {
+                        span_bug!(span, "Should not deduce placeholder outlives component");
+                    }
+
                     Component::Alias(alias_ty) => {
                         // This would either arise from something like:
                         //
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 56e3280088e..d7669b1a4b5 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2351,6 +2351,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         let labeled_user_string = match bound_kind {
             GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
+            GenericKind::Placeholder(ref p) => format!("the placeholder type `{p:?}`"),
             GenericKind::Alias(ref p) => match p.kind(self.tcx) {
                 ty::AliasKind::Projection | ty::AliasKind::Inherent => {
                     format!("the associated type `{p}`")
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index f867876a2e6..806ecf35330 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -11,6 +11,7 @@ use smallvec::{smallvec, SmallVec};
 pub enum Component<'tcx> {
     Region(ty::Region<'tcx>),
     Param(ty::ParamTy),
+    Placeholder(ty::PlaceholderType),
     UnresolvedInferenceVariable(ty::InferTy),
 
     // Projections like `T::Foo` are tricky because a constraint like
@@ -120,6 +121,10 @@ fn compute_components<'tcx>(
                 out.push(Component::Param(p));
             }
 
+            ty::Placeholder(p) => {
+                out.push(Component::Placeholder(p));
+            }
+
             // For projections, we prefer to generate an obligation like
             // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
             // regionck more ways to prove that it holds. However,
@@ -176,7 +181,6 @@ fn compute_components<'tcx>(
             ty::Tuple(..) |       // ...
             ty::FnPtr(_) |        // OutlivesFunction (*)
             ty::Dynamic(..) |     // OutlivesObject, OutlivesFragment (*)
-            ty::Placeholder(..) |
             ty::Bound(..) |
             ty::Error(_) => {
                 // (*) Function pointers and trait objects are both binders.
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index f36802e1284..1bc24682b9a 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -243,6 +243,9 @@ where
                 Component::Param(param_ty) => {
                     self.param_ty_must_outlive(origin, region, *param_ty);
                 }
+                Component::Placeholder(placeholder_ty) => {
+                    self.placeholder_ty_must_outlive(origin, region, *placeholder_ty);
+                }
                 Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
                 Component::EscapingAlias(subcomponents) => {
                     self.components_must_outlive(origin, &subcomponents, region, category);
@@ -267,11 +270,29 @@ where
         region: ty::Region<'tcx>,
         param_ty: ty::ParamTy,
     ) {
-        let verify_bound = self.verify_bound.param_bound(param_ty);
+        let verify_bound = self.verify_bound.param_or_placeholder_bound(param_ty.to_ty(self.tcx));
         self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
     }
 
     #[instrument(level = "debug", skip(self))]
+    fn placeholder_ty_must_outlive(
+        &mut self,
+        origin: infer::SubregionOrigin<'tcx>,
+        region: ty::Region<'tcx>,
+        placeholder_ty: ty::PlaceholderType,
+    ) {
+        let verify_bound = self
+            .verify_bound
+            .param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty));
+        self.delegate.push_verify(
+            origin,
+            GenericKind::Placeholder(placeholder_ty),
+            region,
+            verify_bound,
+        );
+    }
+
+    #[instrument(level = "debug", skip(self))]
     fn alias_ty_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 7f0a4717d88..35a8fe6dc47 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -37,11 +37,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self))]
-    pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
+    pub fn param_or_placeholder_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
         // Start with anything like `T: 'a` we can scrape from the
         // environment. If the environment contains something like
         // `for<'a> T: 'a`, then we know that `T` outlives everything.
-        let declared_bounds_from_env = self.declared_generic_bounds_from_env(param_ty);
+        let declared_bounds_from_env = self.declared_generic_bounds_from_env(ty);
         debug!(?declared_bounds_from_env);
         let mut param_bounds = vec![];
         for declared_bound in declared_bounds_from_env {
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
                 param_bounds.push(VerifyBound::OutlivedBy(region));
             } else {
                 // This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here.
-                debug!("found that {param_ty:?} outlives any lifetime, returning empty vector");
+                debug!("found that {ty:?} outlives any lifetime, returning empty vector");
                 return VerifyBound::AllBounds(vec![]);
             }
         }
@@ -168,7 +168,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     ) -> VerifyBound<'tcx> {
         match *component {
             Component::Region(lt) => VerifyBound::OutlivedBy(lt),
-            Component::Param(param_ty) => self.param_bound(param_ty),
+            Component::Param(param_ty) => self.param_or_placeholder_bound(param_ty.to_ty(self.tcx)),
+            Component::Placeholder(placeholder_ty) => {
+                self.param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty))
+            }
             Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited),
             Component::EscapingAlias(ref components) => {
                 self.bound_from_components(components, visited)
@@ -195,9 +198,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     /// bounds, but all the bounds it returns can be relied upon.
     fn declared_generic_bounds_from_env(
         &self,
-        param_ty: ty::ParamTy,
+        generic_ty: Ty<'tcx>,
     ) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
-        let generic_ty = param_ty.to_ty(self.tcx);
+        assert!(matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_)));
         self.declared_generic_bounds_from_env_for_erased_ty(generic_ty)
     }
 
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index e888340bde3..eb00621ed7f 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -147,6 +147,7 @@ pub struct Verify<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
 pub enum GenericKind<'tcx> {
     Param(ty::ParamTy),
+    Placeholder(ty::PlaceholderType),
     Alias(ty::AliasTy<'tcx>),
 }
 
@@ -707,6 +708,7 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             GenericKind::Param(ref p) => write!(f, "{p:?}"),
+            GenericKind::Placeholder(ref p) => write!(f, "{p:?}"),
             GenericKind::Alias(ref p) => write!(f, "{p:?}"),
         }
     }
@@ -716,6 +718,7 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             GenericKind::Param(ref p) => write!(f, "{p}"),
+            GenericKind::Placeholder(ref p) => write!(f, "{p:?}"),
             GenericKind::Alias(ref p) => write!(f, "{p}"),
         }
     }
@@ -725,6 +728,7 @@ impl<'tcx> GenericKind<'tcx> {
     pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
             GenericKind::Param(ref p) => p.to_ty(tcx),
+            GenericKind::Placeholder(ref p) => Ty::new_placeholder(tcx, *p),
             GenericKind::Alias(ref p) => p.to_ty(tcx),
         }
     }
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 8cee13ce4ec..ed3409149d0 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -365,6 +365,11 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                                 Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
                             }
 
+                            Component::Placeholder(p) => {
+                                let ty = Ty::new_placeholder(tcx, p);
+                                Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
+                            }
+
                             Component::UnresolvedInferenceVariable(_) => None,
 
                             Component::Alias(alias_ty) => {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 7b0f27f9b34..8cf9e55f0b6 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1404,18 +1404,18 @@ pub enum BinOp {
     BitOr,
     /// The `<<` operator (shift left)
     ///
-    /// The offset is truncated to the size of the first operand before shifting.
+    /// The offset is truncated to the size of the first operand and made unsigned before shifting.
     Shl,
-    /// Like `Shl`, but is UB if the RHS >= LHS::BITS
+    /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0
     ShlUnchecked,
     /// The `>>` operator (shift right)
     ///
-    /// The offset is truncated to the size of the first operand before shifting.
+    /// The offset is truncated to the size of the first operand and made unsigned before shifting.
     ///
     /// This is an arithmetic shift if the LHS is signed
     /// and a logical shift if the LHS is unsigned.
     Shr,
-    /// Like `Shl`, but is UB if the RHS >= LHS::BITS
+    /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0
     ShrUnchecked,
     /// The `==` operator (equality)
     Eq,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index eece8684e36..2130dbdc033 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -600,10 +600,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => {
                 // For an unsigned RHS, the shift is in-range for `rhs < bits`.
                 // For a signed RHS, `IntToInt` cast to the equivalent unsigned
-                // type and do that same comparison. Because the type is the
-                // same size, there's no negative shift amount that ends up
-                // overlapping with valid ones, thus it catches negatives too.
+                // type and do that same comparison.
+                // A negative value will be *at least* 128 after the cast (that's i8::MIN),
+                // and 128 is an overflowing shift amount for all our currently existing types,
+                // so this cast can never make us miss an overflow.
                 let (lhs_size, _) = ty.int_size_and_signed(self.tcx);
+                assert!(lhs_size.bits() <= 128);
                 let rhs_ty = rhs.ty(&self.local_decls, self.tcx);
                 let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx);
 
@@ -625,7 +627,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 // This can't overflow because the largest shiftable types are 128-bit,
                 // which fits in `u8`, the smallest possible `unsigned_ty`.
-                // (And `from_uint` will `bug!` if that's ever no longer true.)
                 let lhs_bits = Operand::const_from_scalar(
                     self.tcx,
                     unsigned_ty,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 266190da035..49a2c414467 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -739,6 +739,9 @@ parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
 parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
 parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
 
+parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before
+    .suggestion = move `{$kw}` before the `for<...>`
+
 parse_type_ascription_removed =
     if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 99e66fddc70..7ce348619c6 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2827,3 +2827,23 @@ pub(crate) struct GenericArgsInPatRequireTurbofishSyntax {
     )]
     pub suggest_turbofish: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_transpose_dyn_or_impl)]
+pub(crate) struct TransposeDynOrImpl<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub kw: &'a str,
+    #[subdiagnostic]
+    pub sugg: TransposeDynOrImplSugg<'a>,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
+pub(crate) struct TransposeDynOrImplSugg<'a> {
+    #[suggestion_part(code = "")]
+    pub removal_span: Span,
+    #[suggestion_part(code = "{kw} ")]
+    pub insertion_span: Span,
+    pub kw: &'a str,
+}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 262e7b899ad..57bc865a0ee 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -21,6 +21,7 @@ use crate::errors::{
 
 use crate::fluent_generated as fluent;
 use crate::parser;
+use crate::parser::attr::InnerAttrPolicy;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
@@ -723,6 +724,101 @@ impl<'a> Parser<'a> {
         Err(err)
     }
 
+    pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) {
+        // Missing semicolon typo error.
+        let span = self.prev_token.span.shrink_to_hi();
+        let mut err = self.sess.create_err(ExpectedSemi {
+            span,
+            token: self.token.clone(),
+            unexpected_token_label: Some(self.token.span),
+            sugg: ExpectedSemiSugg::AddSemi(span),
+        });
+        let attr_span = match &expr.attrs[..] {
+            [] => unreachable!(),
+            [only] => only.span,
+            [first, rest @ ..] => {
+                for attr in rest {
+                    err.span_label(attr.span, "");
+                }
+                first.span
+            }
+        };
+        err.span_label(
+            attr_span,
+            format!(
+                "only `;` terminated statements or tail expressions are allowed after {}",
+                if expr.attrs.len() == 1 { "this attribute" } else { "these attributes" },
+            ),
+        );
+        if self.token == token::Pound
+            && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Bracket))
+        {
+            // We have
+            // #[attr]
+            // expr
+            // #[not_attr]
+            // other_expr
+            err.span_label(span, "expected `;` here");
+            err.multipart_suggestion(
+                "alternatively, consider surrounding the expression with a block",
+                vec![
+                    (expr.span.shrink_to_lo(), "{ ".to_string()),
+                    (expr.span.shrink_to_hi(), " }".to_string()),
+                ],
+                Applicability::MachineApplicable,
+            );
+            let mut snapshot = self.create_snapshot_for_diagnostic();
+            if let [attr] = &expr.attrs[..]
+                && let ast::AttrKind::Normal(attr_kind) = &attr.kind
+                && let [segment] = &attr_kind.item.path.segments[..]
+                && segment.ident.name == sym::cfg
+                && let Ok(next_attr) = snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None))
+                && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
+                && let [next_segment] = &next_attr_kind.item.path.segments[..]
+                && segment.ident.name == sym::cfg
+                && let Ok(next_expr) = snapshot.parse_expr()
+            {
+                // We have for sure
+                // #[cfg(..)]
+                // expr
+                // #[cfg(..)]
+                // other_expr
+                // So we suggest using `if cfg!(..) { expr } else if cfg!(..) { other_expr }`.
+                let margin = self.sess.source_map().span_to_margin(next_expr.span).unwrap_or(0);
+                let sugg = vec![
+                    (attr.span.with_hi(segment.span().hi()), "if cfg!".to_string()),
+                    (
+                        attr_kind.item.args.span().unwrap().shrink_to_hi().with_hi(attr.span.hi()),
+                        " {".to_string(),
+                    ),
+                    (expr.span.shrink_to_lo(), "    ".to_string()),
+                    (
+                        next_attr.span.with_hi(next_segment.span().hi()),
+                        "} else if cfg!".to_string(),
+                    ),
+                    (
+                        next_attr_kind
+                            .item
+                            .args
+                            .span()
+                            .unwrap()
+                            .shrink_to_hi()
+                            .with_hi(next_attr.span.hi()),
+                        " {".to_string(),
+                    ),
+                    (next_expr.span.shrink_to_lo(), "    ".to_string()),
+                    (next_expr.span.shrink_to_hi(), format!("\n{}}}", " ".repeat(margin))),
+                ];
+                err.multipart_suggestion(
+                    "it seems like you are trying to provide different expressions depending on \
+                     `cfg`, consider using `if cfg!(..)`",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+        err.emit();
+    }
     fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool {
         let sm = self.sess.source_map();
         match (&self.prev_token.kind, &self.token.kind) {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index d1c5ca4b93c..5316dde6096 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -619,6 +619,20 @@ impl<'a> Parser<'a> {
         match &mut stmt.kind {
             // Expression without semicolon.
             StmtKind::Expr(expr)
+                if classify::expr_requires_semi_to_be_stmt(expr)
+                    && !expr.attrs.is_empty()
+                    && ![token::Eof, token::Semi, token::CloseDelim(Delimiter::Brace)]
+                        .contains(&self.token.kind) =>
+            {
+                // The user has written `#[attr] expr` which is unsupported. (#106020)
+                self.attr_on_non_tail_expr(&expr);
+                // We already emitted an error, so don't emit another type error
+                let sp = expr.span.to(self.prev_token.span);
+                *expr = self.mk_expr_err(sp);
+            }
+
+            // Expression without semicolon.
+            StmtKind::Expr(expr)
                 if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) =>
             {
                 // Just check for errors and recover; do not eat semicolon yet.
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index dc0f1396523..75617b1b3ea 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -287,6 +287,7 @@ impl<'a> Parser<'a> {
             // Function pointer type
             self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)?
         } else if self.check_keyword(kw::For) {
+            let for_span = self.token.span;
             // Function pointer type or bound list (trait object type) starting with a poly-trait.
             //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
             //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
@@ -299,9 +300,42 @@ impl<'a> Parser<'a> {
                     recover_return_sign,
                 )?
             } else {
-                let path = self.parse_path(PathStyle::Type)?;
-                let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
-                self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
+                // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`.
+                if self.may_recover()
+                    && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
+                {
+                    let kw = self.prev_token.ident().unwrap().0.name;
+                    let mut err = self.sess.create_err(errors::TransposeDynOrImpl {
+                        span: self.prev_token.span,
+                        kw: kw.as_str(),
+                        sugg: errors::TransposeDynOrImplSugg {
+                            removal_span: self.prev_token.span.with_hi(self.token.span.lo()),
+                            insertion_span: for_span.shrink_to_lo(),
+                            kw: kw.as_str(),
+                        },
+                    });
+                    let path = self.parse_path(PathStyle::Type)?;
+                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
+                    let kind =
+                        self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?;
+                    // Take the parsed bare trait object and turn it either
+                    // into a `dyn` object or an `impl Trait`.
+                    let kind = match (kind, kw) {
+                        (TyKind::TraitObject(bounds, _), kw::Dyn) => {
+                            TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
+                        }
+                        (TyKind::TraitObject(bounds, _), kw::Impl) => {
+                            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
+                        }
+                        _ => return Err(err),
+                    };
+                    err.emit();
+                    kind
+                } else {
+                    let path = self.parse_path(PathStyle::Type)?;
+                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
+                    self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
+                }
             }
         } else if self.eat_keyword(kw::Impl) {
             self.parse_impl_ty(&mut impl_dyn_multi)?
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 7ca33ae41c0..362a734818c 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -398,7 +398,8 @@ fn impl_intersection_has_negative_obligation(
     debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
 
     let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build();
-    let universe = infcx.universe();
+    let root_universe = infcx.universe();
+    assert_eq!(root_universe, ty::UniverseIndex::ROOT);
 
     let impl1_header = fresh_impl_header(infcx, impl1_def_id);
     let param_env =
@@ -408,13 +409,25 @@ fn impl_intersection_has_negative_obligation(
 
     // Equate the headers to find their intersection (the general type, with infer vars,
     // that may apply both impls).
-    let Some(_equate_obligations) =
+    let Some(equate_obligations) =
         equate_impl_headers(infcx, param_env, &impl1_header, &impl2_header)
     else {
         return false;
     };
 
-    plug_infer_with_placeholders(infcx, universe, (impl1_header.impl_args, impl2_header.impl_args));
+    plug_infer_with_placeholders(
+        infcx,
+        root_universe,
+        (impl1_header.impl_args, impl2_header.impl_args),
+    );
+    let param_env = infcx.resolve_vars_if_possible(param_env);
+
+    // FIXME(with_negative_coherence): the infcx has constraints from equating
+    // the impl headers. We should use these constraints as assumptions, not as
+    // requirements, when proving the negated where clauses below.
+    drop(equate_obligations);
+    drop(infcx.take_registered_region_obligations());
+    drop(infcx.take_and_reset_region_constraints());
 
     util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args))
         .any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
@@ -541,14 +554,6 @@ fn try_prove_negated_where_clause<'tcx>(
         return false;
     };
 
-    // FIXME(with_negative_coherence): the infcx has region contraints from equating
-    // the impl headers as requirements. Given that the only region constraints we
-    // get are involving inference regions in the root, it shouldn't matter, but
-    // still sus.
-    //
-    // We probably should just throw away the region obligations registered up until
-    // now, or ideally use them as assumptions when proving the region obligations
-    // that we get from proving the negative predicate below.
     let ref infcx = root_infcx.fork();
     let ocx = ObligationCtxt::new(infcx);
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index e345fc39ead..57df277f4b3 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -208,6 +208,9 @@ fn implied_bounds_from_components<'tcx>(
                 Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
                 Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
                 Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
+                Component::Placeholder(_) => {
+                    unimplemented!("Shouldn't expect a placeholder type in implied bounds (yet)")
+                }
                 Component::EscapingAlias(_) =>
                 // If the projection has escaping regions, don't
                 // try to infer any implied bounds even for its
diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs
index 2b3ff76d7a4..51af432d056 100644
--- a/library/std/src/os/linux/process.rs
+++ b/library/std/src/os/linux/process.rs
@@ -152,6 +152,12 @@ pub trait CommandExt: Sealed {
     /// in a guaranteed race-free manner (e.g. if the `clone3` system call
     /// is supported). Otherwise, [`pidfd`] will return an error.
     ///
+    /// If a pidfd has been successfully created and not been taken from the `Child`
+    /// then calls to `kill()`, `wait()` and `try_wait()` will use the pidfd
+    /// instead of the pid. This can prevent pid recycling races, e.g.
+    /// those  caused by rogue libraries in the same process prematurely reaping
+    /// zombie children via `waitpid(-1, ...)` calls.
+    ///
     /// [`Command`]: process::Command
     /// [`Child`]: process::Child
     /// [`pidfd`]: fn@ChildExt::pidfd
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 72aca4e6659..ee86a5f88dd 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -9,6 +9,8 @@ use core::ffi::NonZero_c_int;
 
 #[cfg(target_os = "linux")]
 use crate::os::linux::process::PidFd;
+#[cfg(target_os = "linux")]
+use crate::os::unix::io::AsRawFd;
 
 #[cfg(any(
     target_os = "macos",
@@ -696,11 +698,12 @@ impl Command {
 
             msg.msg_iov = &mut iov as *mut _ as *mut _;
             msg.msg_iovlen = 1;
-            msg.msg_controllen = mem::size_of_val(&cmsg.buf) as _;
-            msg.msg_control = &mut cmsg.buf as *mut _ as *mut _;
 
             // only attach cmsg if we successfully acquired the pidfd
             if pidfd >= 0 {
+                msg.msg_controllen = mem::size_of_val(&cmsg.buf) as _;
+                msg.msg_control = &mut cmsg.buf as *mut _ as *mut _;
+
                 let hdr = CMSG_FIRSTHDR(&mut msg as *mut _ as *mut _);
                 (*hdr).cmsg_level = SOL_SOCKET;
                 (*hdr).cmsg_type = SCM_RIGHTS;
@@ -717,7 +720,7 @@ impl Command {
             // so we get a consistent SEQPACKET order
             match cvt_r(|| libc::sendmsg(sock.as_raw(), &msg, 0)) {
                 Ok(0) => {}
-                _ => rtabort!("failed to communicate with parent process"),
+                other => rtabort!("failed to communicate with parent process. {:?}", other),
             }
         }
     }
@@ -748,7 +751,7 @@ impl Command {
             msg.msg_controllen = mem::size_of::<Cmsg>() as _;
             msg.msg_control = &mut cmsg as *mut _ as *mut _;
 
-            match cvt_r(|| libc::recvmsg(sock.as_raw(), &mut msg, 0)) {
+            match cvt_r(|| libc::recvmsg(sock.as_raw(), &mut msg, libc::MSG_CMSG_CLOEXEC)) {
                 Err(_) => return -1,
                 Ok(_) => {}
             }
@@ -787,7 +790,7 @@ pub struct Process {
     // On Linux, stores the pidfd created for this child.
     // This is None if the user did not request pidfd creation,
     // or if the pidfd could not be created for some reason
-    // (e.g. the `clone3` syscall was not available).
+    // (e.g. the `pidfd_open` syscall was not available).
     #[cfg(target_os = "linux")]
     pidfd: Option<PidFd>,
 }
@@ -816,10 +819,23 @@ impl Process {
         // and used for another process, and we probably shouldn't be killing
         // random processes, so return Ok because the process has exited already.
         if self.status.is_some() {
-            Ok(())
-        } else {
-            cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
+            return Ok(());
+        }
+        #[cfg(target_os = "linux")]
+        if let Some(pid_fd) = self.pidfd.as_ref() {
+            // pidfd_send_signal predates pidfd_open. so if we were able to get an fd then sending signals will work too
+            return cvt(unsafe {
+                libc::syscall(
+                    libc::SYS_pidfd_send_signal,
+                    pid_fd.as_raw_fd(),
+                    libc::SIGKILL,
+                    crate::ptr::null::<()>(),
+                    0,
+                )
+            })
+            .map(drop);
         }
+        cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
     }
 
     pub fn wait(&mut self) -> io::Result<ExitStatus> {
@@ -827,6 +843,17 @@ impl Process {
         if let Some(status) = self.status {
             return Ok(status);
         }
+        #[cfg(target_os = "linux")]
+        if let Some(pid_fd) = self.pidfd.as_ref() {
+            let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() };
+
+            cvt_r(|| unsafe {
+                libc::waitid(libc::P_PIDFD, pid_fd.as_raw_fd() as u32, &mut siginfo, libc::WEXITED)
+            })?;
+            let status = ExitStatus::from_waitid_siginfo(siginfo);
+            self.status = Some(status);
+            return Ok(status);
+        }
         let mut status = 0 as c_int;
         cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
         self.status = Some(ExitStatus::new(status));
@@ -837,6 +864,25 @@ impl Process {
         if let Some(status) = self.status {
             return Ok(Some(status));
         }
+        #[cfg(target_os = "linux")]
+        if let Some(pid_fd) = self.pidfd.as_ref() {
+            let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() };
+
+            cvt(unsafe {
+                libc::waitid(
+                    libc::P_PIDFD,
+                    pid_fd.as_raw_fd() as u32,
+                    &mut siginfo,
+                    libc::WEXITED | libc::WNOHANG,
+                )
+            })?;
+            if unsafe { siginfo.si_pid() } == 0 {
+                return Ok(None);
+            }
+            let status = ExitStatus::from_waitid_siginfo(siginfo);
+            self.status = Some(status);
+            return Ok(Some(status));
+        }
         let mut status = 0 as c_int;
         let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?;
         if pid == 0 {
@@ -866,6 +912,20 @@ impl ExitStatus {
         ExitStatus(status)
     }
 
+    #[cfg(target_os = "linux")]
+    pub fn from_waitid_siginfo(siginfo: libc::siginfo_t) -> ExitStatus {
+        let status = unsafe { siginfo.si_status() };
+
+        match siginfo.si_code {
+            libc::CLD_EXITED => ExitStatus((status & 0xff) << 8),
+            libc::CLD_KILLED => ExitStatus(status),
+            libc::CLD_DUMPED => ExitStatus(status | 0x80),
+            libc::CLD_CONTINUED => ExitStatus(0xffff),
+            libc::CLD_STOPPED | libc::CLD_TRAPPED => ExitStatus(((status & 0xff) << 8) | 0x7f),
+            _ => unreachable!("waitid() should only return the above codes"),
+        }
+    }
+
     fn exited(&self) -> bool {
         libc::WIFEXITED(self.0)
     }
diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs
index 6aa79e7f9e7..6e952ed7c42 100644
--- a/library/std/src/sys/unix/process/process_unix/tests.rs
+++ b/library/std/src/sys/unix/process/process_unix/tests.rs
@@ -64,7 +64,8 @@ fn test_command_fork_no_unwind() {
 #[test]
 #[cfg(target_os = "linux")]
 fn test_command_pidfd() {
-    use crate::os::fd::RawFd;
+    use crate::assert_matches::assert_matches;
+    use crate::os::fd::{AsRawFd, RawFd};
     use crate::os::linux::process::{ChildExt, CommandExt};
     use crate::process::Command;
 
@@ -78,10 +79,22 @@ fn test_command_pidfd() {
     };
 
     // always exercise creation attempts
-    let child = Command::new("echo").create_pidfd(true).spawn().unwrap();
+    let mut child = Command::new("false").create_pidfd(true).spawn().unwrap();
 
     // but only check if we know that the kernel supports pidfds
     if pidfd_open_available {
-        assert!(child.pidfd().is_ok())
+        assert!(child.pidfd().is_ok());
     }
+    if let Ok(pidfd) = child.pidfd() {
+        let flags = super::cvt(unsafe { libc::fcntl(pidfd.as_raw_fd(), libc::F_GETFD) }).unwrap();
+        assert!(flags & libc::FD_CLOEXEC != 0);
+    }
+    let status = child.wait().expect("error waiting on pidfd");
+    assert_eq!(status.code(), Some(1));
+
+    let mut child = Command::new("sleep").arg("1000").create_pidfd(true).spawn().unwrap();
+    assert_matches!(child.try_wait(), Ok(None));
+    child.kill().expect("failed to kill child");
+    let status = child.wait().expect("error waiting on pidfd");
+    assert_eq!(status.signal(), Some(libc::SIGKILL));
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.rs
new file mode 100644
index 00000000000..a5777ebbb7f
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.rs
@@ -0,0 +1,9 @@
+#![feature(core_intrinsics)]
+use std::intrinsics;
+
+fn main() {
+    unsafe {
+        let _n = intrinsics::unchecked_shl(1i8, -1);
+        //~^ ERROR: overflowing shift by -1 in `unchecked_shl`
+    }
+}
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.stderr
new file mode 100644
index 00000000000..ab27c9fe911
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: overflowing shift by -1 in `unchecked_shl`
+  --> $DIR/unchecked_shl2.rs:LL:CC
+   |
+LL |         let _n = intrinsics::unchecked_shl(1i8, -1);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl`
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/unchecked_shl2.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-types/missing-associated-types.stderr b/tests/ui/associated-types/missing-associated-types.stderr
index e9669afe8c7..0636667ea1f 100644
--- a/tests/ui/associated-types/missing-associated-types.stderr
+++ b/tests/ui/associated-types/missing-associated-types.stderr
@@ -49,7 +49,7 @@ LL |     type B;
 LL | type Bar<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Z<Rhs>;
    |                     ^^^^^^^^   ^^^^^^^^   ^^^^^^   ^^^^^^ associated types `A`, `B`, `Output` must be specified
    |                     |          |          |
-   |                     |          |          associated types `Output` (from trait `Mul`), `Output` (from trait `Div`) must be specified
+   |                     |          |          associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified
    |                     |          associated type `Output` must be specified
    |                     associated type `Output` must be specified
    |
@@ -119,7 +119,7 @@ error[E0191]: the value of the associated types `Output` in `Div`, `Output` in `
   --> $DIR/missing-associated-types.rs:24:21
    |
 LL | type Bal<Rhs> = dyn X<Rhs>;
-   |                     ^^^^^^ associated types `Output` (from trait `Mul`), `Output` (from trait `Div`) must be specified
+   |                     ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified
    |
    = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types
 
diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.rs b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.rs
new file mode 100644
index 00000000000..5d8beb45132
--- /dev/null
+++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.rs
@@ -0,0 +1,14 @@
+#![feature(negative_impls)]
+#![feature(with_negative_coherence)]
+
+struct Wrap<T>(T);
+
+trait Foo {}
+impl<T: 'static> !Foo for Box<T> {}
+
+trait Bar {}
+impl<T> Bar for T where T: Foo {}
+impl<T> Bar for Box<T> {}
+//~^ ERROR conflicting implementations of trait `Bar` for type `Box<_>`
+
+fn main() {}
diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
new file mode 100644
index 00000000000..52d36c92f99
--- /dev/null
+++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `Bar` for type `Box<_>`
+  --> $DIR/negative-coherence-check-placeholder-outlives.rs:11:1
+   |
+LL | impl<T> Bar for T where T: Foo {}
+   | ------------------------------ first implementation here
+LL | impl<T> Bar for Box<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
new file mode 100644
index 00000000000..34f3904443c
--- /dev/null
+++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
@@ -0,0 +1,19 @@
+error: conflicting implementations of trait `FnMarker` for type `fn(&_)`
+  --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:21:1
+   |
+LL | impl<T: ?Sized + Marker> FnMarker for fn(T) {}
+   | ------------------------------------------- first implementation here
+LL | impl<T: ?Sized> FnMarker for fn(&T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&_)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
+   = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
+note: the lint level is defined here
+  --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11
+   |
+LL | #![forbid(coherence_leak_check)]
+   |           ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs
new file mode 100644
index 00000000000..26d9d84d8f0
--- /dev/null
+++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs
@@ -0,0 +1,25 @@
+// revisions: explicit implicit
+//[implicit] check-pass
+
+#![forbid(coherence_leak_check)]
+#![feature(negative_impls, with_negative_coherence)]
+
+pub trait Marker {}
+
+#[cfg(implicit)]
+impl<T: ?Sized> !Marker for &T {}
+
+#[cfg(explicit)]
+impl<'a, T: ?Sized + 'a> !Marker for &'a T {}
+
+trait FnMarker {}
+
+// Unifying these two impls below results in a `T: '!0` obligation
+// that we shouldn't need to care about. Ideally, we'd treat that
+// as an assumption when proving `&'!0 T: Marker`...
+impl<T: ?Sized + Marker> FnMarker for fn(T) {}
+impl<T: ?Sized> FnMarker for fn(&T) {}
+//[explicit]~^ ERROR conflicting implementations of trait `FnMarker` for type `fn(&_)`
+//[explicit]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+fn main() {}
diff --git a/tests/ui/consts/const-int-unchecked.stderr b/tests/ui/consts/const-int-unchecked.stderr
index ad880d56d90..ad14c8f68f8 100644
--- a/tests/ui/consts/const-int-unchecked.stderr
+++ b/tests/ui/consts/const-int-unchecked.stderr
@@ -62,61 +62,61 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:41:33
    |
 LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shl`
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:43:35
    |
 LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shl`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:45:35
    |
 LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shl`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:47:35
    |
 LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shl`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:49:37
    |
 LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:55:40
    |
 LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shl`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -6 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:57:42
    |
 LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shl`
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:59:42
    |
 LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shl`
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -25 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:61:42
    |
 LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shl`
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -30 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:63:44
    |
 LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
-   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -93 in `unchecked_shl`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:70:29
@@ -182,61 +182,61 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:96:33
    |
 LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shr`
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:98:35
    |
 LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shr`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:100:35
    |
 LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shr`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:102:35
    |
 LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shr`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:104:37
    |
 LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:110:40
    |
 LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shr`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -6 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:112:42
    |
 LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shr`
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:114:42
    |
 LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shr`
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -25 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:116:42
    |
 LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shr`
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -30 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:118:44
    |
 LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
-   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -93 in `unchecked_shr`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:123:25
diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
new file mode 100644
index 00000000000..d97f24a3d29
--- /dev/null
+++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
@@ -0,0 +1,19 @@
+#![feature(stmt_expr_attributes)]
+
+fn foo() -> String {
+    #[cfg(feature = "validation")]
+    [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() //~ ERROR expected `;`, found `#`
+    #[cfg(not(feature = "validation"))]
+    String::new()
+}
+
+fn bar() -> String {
+    #[attr]
+    [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() //~ ERROR expected `;`, found `#`
+    #[attr] //~ ERROR cannot find attribute `attr` in this scope
+    String::new()
+}
+
+fn main() {
+    println!("{}", foo());
+}
diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
new file mode 100644
index 00000000000..a71253a5e42
--- /dev/null
+++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
@@ -0,0 +1,54 @@
+error: expected `;`, found `#`
+  --> $DIR/multiple-tail-expr-behind-cfg.rs:5:64
+   |
+LL |     #[cfg(feature = "validation")]
+   |     ------------------------------ only `;` terminated statements or tail expressions are allowed after this attribute
+LL |     [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>()
+   |                                                                ^ expected `;` here
+LL |     #[cfg(not(feature = "validation"))]
+   |     - unexpected token
+   |
+help: add `;` here
+   |
+LL |     [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>();
+   |                                                                +
+help: alternatively, consider surrounding the expression with a block
+   |
+LL |     { [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() }
+   |     +                                                             +
+help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)`
+   |
+LL ~     if cfg!(feature = "validation") {
+LL ~         [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>()
+LL ~     } else if cfg!(not(feature = "validation")) {
+LL ~         String::new()
+LL +     }
+   |
+
+error: expected `;`, found `#`
+  --> $DIR/multiple-tail-expr-behind-cfg.rs:12:64
+   |
+LL |     #[attr]
+   |     ------- only `;` terminated statements or tail expressions are allowed after this attribute
+LL |     [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>()
+   |                                                                ^ expected `;` here
+LL |     #[attr]
+   |     - unexpected token
+   |
+help: add `;` here
+   |
+LL |     [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>();
+   |                                                                +
+help: alternatively, consider surrounding the expression with a block
+   |
+LL |     { [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() }
+   |     +                                                             +
+
+error: cannot find attribute `attr` in this scope
+  --> $DIR/multiple-tail-expr-behind-cfg.rs:13:7
+   |
+LL |     #[attr]
+   |       ^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs
new file mode 100644
index 00000000000..fe363a6887f
--- /dev/null
+++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs
@@ -0,0 +1,9 @@
+trait Trait {}
+
+fn test(_: &for<'a> dyn Trait) {}
+//~^ ERROR `for<...>` expected after `dyn`, not before
+
+fn test2(_: for<'a> impl Trait) {}
+//~^ ERROR `for<...>` expected after `impl`, not before
+
+fn main() {}
diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr
new file mode 100644
index 00000000000..6fc1259b910
--- /dev/null
+++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr
@@ -0,0 +1,26 @@
+error: `for<...>` expected after `dyn`, not before
+  --> $DIR/recover-hrtb-before-dyn-impl-kw.rs:3:21
+   |
+LL | fn test(_: &for<'a> dyn Trait) {}
+   |                     ^^^
+   |
+help: move `dyn` before the `for<...>`
+   |
+LL - fn test(_: &for<'a> dyn Trait) {}
+LL + fn test(_: &dyn for<'a> Trait) {}
+   |
+
+error: `for<...>` expected after `impl`, not before
+  --> $DIR/recover-hrtb-before-dyn-impl-kw.rs:6:21
+   |
+LL | fn test2(_: for<'a> impl Trait) {}
+   |                     ^^^^
+   |
+help: move `impl` before the `for<...>`
+   |
+LL - fn test2(_: for<'a> impl Trait) {}
+LL + fn test2(_: impl for<'a> Trait) {}
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr
new file mode 100644
index 00000000000..e6c36129b28
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr
@@ -0,0 +1,26 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/placeholders-dont-outlive-static.rs:6:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0310]: the placeholder type `!1_"T"` may not live long enough
+  --> $DIR/placeholders-dont-outlive-static.rs:13:5
+   |
+LL |     foo();
+   |     ^^^^^
+   |     |
+   |     the placeholder type `!1_"T"` must be valid for the static lifetime...
+   |     ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | fn bad() where !1_"T": 'static {
+   |          +++++++++++++++++++++
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr
new file mode 100644
index 00000000000..31441ef4db8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr
@@ -0,0 +1,26 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/placeholders-dont-outlive-static.rs:6:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0310]: the placeholder type `!1_"T"` may not live long enough
+  --> $DIR/placeholders-dont-outlive-static.rs:19:5
+   |
+LL |     foo();
+   |     ^^^^^
+   |     |
+   |     the placeholder type `!1_"T"` must be valid for the static lifetime...
+   |     ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | fn good() where for<T> T: 'static, !1_"T": 'static {
+   |                                  +++++++++++++++++
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs
new file mode 100644
index 00000000000..ae6866511e2
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs
@@ -0,0 +1,22 @@
+// revisions: good bad
+
+//[good] known-bug: unknown
+// `for<T> T: 'static` doesn't imply itself when processing outlives obligations
+
+#![feature(non_lifetime_binders)]
+//[bad]~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn foo() where for<T> T: 'static {}
+
+#[cfg(bad)]
+fn bad() {
+    foo();
+    //[bad]~^ ERROR the placeholder type `!1_"T"` may not live long enough
+}
+
+#[cfg(good)]
+fn good() where for<T> T: 'static {
+    foo();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs
index 5ff7089b993..53957914e3a 100644
--- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs
+++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs
@@ -1,10 +1,9 @@
 // edition:2021
-// check-pass
+// known-bug: unknown
 
 // Checks that test_type_match code doesn't ICE when predicates have late-bound types
 
 #![feature(non_lifetime_binders)]
-//~^ WARN is incomplete and may not be safe to use
 
 async fn walk2<'a, T: 'a>(_: T)
 where
diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
index 3609bed28df..ddb6a798711 100644
--- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
+++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
@@ -7,5 +7,20 @@ LL | #![feature(non_lifetime_binders)]
    = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-warning: 1 warning emitted
+error[E0309]: the placeholder type `!1_"F"` may not live long enough
+  --> $DIR/type-match-with-late-bound.rs:11:1
+   |
+LL | async fn walk2<'a, T: 'a>(_: T)
+   |                -- the placeholder type `!1_"F"` must be valid for the lifetime `'a` as defined here...
+...
+LL | {}
+   | ^^ ...so that the type `F` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     for<F> F: 'a, !1_"F": 'a
+   |                 ~~~~~~~~~~~~
+
+error: aborting due to previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0309`.