about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/assembly/targets/targets-elf.rs15
-rw-r--r--tests/assembly/wasm32-naked-fn.rs199
-rw-r--r--tests/run-make/jobserver-error/Makefile17
-rw-r--r--tests/run-make/jobserver-error/cannot_open_fd.stderr2
-rw-r--r--tests/run-make/jobserver-error/rmake.rs47
-rw-r--r--tests/rustdoc-json/auxiliary/defines_and_reexports.rs10
-rw-r--r--tests/rustdoc-json/blanket_impls.rs2
-rw-r--r--tests/rustdoc-json/fns/async_return.rs4
-rw-r--r--tests/rustdoc-json/impl-trait-in-assoc-type.rs2
-rw-r--r--tests/rustdoc-json/path_name.rs83
-rw-r--r--tests/rustdoc-json/return_private.rs4
-rw-r--r--tests/rustdoc-json/type/dyn.rs14
-rw-r--r--tests/rustdoc-json/type/generic_default.rs4
-rw-r--r--tests/rustdoc-json/type/hrtb.rs2
-rw-r--r--tests/ui-fulldeps/compiler-calls.rs2
-rw-r--r--tests/ui-fulldeps/obtain-borrowck.rs2
-rw-r--r--tests/ui-fulldeps/run-compiler-twice.rs2
-rw-r--r--tests/ui/associated-types/associated-types-in-ambiguous-context.stderr8
-rw-r--r--tests/ui/async-await/coroutine-desc.stderr1
-rw-r--r--tests/ui/async-await/dont-suggest-missing-await.stderr9
-rw-r--r--tests/ui/consts/too_generic_eval_ice.stderr10
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs29
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs29
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs29
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr4
-rw-r--r--tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr4
-rw-r--r--tests/ui/drop/drop-order-comparisons.e2021.fixed575
-rw-r--r--tests/ui/drop/drop-order-comparisons.e2021.stderr477
-rw-r--r--tests/ui/drop/drop-order-comparisons.rs575
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs8
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr32
-rw-r--r--tests/ui/impl-trait/issue-102605.stderr9
-rw-r--r--tests/ui/inference/issue-72616.stderr13
-rw-r--r--tests/ui/inference/issue-72690.stderr9
-rw-r--r--tests/ui/intrinsics/reify-intrinsic.rs6
-rw-r--r--tests/ui/intrinsics/reify-intrinsic.stderr16
-rw-r--r--tests/ui/layout/reprc-power-alignment.rs152
-rw-r--r--tests/ui/layout/reprc-power-alignment.stderr112
-rw-r--r--tests/ui/lint/clashing-extern-fn.rs1
-rw-r--r--tests/ui/lint/clashing-extern-fn.stderr22
-rw-r--r--tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.rs51
-rw-r--r--tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.stderr135
-rw-r--r--tests/ui/suggestions/issue-109195.rs20
-rw-r--r--tests/ui/suggestions/issue-109195.stderr69
-rw-r--r--tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs17
-rw-r--r--tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr39
-rw-r--r--tests/ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs21
59 files changed, 2741 insertions, 200 deletions
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index acfa868c2df..6bb3389c409 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -66,6 +66,9 @@
 //@ revisions: aarch64_unknown_teeos
 //@ [aarch64_unknown_teeos] compile-flags: --target aarch64-unknown-teeos
 //@ [aarch64_unknown_teeos] needs-llvm-components: aarch64
+//@ revisions: aarch64_unknown_nuttx
+//@ [aarch64_unknown_nuttx] compile-flags: --target aarch64-unknown-nuttx
+//@ [aarch64_unknown_nuttx] needs-llvm-components: aarch64
 //@ revisions: aarch64_unknown_trusty
 //@ [aarch64_unknown_trusty] compile-flags: --target aarch64-unknown-trusty
 //@ [aarch64_unknown_trusty] needs-llvm-components: aarch64
@@ -177,6 +180,12 @@
 //@ revisions: armv7a_none_eabihf
 //@ [armv7a_none_eabihf] compile-flags: --target armv7a-none-eabihf
 //@ [armv7a_none_eabihf] needs-llvm-components: arm
+//@ revisions: armv7a_nuttx_eabi
+//@ [armv7a_nuttx_eabi] compile-flags: --target armv7a-nuttx-eabi
+//@ [armv7a_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: armv7a_nuttx_eabihf
+//@ [armv7a_nuttx_eabihf] compile-flags: --target armv7a-nuttx-eabihf
+//@ [armv7a_nuttx_eabihf] needs-llvm-components: arm
 //@ revisions: armv7r_none_eabi
 //@ [armv7r_none_eabi] compile-flags: --target armv7r-none-eabi
 //@ [armv7r_none_eabi] needs-llvm-components: arm
@@ -621,6 +630,12 @@
 //@ revisions: thumbv6m_nuttx_eabi
 //@ [thumbv6m_nuttx_eabi] compile-flags: --target thumbv6m-nuttx-eabi
 //@ [thumbv6m_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7a_nuttx_eabi
+//@ [thumbv7a_nuttx_eabi] compile-flags: --target thumbv7a-nuttx-eabi
+//@ [thumbv7a_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7a_nuttx_eabihf
+//@ [thumbv7a_nuttx_eabihf] compile-flags: --target thumbv7a-nuttx-eabihf
+//@ [thumbv7a_nuttx_eabihf] needs-llvm-components: arm
 //@ revisions: thumbv7m_nuttx_eabi
 //@ [thumbv7m_nuttx_eabi] compile-flags: --target thumbv7m-nuttx-eabi
 //@ [thumbv7m_nuttx_eabi] needs-llvm-components: arm
diff --git a/tests/assembly/wasm32-naked-fn.rs b/tests/assembly/wasm32-naked-fn.rs
new file mode 100644
index 00000000000..4911a6bd08f
--- /dev/null
+++ b/tests/assembly/wasm32-naked-fn.rs
@@ -0,0 +1,199 @@
+// FIXME: add wasm32-unknown when the wasm32-unknown-unknown ABI is fixed
+// see https://github.com/rust-lang/rust/issues/115666
+//@ revisions: wasm64-unknown wasm32-wasip1
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown
+//@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1
+//@ [wasm64-unknown] needs-llvm-components: webassembly
+//@ [wasm32-wasip1] needs-llvm-components: webassembly
+
+#![crate_type = "lib"]
+#![feature(no_core, naked_functions, asm_experimental_arch, f128, linkage, fn_align)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK: .section  .text.nop,"",@
+// CHECK: .globl nop
+// CHECK-LABEL: nop:
+// CHECK: .functype nop () -> ()
+// CHECK-NOT: .size
+// CHECK: end_function
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn nop() {
+    naked_asm!("nop")
+}
+
+// CHECK: .section  .text.weak_aligned_nop,"",@
+// CHECK: .weak weak_aligned_nop
+// CHECK-LABEL: nop:
+// CHECK: .functype weak_aligned_nop () -> ()
+// CHECK-NOT: .size
+// CHECK: end_function
+#[no_mangle]
+#[naked]
+#[linkage = "weak"]
+// wasm functions cannot be aligned, so this has no effect
+#[repr(align(32))]
+unsafe extern "C" fn weak_aligned_nop() {
+    naked_asm!("nop")
+}
+
+// CHECK-LABEL: fn_i8_i8:
+// CHECK-NEXT: .functype fn_i8_i8 (i32) -> (i32)
+//
+// CHECK-NEXT: local.get 0
+// CHECK-NEXT: local.get 0
+// CHECK-NEXT: i32.mul
+//
+// CHECK-NEXT: end_function
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_i8_i8(num: i8) -> i8 {
+    naked_asm!("local.get 0", "local.get 0", "i32.mul")
+}
+
+// CHECK-LABEL: fn_i8_i8_i8:
+// CHECK: .functype fn_i8_i8_i8 (i32, i32) -> (i32)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_i8_i8_i8(a: i8, b: i8) -> i8 {
+    naked_asm!("local.get 1", "local.get 0", "i32.mul")
+}
+
+// CHECK-LABEL: fn_unit_i8:
+// CHECK: .functype fn_unit_i8 () -> (i32)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_unit_i8() -> i8 {
+    naked_asm!("i32.const 42")
+}
+
+// CHECK-LABEL: fn_i8_unit:
+// CHECK: .functype fn_i8_unit (i32) -> ()
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_i8_unit(_: i8) {
+    naked_asm!("nop")
+}
+
+// CHECK-LABEL: fn_i32_i32:
+// CHECK: .functype fn_i32_i32 (i32) -> (i32)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_i32_i32(num: i32) -> i32 {
+    naked_asm!("local.get 0", "local.get 0", "i32.mul")
+}
+
+// CHECK-LABEL: fn_i64_i64:
+// CHECK: .functype fn_i64_i64 (i64) -> (i64)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_i64_i64(num: i64) -> i64 {
+    naked_asm!("local.get 0", "local.get 0", "i64.mul")
+}
+
+// CHECK-LABEL: fn_i128_i128:
+// wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> ()
+// wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> ()
+#[allow(improper_ctypes_definitions)]
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_i128_i128(num: i128) -> i128 {
+    naked_asm!(
+        "local.get       0",
+        "local.get       2",
+        "i64.store       8",
+        "local.get       0",
+        "local.get       1",
+        "i64.store       0",
+    )
+}
+
+// CHECK-LABEL: fn_f128_f128:
+// wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> ()
+// wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> ()
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_f128_f128(num: f128) -> f128 {
+    naked_asm!(
+        "local.get       0",
+        "local.get       2",
+        "i64.store       8",
+        "local.get       0",
+        "local.get       1",
+        "i64.store       0",
+    )
+}
+
+#[repr(C)]
+struct Compound {
+    a: u16,
+    b: i64,
+}
+
+// CHECK-LABEL: fn_compound_compound:
+// wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> ()
+// wasm64-unknown: .functype fn_compound_compound (i64, i64) -> ()
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_compound_compound(_: Compound) -> Compound {
+    // this is the wasm32-wasip1 assembly
+    naked_asm!(
+        "local.get       0",
+        "local.get       1",
+        "i64.load        8",
+        "i64.store       8",
+        "local.get       0",
+        "local.get       1",
+        "i32.load16_u    0",
+        "i32.store16     0",
+    )
+}
+
+#[repr(C)]
+struct WrapperI32(i32);
+
+// CHECK-LABEL: fn_wrapperi32_wrapperi32:
+// CHECK: .functype fn_wrapperi32_wrapperi32 (i32) -> (i32)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_wrapperi32_wrapperi32(_: WrapperI32) -> WrapperI32 {
+    naked_asm!("local.get       0")
+}
+
+#[repr(C)]
+struct WrapperI64(i64);
+
+// CHECK-LABEL: fn_wrapperi64_wrapperi64:
+// CHECK: .functype fn_wrapperi64_wrapperi64 (i64) -> (i64)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_wrapperi64_wrapperi64(_: WrapperI64) -> WrapperI64 {
+    naked_asm!("local.get       0")
+}
+
+#[repr(C)]
+struct WrapperF32(f32);
+
+// CHECK-LABEL: fn_wrapperf32_wrapperf32:
+// CHECK: .functype fn_wrapperf32_wrapperf32 (f32) -> (f32)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_wrapperf32_wrapperf32(_: WrapperF32) -> WrapperF32 {
+    naked_asm!("local.get       0")
+}
+
+#[repr(C)]
+struct WrapperF64(f64);
+
+// CHECK-LABEL: fn_wrapperf64_wrapperf64:
+// CHECK: .functype fn_wrapperf64_wrapperf64 (f64) -> (f64)
+#[no_mangle]
+#[naked]
+unsafe extern "C" fn fn_wrapperf64_wrapperf64(_: WrapperF64) -> WrapperF64 {
+    naked_asm!("local.get       0")
+}
diff --git a/tests/run-make/jobserver-error/Makefile b/tests/run-make/jobserver-error/Makefile
deleted file mode 100644
index 9f34970f96f..00000000000
--- a/tests/run-make/jobserver-error/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-include ../tools.mk
-
-# only-linux
-# ignore-cross-compile
-
-# Test compiler behavior in case environment specifies wrong jobserver.
-# Note that by default, the compiler uses file descriptors 0 (stdin), 1 (stdout), 2 (stderr),
-# but also 3 and 4 for either end of the ctrl-c signal handler self-pipe.
-
-all:
-	bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=5,5" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr -
-	bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff not_a_pipe.stderr -
-
-# This test randomly fails, see https://github.com/rust-lang/rust/issues/110321
-disabled:
-	bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3< <(cat /dev/null)' 2>&1 | diff poisoned_pipe.stderr -
-
diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr
index 9ac4c1c58f7..d075057b3d3 100644
--- a/tests/run-make/jobserver-error/cannot_open_fd.stderr
+++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr
@@ -1,4 +1,4 @@
-warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=5,5"`: cannot open file descriptor 5 from the jobserver environment variable value: Bad file descriptor (os error 9)
+warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=1000,1000"`: cannot open file descriptor 1000 from the jobserver environment variable value: Bad file descriptor (os error 9)
   |
   = note: the build environment is likely misconfigured
 
diff --git a/tests/run-make/jobserver-error/rmake.rs b/tests/run-make/jobserver-error/rmake.rs
new file mode 100644
index 00000000000..14ee24c7148
--- /dev/null
+++ b/tests/run-make/jobserver-error/rmake.rs
@@ -0,0 +1,47 @@
+// ignore-tidy-linelength
+//! If the environment variables contain an invalid `jobserver-auth`, this used to cause an ICE
+//! until this was fixed in [do not panic on failure to acquire jobserver token
+//! #109694](https://github.com/rust-lang/rust/pull/109694).
+//!
+//! Proper handling has been added, and this test checks that helpful warnings and errors are
+//! printed instead in case of a wrong jobserver. See
+//! <https://github.com/rust-lang/rust/issues/46981>.
+
+//@ only-linux
+//@ ignore-cross-compile
+
+#![deny(warnings)]
+
+use run_make_support::{diff, rustc};
+
+fn main() {
+    let out = rustc()
+        .stdin_buf(("fn main() {}").as_bytes())
+        .env("MAKEFLAGS", "--jobserver-auth=1000,1000")
+        .run_fail()
+        .stderr_utf8();
+    diff().expected_file("cannot_open_fd.stderr").actual_text("actual", out).run();
+
+    let out = rustc()
+        .stdin_buf(("fn main() {}").as_bytes())
+        .input("-")
+        .env("MAKEFLAGS", "--jobserver-auth=3,3")
+        .set_aux_fd(3, std::fs::File::open("/dev/null").unwrap())
+        .run()
+        .stderr_utf8();
+    diff().expected_file("not_a_pipe.stderr").actual_text("actual", out).run();
+
+    // FIXME(#110321): the Makefile version had a disabled check:
+    //
+    // ```makefile
+    // bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3< <(cat /dev/null)' 2>&1 | diff poisoned_pipe.stderr -
+    // ```
+    //
+    // > the jobserver helper thread launched here gets starved out and doesn't run, while the
+    // > coordinator thread continually processes work using the implicit jobserver token, never
+    // > yielding long enough for the jobserver helper to do its work (and process the error).
+    //
+    // but is not necessarily worth fixing as it might require changing coordinator behavior that
+    // might regress performance. See discussion at
+    // <https://github.com/rust-lang/rust/issues/110321#issuecomment-1636914956>.
+}
diff --git a/tests/rustdoc-json/auxiliary/defines_and_reexports.rs b/tests/rustdoc-json/auxiliary/defines_and_reexports.rs
new file mode 100644
index 00000000000..72434ef152f
--- /dev/null
+++ b/tests/rustdoc-json/auxiliary/defines_and_reexports.rs
@@ -0,0 +1,10 @@
+pub mod m1 {
+    pub struct InPubMod;
+}
+
+mod m2 {
+    pub struct InPrivMod;
+}
+
+pub use m1::{InPubMod, InPubMod as InPubMod2};
+pub use m2::{InPrivMod, InPrivMod as InPrivMod2};
diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs
index f2acabbe372..bf0983e66a1 100644
--- a/tests/rustdoc-json/blanket_impls.rs
+++ b/tests/rustdoc-json/blanket_impls.rs
@@ -4,5 +4,5 @@
 
 //@ has "$.index[*][?(@.name=='Error')].inner.assoc_type"
 //@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path"
-//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.name" \"Infallible\"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\"
 pub struct ForBlanketTryFromImpl;
diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs
index 18a8a586e76..ff88fa99c61 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -17,7 +17,7 @@ pub async fn get_int_async() -> i32 {
     42
 }
 
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
 //@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
 //@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive"  \"i32\"
 //@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false
@@ -25,7 +25,7 @@ pub fn get_int_future() -> impl Future<Output = i32> {
     async { 42 }
 }
 
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
 //@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
 //@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
 //@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true
diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
index 907a0f6c603..14ea2950769 100644
--- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs
+++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
@@ -10,7 +10,7 @@ impl IntoIterator for AlwaysTrue {
     type Item = bool;
 
     //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1
-    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.name' '"Iterator"'
+    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.path' '"Iterator"'
     //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1
     //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"'
     //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"'
diff --git a/tests/rustdoc-json/path_name.rs b/tests/rustdoc-json/path_name.rs
new file mode 100644
index 00000000000..67843dfc8ff
--- /dev/null
+++ b/tests/rustdoc-json/path_name.rs
@@ -0,0 +1,83 @@
+// Test for the Path::name field within a single crate.
+//
+// See https://github.com/rust-lang/rust/issues/135600
+// and https://github.com/rust-lang/rust/pull/134880#issuecomment-2596386111
+//
+// ignore-tidy-linelength
+//@ aux-build: defines_and_reexports.rs
+extern crate defines_and_reexports;
+
+mod priv_mod {
+    pub struct InPrivMod;
+}
+
+pub mod pub_mod {
+    pub struct InPubMod;
+}
+
+use priv_mod::InPrivMod as InPrivMod3;
+pub use priv_mod::{InPrivMod, InPrivMod as InPrivMod2};
+use pub_mod::InPubMod as InPubMod3;
+pub use pub_mod::{InPubMod, InPubMod as InPubMod2};
+
+//@ is "$.index[*][?(@.name=='T0')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
+pub type T0 = priv_mod::InPrivMod;
+//@ is "$.index[*][?(@.name=='T1')].inner.type_alias.type.resolved_path.path" '"InPrivMod"'
+pub type T1 = InPrivMod;
+//@ is "$.index[*][?(@.name=='T2')].inner.type_alias.type.resolved_path.path" '"InPrivMod2"'
+pub type T2 = InPrivMod2;
+//@ is "$.index[*][?(@.name=='T3')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
+pub type T3 = InPrivMod3;
+
+//@ is "$.index[*][?(@.name=='U0')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
+pub type U0 = pub_mod::InPubMod;
+//@ is "$.index[*][?(@.name=='U1')].inner.type_alias.type.resolved_path.path" '"InPubMod"'
+pub type U1 = InPubMod;
+//@ is "$.index[*][?(@.name=='U2')].inner.type_alias.type.resolved_path.path" '"InPubMod2"'
+pub type U2 = InPubMod2;
+//@ is "$.index[*][?(@.name=='U3')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
+pub type U3 = InPubMod3;
+
+// Check we only have paths for structs at their original path
+//@ ismany "$.paths[*][?(@.crate_id==0 && @.kind=='struct')].path" '["path_name", "priv_mod", "InPrivMod"]' '["path_name", "pub_mod", "InPubMod"]'
+
+pub use defines_and_reexports::{InPrivMod as XPrivMod, InPubMod as XPubMod};
+use defines_and_reexports::{InPrivMod as XPrivMod2, InPubMod as XPubMod2};
+
+//@ is "$.index[*][?(@.name=='X0')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::m1::InPubMod"'
+pub type X0 = defines_and_reexports::m1::InPubMod;
+//@ is "$.index[*][?(@.name=='X1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
+pub type X1 = defines_and_reexports::InPubMod;
+//@ is "$.index[*][?(@.name=='X2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod2"'
+pub type X2 = defines_and_reexports::InPubMod2;
+//@ is "$.index[*][?(@.name=='X3')].inner.type_alias.type.resolved_path.path" '"XPubMod"'
+pub type X3 = XPubMod;
+// N.B. This isn't the path as used *or* the original path!
+//@ is "$.index[*][?(@.name=='X4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
+pub type X4 = XPubMod2;
+
+//@ is "$.index[*][?(@.name=='Y1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
+pub type Y1 = defines_and_reexports::InPrivMod;
+//@ is "$.index[*][?(@.name=='Y2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod2"'
+pub type Y2 = defines_and_reexports::InPrivMod2;
+//@ is "$.index[*][?(@.name=='Y3')].inner.type_alias.type.resolved_path.path" '"XPrivMod"'
+pub type Y3 = XPrivMod;
+//@ is "$.index[*][?(@.name=='Y4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
+pub type Y4 = XPrivMod2;
+
+// For foreign items, $.paths contains the *origional* path, even if it's not publicly
+// assessable. This should probably be changed.
+
+//@ has "$.paths[*].path" '["defines_and_reexports", "m1", "InPubMod"]'
+//@ has "$.paths[*].path" '["defines_and_reexports", "m2", "InPrivMod"]'
+//@ !has "$.paths[*].path" '["defines_and_reexports", "InPubMod"]'
+//@ !has "$.paths[*].path" '["defines_and_reexports", "InPrivMod"]'
+
+// Tests for the example in the docs of Path::name.
+// If these change, chage the docs.
+//@ is "$.index[*][?(@.name=='Vec1')].inner.type_alias.type.resolved_path.path" '"std::vec::Vec"'
+pub type Vec1 = std::vec::Vec<i32>;
+//@ is "$.index[*][?(@.name=='Vec2')].inner.type_alias.type.resolved_path.path" '"Vec"'
+pub type Vec2 = Vec<i32>;
+//@ is "$.index[*][?(@.name=='Vec3')].inner.type_alias.type.resolved_path.path" '"std::prelude::v1::Vec"'
+pub type Vec3 = std::prelude::v1::Vec<i32>;
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index c238a536e0d..bfcbed89040 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -2,11 +2,13 @@
 // ignore-tidy-linelength
 
 mod secret {
+    //@ set struct_secret = "$.index[*][?(@.name == 'Secret' && @.inner.struct)].id"
     pub struct Secret;
 }
 
 //@ has "$.index[*][?(@.name=='get_secret')].inner.function"
-//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.name" \"Secret\"
+//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.path" '"secret::Secret"'
+//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.id" $struct_secret
 pub fn get_secret() -> secret::Secret {
     secret::Secret
 }
diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs
index 97c8689a7c8..f990a2cb53a 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -10,7 +10,7 @@ use std::fmt::Debug;
 //@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias"
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}'
 //@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path"
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\"
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.path" \"Box\"
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
 //@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1
 //@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
@@ -19,9 +19,9 @@ use std::fmt::Debug;
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" []
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" []
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" []
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"'
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"'
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"'
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Fn"'
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Send"'
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.path" '"Sync"'
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}'
 pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
 
@@ -34,13 +34,13 @@ pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null
 //@ count "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1
 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"'
 //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref"
 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\""
 //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref"
 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\""
 pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
 
-//@ is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"'
-//@ is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"'
+//@ is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Send"'
+//@ is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Debug"'
 pub type WeirdOrder = Box<dyn Send + Debug>;
diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs
index c1a05805014..7eaa299af5c 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -21,10 +21,10 @@ pub struct MyError {}
 //@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null
 //@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path"
 //@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error
-//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.name" \"MyError\"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.path" \"MyError\"
 //@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path"
 //@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result
-//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.path" \"Result\"
 //@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
 //@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic"
 //@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic"
diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs
index 825720e9198..e71d9fc1e1e 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -15,7 +15,7 @@ where
 //@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
 //@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
 //@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"'
 pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
     let zero = 0;
     f(&zero, &zero);
diff --git a/tests/ui-fulldeps/compiler-calls.rs b/tests/ui-fulldeps/compiler-calls.rs
index 5fb47c87e50..d6148dfec43 100644
--- a/tests/ui-fulldeps/compiler-calls.rs
+++ b/tests/ui-fulldeps/compiler-calls.rs
@@ -25,7 +25,7 @@ fn main() {
     let mut count = 1;
     let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
     rustc_driver::catch_fatal_errors(|| -> interface::Result<()> {
-        rustc_driver::RunCompiler::new(&args, &mut TestCalls { count: &mut count }).run();
+        rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count });
         Ok(())
     })
     .ok();
diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs
index 8ea2ac61971..f8064c245a8 100644
--- a/tests/ui-fulldeps/obtain-borrowck.rs
+++ b/tests/ui-fulldeps/obtain-borrowck.rs
@@ -47,7 +47,7 @@ fn main() {
         rustc_args.push("-Zpolonius".to_owned());
         let mut callbacks = CompilerCalls::default();
         // Call the Rust compiler with our callbacks.
-        rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks).run();
+        rustc_driver::run_compiler(&rustc_args, &mut callbacks);
         Ok(())
     });
     std::process::exit(exit_code);
diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs
index bcc235e58ed..f414c961627 100644
--- a/tests/ui-fulldeps/run-compiler-twice.rs
+++ b/tests/ui-fulldeps/run-compiler-twice.rs
@@ -72,7 +72,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path
         override_queries: None,
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
-        using_internal_features: std::sync::Arc::default(),
+        using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES,
         expanded_args: Default::default(),
     };
 
diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
index c5260adbed4..88db3611719 100644
--- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
+++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -40,14 +40,14 @@ LL | type X = std::ops::Deref::Target;
    |
 help: use fully-qualified syntax
    |
+LL | type X = <ByteStr as Deref>::Target;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | type X = <ByteString as Deref>::Target;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL | type X = <CString as Deref>::Target;
    |          ~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL | type X = <IoSlice<'_> as Deref>::Target;
    |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL | type X = <IoSliceMut<'_> as Deref>::Target;
-   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL | type X = <OsString as Deref>::Target;
-   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      and N other candidates
 
 error: aborting due to 5 previous errors
diff --git a/tests/ui/async-await/coroutine-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr
index 01482a9cb1f..84a1a3166ad 100644
--- a/tests/ui/async-await/coroutine-desc.stderr
+++ b/tests/ui/async-await/coroutine-desc.stderr
@@ -30,7 +30,6 @@ LL |     fun(one(), two());
    |     |   expected all arguments to be this future type because they need to match the type of this parameter
    |     arguments to this function are incorrect
    |
-   = help: consider `await`ing on both `Future`s
    = note: distinct uses of `impl Trait` result in different opaque types
 note: function defined here
   --> $DIR/coroutine-desc.rs:7:4
diff --git a/tests/ui/async-await/dont-suggest-missing-await.stderr b/tests/ui/async-await/dont-suggest-missing-await.stderr
index 45a226c31f8..2ca52b2d5f5 100644
--- a/tests/ui/async-await/dont-suggest-missing-await.stderr
+++ b/tests/ui/async-await/dont-suggest-missing-await.stderr
@@ -6,20 +6,11 @@ LL |         take_u32(x)
    |         |
    |         arguments to this function are incorrect
    |
-note: calling an async function returns a future
-  --> $DIR/dont-suggest-missing-await.rs:14:18
-   |
-LL |         take_u32(x)
-   |                  ^
 note: function defined here
   --> $DIR/dont-suggest-missing-await.rs:5:4
    |
 LL | fn take_u32(x: u32) {}
    |    ^^^^^^^^ ------
-help: consider `await`ing on the `Future`
-   |
-LL |         take_u32(x.await)
-   |                   ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.stderr
index b48be16a24c..3cc4377514a 100644
--- a/tests/ui/consts/too_generic_eval_ice.stderr
+++ b/tests/ui/consts/too_generic_eval_ice.stderr
@@ -32,13 +32,13 @@ LL |         [5; Self::HOST_SIZE] == [6; 0]
    = help: the following other types implement trait `PartialEq<Rhs>`:
              `&[T]` implements `PartialEq<Vec<U, A>>`
              `&[T]` implements `PartialEq<[U; N]>`
+             `&[u8; N]` implements `PartialEq<ByteStr>`
+             `&[u8; N]` implements `PartialEq<ByteString>`
+             `&[u8]` implements `PartialEq<ByteStr>`
+             `&[u8]` implements `PartialEq<ByteString>`
              `&mut [T]` implements `PartialEq<Vec<U, A>>`
              `&mut [T]` implements `PartialEq<[U; N]>`
-             `[T; N]` implements `PartialEq<&[U]>`
-             `[T; N]` implements `PartialEq<&mut [U]>`
-             `[T; N]` implements `PartialEq<[U; N]>`
-             `[T; N]` implements `PartialEq<[U]>`
-           and 3 others
+           and 11 others
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs
new file mode 100644
index 00000000000..3a8d9c998cf
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs
@@ -0,0 +1,29 @@
+//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g
+//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=off
+//@ check-pass
+
+//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm
+//@[aarch64_gl] needs-llvm-components: aarch64
+
+//@[i686_g] compile-flags: --target i686-pc-windows-gnu
+//@[i686_g] needs-llvm-components: x86
+
+//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm
+//@[i686_gl] needs-llvm-components: x86
+
+//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu
+//@[i686_uwp_g] needs-llvm-components: x86
+
+//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64_g] needs-llvm-components: x86
+
+//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm
+//@[x86_64_gl] needs-llvm-components: x86
+
+//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu
+//@[x86_64_uwp_g] needs-llvm-components: x86
+
+#![feature(no_core)]
+
+#![no_core]
+#![no_std]
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr
new file mode 100644
index 00000000000..f3465e64976
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr
new file mode 100644
index 00000000000..f3465e64976
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr
new file mode 100644
index 00000000000..f3465e64976
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr
new file mode 100644
index 00000000000..f3465e64976
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs
new file mode 100644
index 00000000000..896bbac7d8e
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs
@@ -0,0 +1,29 @@
+//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g
+//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=packed
+//@ error-pattern: error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm
+//@[aarch64_gl] needs-llvm-components: aarch64
+
+//@[i686_g] compile-flags: --target i686-pc-windows-gnu
+//@[i686_g] needs-llvm-components: x86
+
+//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm
+//@[i686_gl] needs-llvm-components: x86
+
+//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu
+//@[i686_uwp_g] needs-llvm-components: x86
+
+//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64_g] needs-llvm-components: x86
+
+//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm
+//@[x86_64_gl] needs-llvm-components: x86
+
+//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu
+//@[x86_64_uwp_g] needs-llvm-components: x86
+
+#![feature(no_core)]
+
+#![no_core]
+#![no_std]
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr
new file mode 100644
index 00000000000..f3465e64976
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr
new file mode 100644
index 00000000000..f3465e64976
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr
new file mode 100644
index 00000000000..f3465e64976
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=packed` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr
new file mode 100644
index 00000000000..0964e21b13b
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr
new file mode 100644
index 00000000000..0964e21b13b
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr
new file mode 100644
index 00000000000..0964e21b13b
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr
new file mode 100644
index 00000000000..0964e21b13b
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs
new file mode 100644
index 00000000000..54a88c91217
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs
@@ -0,0 +1,29 @@
+//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g
+//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=unpacked
+//@ error-pattern: error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm
+//@[aarch64_gl] needs-llvm-components: aarch64
+
+//@[i686_g] compile-flags: --target i686-pc-windows-gnu
+//@[i686_g] needs-llvm-components: x86
+
+//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm
+//@[i686_gl] needs-llvm-components: x86
+
+//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu
+//@[i686_uwp_g] needs-llvm-components: x86
+
+//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu
+//@[x86_64_g] needs-llvm-components: x86
+
+//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm
+//@[x86_64_gl] needs-llvm-components: x86
+
+//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu
+//@[x86_64_uwp_g] needs-llvm-components: x86
+
+#![feature(no_core)]
+
+#![no_core]
+#![no_std]
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr
new file mode 100644
index 00000000000..0964e21b13b
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr
new file mode 100644
index 00000000000..0964e21b13b
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr
new file mode 100644
index 00000000000..0964e21b13b
--- /dev/null
+++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr
@@ -0,0 +1,4 @@
+error: `-Csplit-debuginfo=unpacked` is unstable on this platform
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/drop/drop-order-comparisons.e2021.fixed b/tests/ui/drop/drop-order-comparisons.e2021.fixed
new file mode 100644
index 00000000000..78cf421cfbf
--- /dev/null
+++ b/tests/ui/drop/drop-order-comparisons.e2021.fixed
@@ -0,0 +1,575 @@
+// This tests various aspects of the drop order with a focus on:
+//
+// - The lifetime of temporaries with the `if let` construct (and with
+// various similar constructs) and how these lifetimes were shortened
+// for `if let` in Rust 2024.
+//
+// - The shortening of the lifetimes of temporaries in tail
+// expressions in Rust 2024.
+//
+// - The behavior of `let` chains and how this behavior compares to
+// nested `if let` expressions and chained `let .. else` statements.
+//
+// In the tests below, `Events` tracks a sequence of numbered events.
+// Calling `e.mark(..)` logs a numbered event immediately.  Calling
+// `e.ok(..)` or `e.err(..)` returns an `Ok(_)` or `Err(_)` value,
+// respectively, and logs the numbered event when that value is
+// dropped.  Calling `e.assert()` verifies that the correct number of
+// events were logged and that they were logged in the correct order.
+
+//@ revisions: e2021 e2024
+//@ [e2021] edition: 2021
+//@ [e2021] run-rustfix
+//@ [e2021] rustfix-only-machine-applicable
+//@ [e2024] edition: 2024
+//@ run-pass
+
+#![feature(let_chains)]
+#![cfg_attr(e2021, warn(rust_2024_compatibility))]
+
+fn t_bindings() {
+    let e = Events::new();
+    _ = {
+        e.mark(1);
+        let _v = e.ok(8);
+        let _v = e.ok(2).is_ok();
+        let _ = e.ok(3);
+        let Ok(_) = e.ok(4) else { unreachable!() };
+        let Ok(_) = e.ok(5).as_ref() else { unreachable!() };
+        let _v = e.ok(7);
+        e.mark(6);
+    };
+    e.assert(8);
+}
+
+fn t_tuples() {
+    let e = Events::new();
+    _ = (e.ok(1), e.ok(4).is_ok(), e.ok(2), e.ok(3).is_ok());
+    e.assert(4);
+}
+
+fn t_arrays() {
+    let e = Events::new();
+    trait Tr {}
+    impl<T> Tr for T {}
+    fn b<'a, T: 'a>(x: T) -> Box<dyn Tr + 'a> {
+        Box::new(x)
+    }
+    _ = [b(e.ok(1)), b(e.ok(4).is_ok()), b(e.ok(2)), b(e.ok(3).is_ok())];
+    e.assert(4);
+}
+
+fn t_fncalls() {
+    let e = Events::new();
+    let f = |_, _, _, _| {};
+    _ = f(e.ok(2), e.ok(4).is_ok(), e.ok(1), e.ok(3).is_ok());
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_tailexpr_bindings() {
+    let e = Events::new();
+    _ = ({
+        let _v = e.ok(2);
+        let _v = e.ok(1);
+        e.ok(5).is_ok()
+        //[e2021]~^ WARN relative drop order changing in Rust 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+    }, e.mark(3), e.ok(4));
+    e.assert(5);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_tailexpr_bindings() {
+    let e = Events::new();
+    _ = ({
+        let _v = e.ok(3);
+        let _v = e.ok(2);
+        e.ok(1).is_ok()
+    }, e.mark(4), e.ok(5));
+    e.assert(5);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_tailexpr_tuples() {
+    let e = Events::new();
+    _ = ({
+        (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok())
+        //[e2021]~^ WARN relative drop order changing in Rust 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        //[e2021]~| WARN relative drop order changing in Rust 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+    }, e.mark(1), e.ok(4));
+    e.assert(6);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_tailexpr_tuples() {
+    let e = Events::new();
+    _ = ({
+        (e.ok(4), e.ok(2).is_ok(), e.ok(5), e.ok(1).is_ok())
+    }, e.mark(3), e.ok(6));
+    e.assert(6);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_then() {
+    let e = Events::new();
+    _ = (match e.ok(4).as_ref() { Ok(_) => {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+    } _ => {}}, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_then() {
+    let e = Events::new();
+    _ = (if let Ok(_) = e.ok(2).as_ref() {
+            e.mark(1);
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_else() {
+    let e = Events::new();
+    _ = (match e.err(4).as_ref() { Ok(_) => {} _ => {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+    }}, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_else() {
+    let e = Events::new();
+    _ = (if let Ok(_) = e.err(1).as_ref() {} else {
+            e.mark(2);
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_match_then() {
+    let e = Events::new();
+    _ = (match e.ok(4).as_ref() {
+            Ok(_) => e.mark(1),
+            _ => unreachable!(),
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_match_else() {
+    let e = Events::new();
+    _ = (match e.err(4).as_ref() {
+            Ok(_) => unreachable!(),
+            _ => e.mark(1),
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_let_else_then() {
+    let e = Events::new();
+    _ = ('top: {
+         'chain: {
+            let Ok(_) = e.ok(1).as_ref() else { break 'chain };
+            // The "then" branch:
+            e.mark(2);
+            break 'top;
+        }
+        // The "else" branch:
+        unreachable!()
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_let_else_else() {
+    let e = Events::new();
+    _ = ('top: {
+         'chain: {
+            let Ok(_) = e.err(1).as_ref() else { break 'chain };
+            // The "then" branch:
+            unreachable!();
+            #[allow(unreachable_code)]
+            break 'top;
+        }
+        // The "else" branch:
+        e.mark(2);
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_then_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        if let Ok(_) = e.ok(4).as_ref() {
+            //[e2021]~^ WARN relative drop order changing in Rust 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+        }
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_then_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        if let Ok(_) = e.ok(2).as_ref() {
+            e.mark(1);
+        }
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_else_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        match e.err(4).as_ref() { Ok(_) => {} _ => {
+            //[e2021]~^ WARN relative drop order changing in Rust 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            //[e2021]~| WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+        }}
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_else_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        if let Ok(_) = e.err(1).as_ref() {} else {
+            e.mark(2);
+        }
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_if_let_nested_then() {
+    let e = Events::new();
+    _ = {
+        // The unusual formatting, here and below, is to make the
+        // comparison with `let` chains more direct.
+        if e.ok(1).is_ok() {
+        if let true = e.ok(9).is_ok() {
+        if let Ok(_v) = e.ok(8) {
+        if let Ok(_) = e.ok(7) {
+        if let Ok(_) = e.ok(6).as_ref() {
+        if e.ok(2).is_ok() {
+        if let Ok(_v) = e.ok(5) {
+        if let Ok(_) = e.ok(4).as_ref() {
+            e.mark(3);
+        }}}}}}}}
+    };
+    e.assert(9);
+}
+
+#[rustfmt::skip]
+fn t_let_else_chained_then() {
+    let e = Events::new();
+    _ = 'top: {
+        'chain: {
+            if e.ok(1).is_ok() {} else { break 'chain };
+            let true = e.ok(2).is_ok() else { break 'chain };
+            let Ok(_v) = e.ok(9) else { break 'chain };
+            let Ok(_) = e.ok(3) else { break 'chain };
+            let Ok(_) = e.ok(4).as_ref() else { break 'chain };
+            if e.ok(5).is_ok() {} else { break 'chain };
+            let Ok(_v) = e.ok(8) else { break 'chain };
+            let Ok(_) = e.ok(6).as_ref() else { break 'chain };
+            // The "then" branch:
+            e.mark(7);
+            break 'top;
+        }
+        // The "else" branch:
+        unreachable!()
+    };
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_chains_then() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(9).is_ok()
+        && let Ok(_v) = e.ok(5)
+        && let Ok(_) = e.ok(8)
+        && let Ok(_) = e.ok(7).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(4)
+        && let Ok(_) = e.ok(6).as_ref() {
+            e.mark(3);
+        };
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_chains_then() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(9).is_ok()
+        && let Ok(_v) = e.ok(8)
+        && let Ok(_) = e.ok(7)
+        && let Ok(_) = e.ok(6).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(5)
+        && let Ok(_) = e.ok(4).as_ref() {
+            e.mark(3);
+        };
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_nested_else() {
+    let e = Events::new();
+    _ = if e.err(1).is_ok() {} else {
+        match e.err(9).is_ok() { true => {} _ => {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        match e.err(8) { Ok(_v) => {} _ => {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        match e.err(7) { Ok(_) => {} _ => {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        match e.err(6).as_ref() { Ok(_) => {} _ => {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        if e.err(2).is_ok() {} else {
+        match e.err(5) { Ok(_v) => {} _ => {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        match e.err(4) { Ok(_) => {} _ => {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(3);
+        }}}}}}}}}}}}}};
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_nested_else() {
+    let e = Events::new();
+    _ = if e.err(1).is_ok() {} else {
+        if let true = e.err(2).is_ok() {} else {
+        if let Ok(_v) = e.err(3) {} else {
+        if let Ok(_) = e.err(4) {} else {
+        if let Ok(_) = e.err(5).as_ref() {} else {
+        if e.err(6).is_ok() {} else {
+        if let Ok(_v) = e.err(7) {} else {
+        if let Ok(_) = e.err(8) {} else {
+            e.mark(9);
+        }}}}}}}};
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_nested_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok() {
+        if let true = e.ok(9).is_ok() {
+        if let Ok(_v) = e.ok(8) {
+        if let Ok(_) = e.ok(7) {
+        if let Ok(_) = e.ok(6).as_ref() {
+        if e.ok(2).is_ok() {
+        if let Ok(_v) = e.ok(5) {
+        match e.err(4).as_ref() { Ok(_) => {} _ => {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(3);
+        }}}}}}}}};
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_nested_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok() {
+        if let true = e.ok(9).is_ok() {
+        if let Ok(_v) = e.ok(8) {
+        if let Ok(_) = e.ok(7) {
+        if let Ok(_) = e.ok(6).as_ref() {
+        if e.ok(2).is_ok() {
+        if let Ok(_v) = e.ok(5) {
+        if let Ok(_) = e.err(3).as_ref() {} else {
+            e.mark(4);
+        }}}}}}}};
+    e.assert(9);
+}
+
+#[rustfmt::skip]
+fn t_let_else_chained_then_else() {
+    let e = Events::new();
+    _ = 'top: {
+        'chain: {
+            if e.ok(1).is_ok() {} else { break 'chain };
+            let true = e.ok(2).is_ok() else { break 'chain };
+            let Ok(_v) = e.ok(8) else { break 'chain };
+            let Ok(_) = e.ok(3) else { break 'chain };
+            let Ok(_) = e.ok(4).as_ref() else { break 'chain };
+            if e.ok(5).is_ok() {} else { break 'chain };
+            let Ok(_v) = e.ok(7) else { break 'chain };
+            let Ok(_) = e.err(6).as_ref() else { break 'chain };
+            // The "then" branch:
+            unreachable!();
+            #[allow(unreachable_code)]
+            break 'top;
+        }
+        // The "else" branch:
+        e.mark(9);
+    };
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(9).is_ok()
+        && let Ok(_v) = e.ok(4)
+        && let Ok(_) = e.ok(8)
+        && let Ok(_) = e.ok(7).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(3)
+        && let Ok(_) = e.err(6) {} else {
+            e.mark(5);
+        };
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(8).is_ok()
+        && let Ok(_v) = e.ok(7)
+        && let Ok(_) = e.ok(6)
+        && let Ok(_) = e.ok(5).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(4)
+        && let Ok(_) = e.err(3) {} else {
+            e.mark(9);
+        };
+    e.assert(9);
+}
+
+fn main() {
+    t_bindings();
+    t_tuples();
+    t_arrays();
+    t_fncalls();
+    t_tailexpr_bindings();
+    t_tailexpr_tuples();
+    t_if_let_then();
+    t_if_let_else();
+    t_match_then();
+    t_match_else();
+    t_let_else_then();
+    t_let_else_else();
+    t_if_let_then_tailexpr();
+    t_if_let_else_tailexpr();
+    t_if_let_nested_then();
+    t_let_else_chained_then();
+    t_if_let_chains_then();
+    t_if_let_nested_else();
+    t_if_let_nested_then_else();
+    t_let_else_chained_then_else();
+    t_if_let_chains_then_else();
+}
+
+// # Test scaffolding
+
+use core::cell::RefCell;
+use std::collections::HashSet;
+
+/// A buffer to track the order of events.
+///
+/// First, numbered events are logged into this buffer.
+///
+/// Then, `assert` is called to verify that the correct number of
+/// events were logged, and that they were logged in the expected
+/// order.
+struct Events(RefCell<Option<Vec<u64>>>);
+
+impl Events {
+    const fn new() -> Self {
+        Self(RefCell::new(Some(Vec::new())))
+    }
+    #[track_caller]
+    fn assert(&self, max: u64) {
+        let buf = &self.0;
+        let v1 = buf.borrow().as_ref().unwrap().clone();
+        let mut v2 = buf.borrow().as_ref().unwrap().clone();
+        *buf.borrow_mut() = None;
+        v2.sort();
+        let uniq_len = v2.iter().collect::<HashSet<_>>().len();
+        // Check that the sequence is sorted.
+        assert_eq!(v1, v2);
+        // Check that there are no duplicates.
+        assert_eq!(v2.len(), uniq_len);
+        // Check that the length is the expected one.
+        assert_eq!(max, uniq_len as u64);
+        // Check that the last marker is the expected one.
+        assert_eq!(v2.last().unwrap(), &max);
+    }
+    /// Return an `Ok` value that logs its drop.
+    fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
+        Ok(LogDrop(self, m))
+    }
+    /// Return an `Err` value that logs its drop.
+    fn err(&self, m: u64) -> Result<LogDrop, LogDrop> {
+        Err(LogDrop(self, m))
+    }
+    /// Log an event.
+    fn mark(&self, m: u64) {
+        self.0.borrow_mut().as_mut().unwrap().push(m);
+    }
+}
+
+impl Drop for Events {
+    fn drop(&mut self) {
+        if self.0.borrow().is_some() {
+            panic!("failed to call `Events::assert()`");
+        }
+    }
+}
+
+/// A type that logs its drop events.
+struct LogDrop<'b>(&'b Events, u64);
+
+impl<'b> Drop for LogDrop<'b> {
+    fn drop(&mut self) {
+        self.0.mark(self.1);
+    }
+}
diff --git a/tests/ui/drop/drop-order-comparisons.e2021.stderr b/tests/ui/drop/drop-order-comparisons.e2021.stderr
new file mode 100644
index 00000000000..158d18f6882
--- /dev/null
+++ b/tests/ui/drop/drop-order-comparisons.e2021.stderr
@@ -0,0 +1,477 @@
+warning: relative drop order changing in Rust 2024
+  --> $DIR/drop-order-comparisons.rs:76:9
+   |
+LL |       _ = ({
+   |  _________-
+LL | |         let _v = e.ok(2);
+   | |             --
+   | |             |
+   | |             `_v` calls a custom destructor
+   | |             `_v` will be dropped later as of Edition 2024
+LL | |         let _v = e.ok(1);
+   | |             --
+   | |             |
+   | |             this value will be stored in a temporary; let us call it `#2`
+   | |             `#2` will be dropped later as of Edition 2024
+LL | |         e.ok(5).is_ok()
+   | |         ^^^^^^^
+   | |         |
+   | |         this value will be stored in a temporary; let us call it `#3`
+   | |         up until Edition 2021 `#3` is dropped last but will be dropped earlier in Edition 2024
+...  |
+LL | |     }, e.mark(3), e.ok(4));
+   | |                          -
+   | |                          |
+   | |                          now the temporary value is dropped here, before the local variables in the block or statement
+   | |__________________________this value will be stored in a temporary; let us call it `#1`
+   |                            `#1` will be dropped later as of Edition 2024
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+note: `#3` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+note: `#1` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+note: `_v` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+note: `#2` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+   = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
+note: the lint level is defined here
+  --> $DIR/drop-order-comparisons.rs:28:25
+   |
+LL | #![cfg_attr(e2021, warn(rust_2024_compatibility))]
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[warn(tail_expr_drop_order)]` implied by `#[warn(rust_2024_compatibility)]`
+
+warning: relative drop order changing in Rust 2024
+  --> $DIR/drop-order-comparisons.rs:100:45
+   |
+LL |       _ = ({
+   |  _________-
+LL | |         (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok())
+   | |                                             ^^^^^^^
+   | |                                             |
+   | |                                             this value will be stored in a temporary; let us call it `#2`
+   | |                                             up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024
+...  |
+LL | |     }, e.mark(1), e.ok(4));
+   | |                          -
+   | |                          |
+   | |                          now the temporary value is dropped here, before the local variables in the block or statement
+   | |__________________________this value will be stored in a temporary; let us call it `#1`
+   |                            `#1` will be dropped later as of Edition 2024
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+note: `#2` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+note: `#1` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+   = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
+
+warning: relative drop order changing in Rust 2024
+  --> $DIR/drop-order-comparisons.rs:100:19
+   |
+LL |       _ = ({
+   |  _________-
+LL | |         (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok())
+   | |                   ^^^^^^^
+   | |                   |
+   | |                   this value will be stored in a temporary; let us call it `#2`
+   | |                   up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024
+...  |
+LL | |     }, e.mark(1), e.ok(4));
+   | |                          -
+   | |                          |
+   | |                          now the temporary value is dropped here, before the local variables in the block or statement
+   | |__________________________this value will be stored in a temporary; let us call it `#1`
+   |                            `#1` will be dropped later as of Edition 2024
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+note: `#2` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+note: `#1` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+   = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
+
+warning: relative drop order changing in Rust 2024
+  --> $DIR/drop-order-comparisons.rs:221:24
+   |
+LL |       _ = ({
+   |  _________-
+LL | |         if let Ok(_) = e.ok(4).as_ref() {
+   | |                        ^^^^^^^
+   | |                        |
+   | |                        this value will be stored in a temporary; let us call it `#2`
+   | |                        up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024
+...  |
+LL | |     }, e.mark(2), e.ok(3));
+   | |                          -
+   | |                          |
+   | |                          now the temporary value is dropped here, before the local variables in the block or statement
+   | |__________________________this value will be stored in a temporary; let us call it `#1`
+   |                            `#1` will be dropped later as of Edition 2024
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+note: `#2` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+note: `#1` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+   = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
+
+warning: relative drop order changing in Rust 2024
+  --> $DIR/drop-order-comparisons.rs:247:24
+   |
+LL |       _ = ({
+   |  _________-
+LL | |         if let Ok(_) = e.err(4).as_ref() {} else {
+   | |                        ^^^^^^^^
+   | |                        |
+   | |                        this value will be stored in a temporary; let us call it `#2`
+   | |                        up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024
+...  |
+LL | |     }, e.mark(2), e.ok(3));
+   | |                          -
+   | |                          |
+   | |                          now the temporary value is dropped here, before the local variables in the block or statement
+   | |__________________________this value will be stored in a temporary; let us call it `#1`
+   |                            `#1` will be dropped later as of Edition 2024
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+note: `#2` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+note: `#1` invokes this custom destructor
+  --> $DIR/drop-order-comparisons.rs:571:1
+   |
+LL | / impl<'b> Drop for LogDrop<'b> {
+LL | |     fn drop(&mut self) {
+LL | |         self.0.mark(self.1);
+LL | |     }
+LL | | }
+   | |_^
+   = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:123:13
+   |
+LL |     _ = (if let Ok(_) = e.ok(4).as_ref() {
+   |             ^^^^^^^^^^^^-------^^^^^^^^^
+   |                         |
+   |                         this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:127:5
+   |
+LL |     }, e.mark(2), e.ok(3));
+   |     ^
+   = note: `#[warn(if_let_rescope)]` implied by `#[warn(rust_2024_compatibility)]`
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~     _ = (match e.ok(4).as_ref() { Ok(_) => {
+LL |
+LL |
+LL |             e.mark(1);
+LL ~     } _ => {}}, e.mark(2), e.ok(3));
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:145:13
+   |
+LL |     _ = (if let Ok(_) = e.err(4).as_ref() {} else {
+   |             ^^^^^^^^^^^^--------^^^^^^^^^
+   |                         |
+   |                         this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:145:44
+   |
+LL |     _ = (if let Ok(_) = e.err(4).as_ref() {} else {
+   |                                            ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~     _ = (match e.err(4).as_ref() { Ok(_) => {} _ => {
+LL |
+LL |
+LL |             e.mark(1);
+LL ~     }}, e.mark(2), e.ok(3));
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:247:12
+   |
+LL |         if let Ok(_) = e.err(4).as_ref() {} else {
+   |            ^^^^^^^^^^^^--------^^^^^^^^^
+   |                        |
+   |                        this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:247:43
+   |
+LL |         if let Ok(_) = e.err(4).as_ref() {} else {
+   |                                           ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(4).as_ref() { Ok(_) => {} _ => {
+LL |
+...
+LL |             e.mark(1);
+LL ~         }}
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:352:12
+   |
+LL |         if let true = e.err(9).is_ok() {} else {
+   |            ^^^^^^^^^^^--------^^^^^^^^
+   |                       |
+   |                       this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:352:41
+   |
+LL |         if let true = e.err(9).is_ok() {} else {
+   |                                         ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(9).is_ok() { true => {} _ => {
+LL |
+...
+LL |             e.mark(3);
+LL ~         }}}}}}}}};
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:355:12
+   |
+LL |         if let Ok(_v) = e.err(8) {} else {
+   |            ^^^^^^^^^^^^^--------
+   |                         |
+   |                         this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:355:35
+   |
+LL |         if let Ok(_v) = e.err(8) {} else {
+   |                                   ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(8) { Ok(_v) => {} _ => {
+LL |
+...
+LL |             e.mark(3);
+LL ~         }}}}}}}}};
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:358:12
+   |
+LL |         if let Ok(_) = e.err(7) {} else {
+   |            ^^^^^^^^^^^^--------
+   |                        |
+   |                        this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:358:34
+   |
+LL |         if let Ok(_) = e.err(7) {} else {
+   |                                  ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(7) { Ok(_) => {} _ => {
+LL |
+...
+LL |             e.mark(3);
+LL ~         }}}}}}}}};
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:361:12
+   |
+LL |         if let Ok(_) = e.err(6).as_ref() {} else {
+   |            ^^^^^^^^^^^^--------^^^^^^^^^
+   |                        |
+   |                        this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:361:43
+   |
+LL |         if let Ok(_) = e.err(6).as_ref() {} else {
+   |                                           ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(6).as_ref() { Ok(_) => {} _ => {
+LL |
+...
+LL |             e.mark(3);
+LL ~         }}}}}}}}};
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:365:12
+   |
+LL |         if let Ok(_v) = e.err(5) {} else {
+   |            ^^^^^^^^^^^^^--------
+   |                         |
+   |                         this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:365:35
+   |
+LL |         if let Ok(_v) = e.err(5) {} else {
+   |                                   ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(5) { Ok(_v) => {} _ => {
+LL |
+...
+LL |             e.mark(3);
+LL ~         }}}}}}}}};
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:368:12
+   |
+LL |         if let Ok(_) = e.err(4) {} else {
+   |            ^^^^^^^^^^^^--------
+   |                        |
+   |                        this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:368:34
+   |
+LL |         if let Ok(_) = e.err(4) {} else {
+   |                                  ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(4) { Ok(_) => {} _ => {
+LL |
+LL |
+LL |             e.mark(3);
+LL ~         }}}}}}}}};
+   |
+
+warning: `if let` assigns a shorter lifetime since Edition 2024
+  --> $DIR/drop-order-comparisons.rs:404:12
+   |
+LL |         if let Ok(_) = e.err(4).as_ref() {} else {
+   |            ^^^^^^^^^^^^--------^^^^^^^^^
+   |                        |
+   |                        this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
+help: the value is now dropped here in Edition 2024
+  --> $DIR/drop-order-comparisons.rs:404:43
+   |
+LL |         if let Ok(_) = e.err(4).as_ref() {} else {
+   |                                           ^
+help: a `match` with a single arm can preserve the drop order up to Edition 2021
+   |
+LL ~         match e.err(4).as_ref() { Ok(_) => {} _ => {
+LL |
+LL |
+LL |             e.mark(3);
+LL ~         }}}}}}}}};
+   |
+
+warning: 15 warnings emitted
+
diff --git a/tests/ui/drop/drop-order-comparisons.rs b/tests/ui/drop/drop-order-comparisons.rs
new file mode 100644
index 00000000000..78c75a9449f
--- /dev/null
+++ b/tests/ui/drop/drop-order-comparisons.rs
@@ -0,0 +1,575 @@
+// This tests various aspects of the drop order with a focus on:
+//
+// - The lifetime of temporaries with the `if let` construct (and with
+// various similar constructs) and how these lifetimes were shortened
+// for `if let` in Rust 2024.
+//
+// - The shortening of the lifetimes of temporaries in tail
+// expressions in Rust 2024.
+//
+// - The behavior of `let` chains and how this behavior compares to
+// nested `if let` expressions and chained `let .. else` statements.
+//
+// In the tests below, `Events` tracks a sequence of numbered events.
+// Calling `e.mark(..)` logs a numbered event immediately.  Calling
+// `e.ok(..)` or `e.err(..)` returns an `Ok(_)` or `Err(_)` value,
+// respectively, and logs the numbered event when that value is
+// dropped.  Calling `e.assert()` verifies that the correct number of
+// events were logged and that they were logged in the correct order.
+
+//@ revisions: e2021 e2024
+//@ [e2021] edition: 2021
+//@ [e2021] run-rustfix
+//@ [e2021] rustfix-only-machine-applicable
+//@ [e2024] edition: 2024
+//@ run-pass
+
+#![feature(let_chains)]
+#![cfg_attr(e2021, warn(rust_2024_compatibility))]
+
+fn t_bindings() {
+    let e = Events::new();
+    _ = {
+        e.mark(1);
+        let _v = e.ok(8);
+        let _v = e.ok(2).is_ok();
+        let _ = e.ok(3);
+        let Ok(_) = e.ok(4) else { unreachable!() };
+        let Ok(_) = e.ok(5).as_ref() else { unreachable!() };
+        let _v = e.ok(7);
+        e.mark(6);
+    };
+    e.assert(8);
+}
+
+fn t_tuples() {
+    let e = Events::new();
+    _ = (e.ok(1), e.ok(4).is_ok(), e.ok(2), e.ok(3).is_ok());
+    e.assert(4);
+}
+
+fn t_arrays() {
+    let e = Events::new();
+    trait Tr {}
+    impl<T> Tr for T {}
+    fn b<'a, T: 'a>(x: T) -> Box<dyn Tr + 'a> {
+        Box::new(x)
+    }
+    _ = [b(e.ok(1)), b(e.ok(4).is_ok()), b(e.ok(2)), b(e.ok(3).is_ok())];
+    e.assert(4);
+}
+
+fn t_fncalls() {
+    let e = Events::new();
+    let f = |_, _, _, _| {};
+    _ = f(e.ok(2), e.ok(4).is_ok(), e.ok(1), e.ok(3).is_ok());
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_tailexpr_bindings() {
+    let e = Events::new();
+    _ = ({
+        let _v = e.ok(2);
+        let _v = e.ok(1);
+        e.ok(5).is_ok()
+        //[e2021]~^ WARN relative drop order changing in Rust 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+    }, e.mark(3), e.ok(4));
+    e.assert(5);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_tailexpr_bindings() {
+    let e = Events::new();
+    _ = ({
+        let _v = e.ok(3);
+        let _v = e.ok(2);
+        e.ok(1).is_ok()
+    }, e.mark(4), e.ok(5));
+    e.assert(5);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_tailexpr_tuples() {
+    let e = Events::new();
+    _ = ({
+        (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok())
+        //[e2021]~^ WARN relative drop order changing in Rust 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        //[e2021]~| WARN relative drop order changing in Rust 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+    }, e.mark(1), e.ok(4));
+    e.assert(6);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_tailexpr_tuples() {
+    let e = Events::new();
+    _ = ({
+        (e.ok(4), e.ok(2).is_ok(), e.ok(5), e.ok(1).is_ok())
+    }, e.mark(3), e.ok(6));
+    e.assert(6);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_then() {
+    let e = Events::new();
+    _ = (if let Ok(_) = e.ok(4).as_ref() {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_then() {
+    let e = Events::new();
+    _ = (if let Ok(_) = e.ok(2).as_ref() {
+            e.mark(1);
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_else() {
+    let e = Events::new();
+    _ = (if let Ok(_) = e.err(4).as_ref() {} else {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_else() {
+    let e = Events::new();
+    _ = (if let Ok(_) = e.err(1).as_ref() {} else {
+            e.mark(2);
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_match_then() {
+    let e = Events::new();
+    _ = (match e.ok(4).as_ref() {
+            Ok(_) => e.mark(1),
+            _ => unreachable!(),
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_match_else() {
+    let e = Events::new();
+    _ = (match e.err(4).as_ref() {
+            Ok(_) => unreachable!(),
+            _ => e.mark(1),
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_let_else_then() {
+    let e = Events::new();
+    _ = ('top: {
+         'chain: {
+            let Ok(_) = e.ok(1).as_ref() else { break 'chain };
+            // The "then" branch:
+            e.mark(2);
+            break 'top;
+        }
+        // The "else" branch:
+        unreachable!()
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_let_else_else() {
+    let e = Events::new();
+    _ = ('top: {
+         'chain: {
+            let Ok(_) = e.err(1).as_ref() else { break 'chain };
+            // The "then" branch:
+            unreachable!();
+            #[allow(unreachable_code)]
+            break 'top;
+        }
+        // The "else" branch:
+        e.mark(2);
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_then_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        if let Ok(_) = e.ok(4).as_ref() {
+            //[e2021]~^ WARN relative drop order changing in Rust 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+        }
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_then_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        if let Ok(_) = e.ok(2).as_ref() {
+            e.mark(1);
+        }
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_else_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        if let Ok(_) = e.err(4).as_ref() {} else {
+            //[e2021]~^ WARN relative drop order changing in Rust 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            //[e2021]~| WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(1);
+        }
+    }, e.mark(2), e.ok(3));
+    e.assert(4);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_else_tailexpr() {
+    let e = Events::new();
+    _ = ({
+        if let Ok(_) = e.err(1).as_ref() {} else {
+            e.mark(2);
+        }
+    }, e.mark(3), e.ok(4));
+    e.assert(4);
+}
+
+#[rustfmt::skip]
+fn t_if_let_nested_then() {
+    let e = Events::new();
+    _ = {
+        // The unusual formatting, here and below, is to make the
+        // comparison with `let` chains more direct.
+        if e.ok(1).is_ok() {
+        if let true = e.ok(9).is_ok() {
+        if let Ok(_v) = e.ok(8) {
+        if let Ok(_) = e.ok(7) {
+        if let Ok(_) = e.ok(6).as_ref() {
+        if e.ok(2).is_ok() {
+        if let Ok(_v) = e.ok(5) {
+        if let Ok(_) = e.ok(4).as_ref() {
+            e.mark(3);
+        }}}}}}}}
+    };
+    e.assert(9);
+}
+
+#[rustfmt::skip]
+fn t_let_else_chained_then() {
+    let e = Events::new();
+    _ = 'top: {
+        'chain: {
+            if e.ok(1).is_ok() {} else { break 'chain };
+            let true = e.ok(2).is_ok() else { break 'chain };
+            let Ok(_v) = e.ok(9) else { break 'chain };
+            let Ok(_) = e.ok(3) else { break 'chain };
+            let Ok(_) = e.ok(4).as_ref() else { break 'chain };
+            if e.ok(5).is_ok() {} else { break 'chain };
+            let Ok(_v) = e.ok(8) else { break 'chain };
+            let Ok(_) = e.ok(6).as_ref() else { break 'chain };
+            // The "then" branch:
+            e.mark(7);
+            break 'top;
+        }
+        // The "else" branch:
+        unreachable!()
+    };
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_chains_then() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(9).is_ok()
+        && let Ok(_v) = e.ok(5)
+        && let Ok(_) = e.ok(8)
+        && let Ok(_) = e.ok(7).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(4)
+        && let Ok(_) = e.ok(6).as_ref() {
+            e.mark(3);
+        };
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_chains_then() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(9).is_ok()
+        && let Ok(_v) = e.ok(8)
+        && let Ok(_) = e.ok(7)
+        && let Ok(_) = e.ok(6).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(5)
+        && let Ok(_) = e.ok(4).as_ref() {
+            e.mark(3);
+        };
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_nested_else() {
+    let e = Events::new();
+    _ = if e.err(1).is_ok() {} else {
+        if let true = e.err(9).is_ok() {} else {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        if let Ok(_v) = e.err(8) {} else {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        if let Ok(_) = e.err(7) {} else {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        if let Ok(_) = e.err(6).as_ref() {} else {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        if e.err(2).is_ok() {} else {
+        if let Ok(_v) = e.err(5) {} else {
+        //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+        //[e2021]~| WARN this changes meaning in Rust 2024
+        if let Ok(_) = e.err(4) {} else {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(3);
+        }}}}}}}};
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_nested_else() {
+    let e = Events::new();
+    _ = if e.err(1).is_ok() {} else {
+        if let true = e.err(2).is_ok() {} else {
+        if let Ok(_v) = e.err(3) {} else {
+        if let Ok(_) = e.err(4) {} else {
+        if let Ok(_) = e.err(5).as_ref() {} else {
+        if e.err(6).is_ok() {} else {
+        if let Ok(_v) = e.err(7) {} else {
+        if let Ok(_) = e.err(8) {} else {
+            e.mark(9);
+        }}}}}}}};
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_nested_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok() {
+        if let true = e.ok(9).is_ok() {
+        if let Ok(_v) = e.ok(8) {
+        if let Ok(_) = e.ok(7) {
+        if let Ok(_) = e.ok(6).as_ref() {
+        if e.ok(2).is_ok() {
+        if let Ok(_v) = e.ok(5) {
+        if let Ok(_) = e.err(4).as_ref() {} else {
+            //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024
+            //[e2021]~| WARN this changes meaning in Rust 2024
+            e.mark(3);
+        }}}}}}}};
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_nested_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok() {
+        if let true = e.ok(9).is_ok() {
+        if let Ok(_v) = e.ok(8) {
+        if let Ok(_) = e.ok(7) {
+        if let Ok(_) = e.ok(6).as_ref() {
+        if e.ok(2).is_ok() {
+        if let Ok(_v) = e.ok(5) {
+        if let Ok(_) = e.err(3).as_ref() {} else {
+            e.mark(4);
+        }}}}}}}};
+    e.assert(9);
+}
+
+#[rustfmt::skip]
+fn t_let_else_chained_then_else() {
+    let e = Events::new();
+    _ = 'top: {
+        'chain: {
+            if e.ok(1).is_ok() {} else { break 'chain };
+            let true = e.ok(2).is_ok() else { break 'chain };
+            let Ok(_v) = e.ok(8) else { break 'chain };
+            let Ok(_) = e.ok(3) else { break 'chain };
+            let Ok(_) = e.ok(4).as_ref() else { break 'chain };
+            if e.ok(5).is_ok() {} else { break 'chain };
+            let Ok(_v) = e.ok(7) else { break 'chain };
+            let Ok(_) = e.err(6).as_ref() else { break 'chain };
+            // The "then" branch:
+            unreachable!();
+            #[allow(unreachable_code)]
+            break 'top;
+        }
+        // The "else" branch:
+        e.mark(9);
+    };
+    e.assert(9);
+}
+
+#[cfg(e2021)]
+#[rustfmt::skip]
+fn t_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(9).is_ok()
+        && let Ok(_v) = e.ok(4)
+        && let Ok(_) = e.ok(8)
+        && let Ok(_) = e.ok(7).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(3)
+        && let Ok(_) = e.err(6) {} else {
+            e.mark(5);
+        };
+    e.assert(9);
+}
+
+#[cfg(e2024)]
+#[rustfmt::skip]
+fn t_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = if e.ok(1).is_ok()
+        && let true = e.ok(8).is_ok()
+        && let Ok(_v) = e.ok(7)
+        && let Ok(_) = e.ok(6)
+        && let Ok(_) = e.ok(5).as_ref()
+        && e.ok(2).is_ok()
+        && let Ok(_v) = e.ok(4)
+        && let Ok(_) = e.err(3) {} else {
+            e.mark(9);
+        };
+    e.assert(9);
+}
+
+fn main() {
+    t_bindings();
+    t_tuples();
+    t_arrays();
+    t_fncalls();
+    t_tailexpr_bindings();
+    t_tailexpr_tuples();
+    t_if_let_then();
+    t_if_let_else();
+    t_match_then();
+    t_match_else();
+    t_let_else_then();
+    t_let_else_else();
+    t_if_let_then_tailexpr();
+    t_if_let_else_tailexpr();
+    t_if_let_nested_then();
+    t_let_else_chained_then();
+    t_if_let_chains_then();
+    t_if_let_nested_else();
+    t_if_let_nested_then_else();
+    t_let_else_chained_then_else();
+    t_if_let_chains_then_else();
+}
+
+// # Test scaffolding
+
+use core::cell::RefCell;
+use std::collections::HashSet;
+
+/// A buffer to track the order of events.
+///
+/// First, numbered events are logged into this buffer.
+///
+/// Then, `assert` is called to verify that the correct number of
+/// events were logged, and that they were logged in the expected
+/// order.
+struct Events(RefCell<Option<Vec<u64>>>);
+
+impl Events {
+    const fn new() -> Self {
+        Self(RefCell::new(Some(Vec::new())))
+    }
+    #[track_caller]
+    fn assert(&self, max: u64) {
+        let buf = &self.0;
+        let v1 = buf.borrow().as_ref().unwrap().clone();
+        let mut v2 = buf.borrow().as_ref().unwrap().clone();
+        *buf.borrow_mut() = None;
+        v2.sort();
+        let uniq_len = v2.iter().collect::<HashSet<_>>().len();
+        // Check that the sequence is sorted.
+        assert_eq!(v1, v2);
+        // Check that there are no duplicates.
+        assert_eq!(v2.len(), uniq_len);
+        // Check that the length is the expected one.
+        assert_eq!(max, uniq_len as u64);
+        // Check that the last marker is the expected one.
+        assert_eq!(v2.last().unwrap(), &max);
+    }
+    /// Return an `Ok` value that logs its drop.
+    fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
+        Ok(LogDrop(self, m))
+    }
+    /// Return an `Err` value that logs its drop.
+    fn err(&self, m: u64) -> Result<LogDrop, LogDrop> {
+        Err(LogDrop(self, m))
+    }
+    /// Log an event.
+    fn mark(&self, m: u64) {
+        self.0.borrow_mut().as_mut().unwrap().push(m);
+    }
+}
+
+impl Drop for Events {
+    fn drop(&mut self) {
+        if self.0.borrow().is_some() {
+            panic!("failed to call `Events::assert()`");
+        }
+    }
+}
+
+/// A type that logs its drop events.
+struct LogDrop<'b>(&'b Events, u64);
+
+impl<'b> Drop for LogDrop<'b> {
+    fn drop(&mut self) {
+        self.0.mark(self.1);
+    }
+}
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
index a44ed9e5ef5..34548e2487e 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs
@@ -43,9 +43,9 @@ fn main() {
     }
 
     foo(bar, "string", |s| s.len() == 5);
-    //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
+    //~^ ERROR implementation of `Parser` is not general enough
+    //~| ERROR implementation of `Parser` is not general enough
     foo(baz, "string", |s| s.0.len() == 5);
-    //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
+    //~^ ERROR implementation of `Parser` is not general enough
+    //~| ERROR implementation of `Parser` is not general enough
 }
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
index b2bb417a8f0..23fc6e2f7f4 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr
@@ -1,39 +1,39 @@
-error: implementation of `FnOnce` is not general enough
+error: implementation of `Parser` is not general enough
   --> $DIR/issue-71955.rs:45:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
    |
-   = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2`
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
-error: implementation of `FnOnce` is not general enough
+error: implementation of `Parser` is not general enough
   --> $DIR/issue-71955.rs:45:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
    |
-   = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2`
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: implementation of `FnOnce` is not general enough
+error: implementation of `Parser` is not general enough
   --> $DIR/issue-71955.rs:48:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
    |
-   = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2`
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
-error: implementation of `FnOnce` is not general enough
+error: implementation of `Parser` is not general enough
   --> $DIR/issue-71955.rs:48:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
    |
-   = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2`
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/impl-trait/issue-102605.stderr b/tests/ui/impl-trait/issue-102605.stderr
index dcb22797173..ed6663fa61f 100644
--- a/tests/ui/impl-trait/issue-102605.stderr
+++ b/tests/ui/impl-trait/issue-102605.stderr
@@ -14,20 +14,11 @@ LL |     convert_result(foo())
    |     |
    |     arguments to this function are incorrect
    |
-note: calling an async function returns a future
-  --> $DIR/issue-102605.rs:13:20
-   |
-LL |     convert_result(foo())
-   |                    ^^^^^
 note: function defined here
   --> $DIR/issue-102605.rs:7:4
    |
 LL | fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
    |    ^^^^^^^^^^^^^^       ---------------
-help: consider `await`ing on the `Future`
-   |
-LL |     convert_result(foo().await)
-   |                         ++++++
 help: try wrapping the expression in `Err`
    |
 LL |     convert_result(Err(foo()))
diff --git a/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr
index 02c92c1c11d..a26f9a1ff56 100644
--- a/tests/ui/inference/issue-72616.stderr
+++ b/tests/ui/inference/issue-72616.stderr
@@ -6,11 +6,14 @@ LL |         if String::from("a") == "a".try_into().unwrap() {}
    |                              |
    |                              type must be known at this point
    |
-   = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate:
-           - impl PartialEq for String;
-           - impl<'a, 'b> PartialEq<&'a str> for String;
-           - impl<'a, 'b> PartialEq<Cow<'a, str>> for String;
-           - impl<'a, 'b> PartialEq<str> for String;
+   = note: cannot satisfy `String: PartialEq<_>`
+   = help: the following types implement trait `PartialEq<Rhs>`:
+             `String` implements `PartialEq<&str>`
+             `String` implements `PartialEq<ByteStr>`
+             `String` implements `PartialEq<ByteString>`
+             `String` implements `PartialEq<Cow<'_, str>>`
+             `String` implements `PartialEq<str>`
+             `String` implements `PartialEq`
 help: try using a fully qualified path to specify the expected types
    |
 LL |         if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}
diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr
index 6391672f861..2d09f667ae2 100644
--- a/tests/ui/inference/issue-72690.stderr
+++ b/tests/ui/inference/issue-72690.stderr
@@ -15,6 +15,7 @@ LL |     String::from("x".as_ref());
    |                      ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -41,6 +42,7 @@ LL |     |x| String::from("x".as_ref());
    |                          ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -57,6 +59,7 @@ LL |     let _ = "x".as_ref();
    |         ^       ------ type must be known at this point
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -83,6 +86,7 @@ LL |     String::from("x".as_ref());
    |                      ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -109,6 +113,7 @@ LL |     String::from("x".as_ref());
    |                      ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -135,6 +140,7 @@ LL |     String::from("x".as_ref());
    |                      ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -161,6 +167,7 @@ LL |     String::from("x".as_ref());
    |                      ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -187,6 +194,7 @@ LL |     String::from("x".as_ref());
    |                      ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
@@ -213,6 +221,7 @@ LL |     String::from("x".as_ref());
    |                      ^^^^^^
    |
    = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<ByteStr> for str;
            - impl AsRef<OsStr> for str;
            - impl AsRef<Path> for str;
            - impl AsRef<[u8]> for str;
diff --git a/tests/ui/intrinsics/reify-intrinsic.rs b/tests/ui/intrinsics/reify-intrinsic.rs
index 0d047ccf4a3..5b2324235c1 100644
--- a/tests/ui/intrinsics/reify-intrinsic.rs
+++ b/tests/ui/intrinsics/reify-intrinsic.rs
@@ -3,17 +3,17 @@
 #![feature(core_intrinsics, intrinsics)]
 
 fn a() {
-    let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
+    let _: unsafe fn(isize) -> usize = std::mem::transmute;
     //~^ ERROR cannot coerce
 }
 
 fn b() {
-    let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
+    let _ = std::mem::transmute as unsafe fn(isize) -> usize;
     //~^ ERROR casting
 }
 
 fn c() {
-    let _: [unsafe extern "rust-intrinsic" fn(f32) -> f32; 2] = [
+    let _: [unsafe fn(f32) -> f32; 2] = [
         std::intrinsics::floorf32, //~ ERROR cannot coerce
         std::intrinsics::log2f32,
     ];
diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr
index aea6d263a72..aea6f838e0d 100644
--- a/tests/ui/intrinsics/reify-intrinsic.stderr
+++ b/tests/ui/intrinsics/reify-intrinsic.stderr
@@ -1,19 +1,19 @@
 error[E0308]: cannot coerce intrinsics to function pointers
-  --> $DIR/reify-intrinsic.rs:6:64
+  --> $DIR/reify-intrinsic.rs:6:40
    |
-LL |     let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
-   |            -------------------------------------------------   ^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
+LL |     let _: unsafe fn(isize) -> usize = std::mem::transmute;
+   |            -------------------------   ^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
    |            |
    |            expected due to this
    |
-   = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
+   = note: expected fn pointer `unsafe fn(isize) -> usize`
                  found fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
 
-error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
+error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe fn(isize) -> usize` is invalid
   --> $DIR/reify-intrinsic.rs:11:13
    |
-LL |     let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let _ = std::mem::transmute as unsafe fn(isize) -> usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: cannot coerce intrinsics to function pointers
   --> $DIR/reify-intrinsic.rs:17:9
@@ -21,7 +21,7 @@ error[E0308]: cannot coerce intrinsics to function pointers
 LL |         std::intrinsics::floorf32,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
    |
-   = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _`
+   = note: expected fn pointer `unsafe fn(_) -> _`
                  found fn item `unsafe fn(_) -> _ {floorf32}`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs
new file mode 100644
index 00000000000..f6c1df55988
--- /dev/null
+++ b/tests/ui/layout/reprc-power-alignment.rs
@@ -0,0 +1,152 @@
+//@ check-pass
+//@ compile-flags: --target powerpc64-ibm-aix
+//@ needs-llvm-components: powerpc
+//@ add-core-stubs
+#![feature(no_core)]
+#![no_core]
+#![no_std]
+
+extern crate minicore;
+use minicore::*;
+
+#[warn(uses_power_alignment)]
+
+#[repr(C)]
+pub struct Floats {
+    a: f64,
+    b: u8,
+    c: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    d: f32,
+}
+
+pub struct Floats2 {
+    a: f64,
+    b: u32,
+    c: f64,
+}
+
+#[repr(C)]
+pub struct Floats3 {
+    a: f32,
+    b: f32,
+    c: i64,
+}
+
+#[repr(C)]
+pub struct Floats4 {
+    a: u64,
+    b: u32,
+    c: f32,
+}
+
+#[repr(C)]
+pub struct Floats5 {
+    a: f32,
+    b: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    c: f32,
+}
+
+#[repr(C)]
+pub struct FloatAgg1 {
+    x: Floats,
+    y: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg2 {
+    x: i64,
+    y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg3 {
+    x: FloatAgg1,
+    // NOTE: the "power" alignment rule is infectious to nested struct fields.
+    y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg4 {
+    x: FloatAgg1,
+    y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg5 {
+    x: FloatAgg1,
+    y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: FloatAgg3, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+
+#[repr(C)]
+pub struct FloatAgg6 {
+    x: i64,
+    y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: u8,
+}
+
+#[repr(C)]
+pub struct FloatAgg7 {
+    x: i64,
+    y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    z: u8,
+    zz: f32,
+}
+
+#[repr(C)]
+pub struct A {
+  d: f64,
+}
+#[repr(C)]
+pub struct B {
+  a: A,
+  f: f32,
+  d: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct C {
+  c: u8,
+  b: B, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct D {
+  x: f64,
+}
+#[repr(C)]
+pub struct E {
+  x: i32,
+  d: D, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct F {
+  a: u8,
+  b: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+#[repr(C)]
+pub struct G {
+    a: u8,
+    b: u8,
+    c: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+    d: f32,
+    e: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+}
+// Should not warn on #[repr(packed)].
+#[repr(packed)]
+pub struct H {
+    a: u8,
+    b: u8,
+    c: f64,
+    d: f32,
+    e: f64,
+}
+#[repr(C, packed)]
+pub struct I {
+    a: u8,
+    b: u8,
+    c: f64,
+    d: f32,
+    e: f64,
+}
+
+fn main() { }
diff --git a/tests/ui/layout/reprc-power-alignment.stderr b/tests/ui/layout/reprc-power-alignment.stderr
new file mode 100644
index 00000000000..18664e4d655
--- /dev/null
+++ b/tests/ui/layout/reprc-power-alignment.stderr
@@ -0,0 +1,112 @@
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:18:5
+   |
+LL |     c: f64,
+   |     ^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/reprc-power-alignment.rs:12:8
+   |
+LL | #[warn(uses_power_alignment)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:45:5
+   |
+LL |     b: f64,
+   |     ^^^^^^
+   |
+   = note: `#[warn(uses_power_alignment)]` on by default
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:52:5
+   |
+LL |     y: f64,
+   |     ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:58:5
+   |
+LL |     y: Floats,
+   |     ^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:65:5
+   |
+LL |     y: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:66:5
+   |
+LL |     z: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:72:5
+   |
+LL |     y: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:78:5
+   |
+LL |     y: FloatAgg2,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:79:5
+   |
+LL |     z: FloatAgg3,
+   |     ^^^^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:85:5
+   |
+LL |     y: Floats,
+   |     ^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:92:5
+   |
+LL |     y: Floats,
+   |     ^^^^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:105:3
+   |
+LL |   d: f64,
+   |   ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:110:3
+   |
+LL |   b: B,
+   |   ^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:119:3
+   |
+LL |   d: D,
+   |   ^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:124:3
+   |
+LL |   b: f64,
+   |   ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:130:5
+   |
+LL |     c: f64,
+   |     ^^^^^^
+
+warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
+  --> $DIR/reprc-power-alignment.rs:132:5
+   |
+LL |     e: f64,
+   |     ^^^^^^
+
+warning: 17 warnings emitted
+
diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs
index a12fe81eecd..9bbb20246df 100644
--- a/tests/ui/lint/clashing-extern-fn.rs
+++ b/tests/ui/lint/clashing-extern-fn.rs
@@ -248,6 +248,7 @@ mod sameish_members {
 
 mod same_sized_members_clash {
     mod a {
+        #[allow(uses_power_alignment)]
         #[repr(C)]
         struct Point3 {
             x: f32,
diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr
index b30dd476a1d..48dd1adbc1f 100644
--- a/tests/ui/lint/clashing-extern-fn.stderr
+++ b/tests/ui/lint/clashing-extern-fn.stderr
@@ -1,5 +1,5 @@
 warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:482:55
+  --> $DIR/clashing-extern-fn.rs:483:55
    |
 LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
    |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -9,7 +9,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
    = note: `#[warn(improper_ctypes)]` on by default
 
 warning: `extern` block uses type `Option<UnsafeCell<NonZero<usize>>>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:486:46
+  --> $DIR/clashing-extern-fn.rs:487:46
    |
 LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usize>>>;
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -151,7 +151,7 @@ LL |             fn draw_point(p: Point);
               found `unsafe extern "C" fn(sameish_members::b::Point)`
 
 warning: `origin` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:269:13
+  --> $DIR/clashing-extern-fn.rs:270:13
    |
 LL |             fn origin() -> Point3;
    |             ---------------------- `origin` previously declared here
@@ -163,7 +163,7 @@ LL |             fn origin() -> Point3;
               found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`
 
 warning: `transparent_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:292:13
+  --> $DIR/clashing-extern-fn.rs:293:13
    |
 LL |             fn transparent_incorrect() -> T;
    |             -------------------------------- `transparent_incorrect` previously declared here
@@ -175,7 +175,7 @@ LL |             fn transparent_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `missing_return_type` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:310:13
+  --> $DIR/clashing-extern-fn.rs:311:13
    |
 LL |             fn missing_return_type() -> usize;
    |             ---------------------------------- `missing_return_type` previously declared here
@@ -187,7 +187,7 @@ LL |             fn missing_return_type();
               found `unsafe extern "C" fn()`
 
 warning: `non_zero_usize` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:328:13
+  --> $DIR/clashing-extern-fn.rs:329:13
    |
 LL |             fn non_zero_usize() -> core::num::NonZero<usize>;
    |             ------------------------------------------------- `non_zero_usize` previously declared here
@@ -199,7 +199,7 @@ LL |             fn non_zero_usize() -> usize;
               found `unsafe extern "C" fn() -> usize`
 
 warning: `non_null_ptr` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:330:13
+  --> $DIR/clashing-extern-fn.rs:331:13
    |
 LL |             fn non_null_ptr() -> core::ptr::NonNull<usize>;
    |             ----------------------------------------------- `non_null_ptr` previously declared here
@@ -211,7 +211,7 @@ LL |             fn non_null_ptr() -> *const usize;
               found `unsafe extern "C" fn() -> *const usize`
 
 warning: `option_non_zero_usize_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:424:13
+  --> $DIR/clashing-extern-fn.rs:425:13
    |
 LL |             fn option_non_zero_usize_incorrect() -> usize;
    |             ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
@@ -223,7 +223,7 @@ LL |             fn option_non_zero_usize_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `option_non_null_ptr_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:426:13
+  --> $DIR/clashing-extern-fn.rs:427:13
    |
 LL |             fn option_non_null_ptr_incorrect() -> *const usize;
    |             --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
@@ -235,7 +235,7 @@ LL |             fn option_non_null_ptr_incorrect() -> *const isize;
               found `unsafe extern "C" fn() -> *const isize`
 
 warning: `hidden_niche_transparent_no_niche` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:482:13
+  --> $DIR/clashing-extern-fn.rs:483:13
    |
 LL |             fn hidden_niche_transparent_no_niche() -> usize;
    |             ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here
@@ -247,7 +247,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
               found `unsafe extern "C" fn() -> Option<TransparentNoNiche>`
 
 warning: `hidden_niche_unsafe_cell` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:486:13
+  --> $DIR/clashing-extern-fn.rs:487:13
    |
 LL |             fn hidden_niche_unsafe_cell() -> usize;
    |             --------------------------------------- `hidden_niche_unsafe_cell` previously declared here
diff --git a/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.rs b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.rs
new file mode 100644
index 00000000000..a9c2c20ef37
--- /dev/null
+++ b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.rs
@@ -0,0 +1,51 @@
+// https://github.com/rust-lang/rust/issues/109195
+struct Foo;
+
+impl Foo {
+    fn bar_baz() {}
+}
+
+impl Foo {
+    fn bar_quux() {}
+}
+
+fn main() {
+    String::from::utf8;
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `from_utf8`
+    String::from::utf8();
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `from_utf8`
+    String::from::utf16();
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `from_utf16`
+    String::from::method_that_doesnt_exist();
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP if there were a trait named `Example` with associated type `from`
+    str::into::string();
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `into_string`
+    str::char::indices();
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `char_indices`
+    Foo::bar::baz;
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `bar_baz`
+    Foo::bar::quux;
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `bar_quux`
+    Foo::bar::fizz;
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP if there were a trait named `Example` with associated type `bar`
+    i32::wrapping::add;
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP there is an associated function with a similar name: `wrapping_add`
+    i32::wrapping::method_that_doesnt_exist;
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP if there were a trait named `Example` with associated type `wrapping`
+
+    // this one ideally should suggest `downcast_mut_unchecked`
+    <dyn std::any::Any>::downcast::mut_unchecked;
+    //~^ ERROR ambiguous associated type [E0223]
+    //~| HELP if there were a trait named `Example` with associated type `downcast`
+}
diff --git a/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.stderr b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.stderr
new file mode 100644
index 00000000000..5863aa28f41
--- /dev/null
+++ b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.stderr
@@ -0,0 +1,135 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:13:5
+   |
+LL |     String::from::utf8;
+   |     ^^^^^^^^^^^^
+   |
+help: there is an associated function with a similar name: `from_utf8`
+   |
+LL |     String::from_utf8;
+   |             ~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:16:5
+   |
+LL |     String::from::utf8();
+   |     ^^^^^^^^^^^^
+   |
+help: there is an associated function with a similar name: `from_utf8`
+   |
+LL |     String::from_utf8();
+   |             ~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:19:5
+   |
+LL |     String::from::utf16();
+   |     ^^^^^^^^^^^^
+   |
+help: there is an associated function with a similar name: `from_utf16`
+   |
+LL |     String::from_utf16();
+   |             ~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:22:5
+   |
+LL |     String::from::method_that_doesnt_exist();
+   |     ^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path
+   |
+LL |     <String as Example>::from::method_that_doesnt_exist();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:25:5
+   |
+LL |     str::into::string();
+   |     ^^^^^^^^^
+   |
+help: there is an associated function with a similar name: `into_string`
+   |
+LL |     str::into_string();
+   |          ~~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:28:5
+   |
+LL |     str::char::indices();
+   |     ^^^^^^^^^
+   |
+help: there is an associated function with a similar name: `char_indices`
+   |
+LL |     str::char_indices();
+   |          ~~~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:31:5
+   |
+LL |     Foo::bar::baz;
+   |     ^^^^^^^^
+   |
+help: there is an associated function with a similar name: `bar_baz`
+   |
+LL |     Foo::bar_baz;
+   |          ~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:34:5
+   |
+LL |     Foo::bar::quux;
+   |     ^^^^^^^^
+   |
+help: there is an associated function with a similar name: `bar_quux`
+   |
+LL |     Foo::bar_quux;
+   |          ~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:37:5
+   |
+LL |     Foo::bar::fizz;
+   |     ^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `bar` implemented for `Foo`, you could use the fully-qualified path
+   |
+LL |     <Foo as Example>::bar::fizz;
+   |     ~~~~~~~~~~~~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:40:5
+   |
+LL |     i32::wrapping::add;
+   |     ^^^^^^^^^^^^^
+   |
+help: there is an associated function with a similar name: `wrapping_add`
+   |
+LL |     i32::wrapping_add;
+   |          ~~~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:43:5
+   |
+LL |     i32::wrapping::method_that_doesnt_exist;
+   |     ^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `wrapping` implemented for `i32`, you could use the fully-qualified path
+   |
+LL |     <i32 as Example>::wrapping::method_that_doesnt_exist;
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:48:5
+   |
+LL |     <dyn std::any::Any>::downcast::mut_unchecked;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `downcast` implemented for `(dyn Any + 'static)`, you could use the fully-qualified path
+   |
+LL |     <(dyn Any + 'static) as Example>::downcast::mut_unchecked;
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/suggestions/issue-109195.rs b/tests/ui/suggestions/issue-109195.rs
deleted file mode 100644
index cc499b0d776..00000000000
--- a/tests/ui/suggestions/issue-109195.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-fn main() {
-    String::from::utf8;
-    //~^ ERROR ambiguous associated type [E0223]
-    //~| HELP there is an associated function with a similar name: `from_utf8`
-    String::from::utf8();
-    //~^ ERROR ambiguous associated type [E0223]
-    //~| HELP there is an associated function with a similar name: `from_utf8`
-    String::from::utf16();
-    //~^ ERROR ambiguous associated type [E0223]
-    //~| HELP there is an associated function with a similar name: `from_utf16`
-    String::from::method_that_doesnt_exist();
-    //~^ ERROR ambiguous associated type [E0223]
-    //~| HELP if there were a trait named `Example` with associated type `from`
-    str::from::utf8();
-    //~^ ERROR ambiguous associated type [E0223]
-    //~| HELP if there were a trait named `Example` with associated type `from`
-    str::from::utf8_mut();
-    //~^ ERROR ambiguous associated type [E0223]
-    //~| HELP if there were a trait named `Example` with associated type `from`
-}
diff --git a/tests/ui/suggestions/issue-109195.stderr b/tests/ui/suggestions/issue-109195.stderr
deleted file mode 100644
index 10cf9cfd28c..00000000000
--- a/tests/ui/suggestions/issue-109195.stderr
+++ /dev/null
@@ -1,69 +0,0 @@
-error[E0223]: ambiguous associated type
-  --> $DIR/issue-109195.rs:2:5
-   |
-LL |     String::from::utf8;
-   |     ^^^^^^^^^^^^
-   |
-help: there is an associated function with a similar name: `from_utf8`
-   |
-LL |     String::from_utf8;
-   |             ~~~~~~~~~
-
-error[E0223]: ambiguous associated type
-  --> $DIR/issue-109195.rs:5:5
-   |
-LL |     String::from::utf8();
-   |     ^^^^^^^^^^^^
-   |
-help: there is an associated function with a similar name: `from_utf8`
-   |
-LL |     String::from_utf8();
-   |             ~~~~~~~~~
-
-error[E0223]: ambiguous associated type
-  --> $DIR/issue-109195.rs:8:5
-   |
-LL |     String::from::utf16();
-   |     ^^^^^^^^^^^^
-   |
-help: there is an associated function with a similar name: `from_utf16`
-   |
-LL |     String::from_utf16();
-   |             ~~~~~~~~~~
-
-error[E0223]: ambiguous associated type
-  --> $DIR/issue-109195.rs:11:5
-   |
-LL |     String::from::method_that_doesnt_exist();
-   |     ^^^^^^^^^^^^
-   |
-help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path
-   |
-LL |     <String as Example>::from::method_that_doesnt_exist();
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-error[E0223]: ambiguous associated type
-  --> $DIR/issue-109195.rs:14:5
-   |
-LL |     str::from::utf8();
-   |     ^^^^^^^^^
-   |
-help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path
-   |
-LL |     <str as Example>::from::utf8();
-   |     ~~~~~~~~~~~~~~~~~~~~~~
-
-error[E0223]: ambiguous associated type
-  --> $DIR/issue-109195.rs:17:5
-   |
-LL |     str::from::utf8_mut();
-   |     ^^^^^^^^^
-   |
-help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path
-   |
-LL |     <str as Example>::from::utf8_mut();
-   |     ~~~~~~~~~~~~~~~~~~~~~~
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs
new file mode 100644
index 00000000000..d05def2cb75
--- /dev/null
+++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Znext-solver
+
+trait Wf {
+    type Assoc;
+}
+
+struct S {
+    f: &'static <() as Wf>::Assoc,
+    //~^ ERROR the trait bound `(): Wf` is not satisfied
+}
+
+fn main() {
+    let x: S = todo!();
+    let y: &() = x.f;
+    //~^ ERROR mismatched types
+    //~| ERROR the trait bound `(): Wf` is not satisfied
+}
diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr
new file mode 100644
index 00000000000..32a7766a638
--- /dev/null
+++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr
@@ -0,0 +1,39 @@
+error[E0277]: the trait bound `(): Wf` is not satisfied
+  --> $DIR/non-wf-in-coerce-pointers.rs:8:17
+   |
+LL |     f: &'static <() as Wf>::Assoc,
+   |                 ^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/non-wf-in-coerce-pointers.rs:3:1
+   |
+LL | trait Wf {
+   | ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/non-wf-in-coerce-pointers.rs:14:18
+   |
+LL |     let y: &() = x.f;
+   |            ---   ^^^ types differ
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&()`
+              found reference `&'static <() as Wf>::Assoc`
+
+error[E0277]: the trait bound `(): Wf` is not satisfied
+  --> $DIR/non-wf-in-coerce-pointers.rs:14:18
+   |
+LL |     let y: &() = x.f;
+   |                  ^^^ the trait `Wf` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/non-wf-in-coerce-pointers.rs:3:1
+   |
+LL | trait Wf {
+   | ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs b/tests/ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs
new file mode 100644
index 00000000000..dc96652f82f
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// `(): Trait` is a global where-bound with a projection bound.
+// This previously resulted in ambiguity as we considered both
+// the impl and the where-bound while normalizing.
+
+trait Trait {
+    type Assoc;
+}
+impl Trait for () {
+    type Assoc = &'static ();
+}
+
+fn foo<'a>(x: <() as Trait>::Assoc)
+where
+    (): Trait<Assoc = &'a ()>,
+{
+}
+
+fn main() {}