about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2025-09-17 05:00:44 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2025-09-17 05:00:44 +0000
commit1672251dad4ffe70c95dd233b2c044045acd2fd3 (patch)
treec247b3719ca59935abd7e225e202cf8609bcb48c
parent06e881042d3f58fdb60fde58de5bf112b2184b11 (diff)
parent3f1552a273e43e15f6ed240d00e1efdd6a53e65e (diff)
downloadrust-1672251dad4ffe70c95dd233b2c044045acd2fd3.tar.gz
rust-1672251dad4ffe70c95dd233b2c044045acd2fd3.zip
Merge ref '3f1552a273e4' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: 3f1552a273e43e15f6ed240d00e1efdd6a53e65e
Filtered ref: fbfa7b30a3ad5abd6a5db7e3ef15adc8da1ecc37
Upstream diff: https://github.com/rust-lang/rust/compare/9d82de19dfae60e55c291f5f28e28cfc2c1b9630...3f1552a273e43e15f6ed240d00e1efdd6a53e65e

This merge was created using https://github.com/rust-lang/josh-sync.
-rw-r--r--.mailmap1
-rw-r--r--Cargo.lock4
-rw-r--r--RELEASES.md126
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs39
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs16
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2400
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs17
-rw-r--r--compiler/rustc_lint/src/unused.rs8
-rw-r--r--compiler/rustc_llvm/build.rs1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp124
-rw-r--r--compiler/rustc_llvm/src/lib.rs6
-rw-r--r--compiler/rustc_middle/messages.ftl2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs8
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs43
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs38
-rw-r--r--library/alloc/src/vec/peek_mut.rs4
-rw-r--r--library/alloctests/tests/vec.rs4
-rw-r--r--library/core/src/array/mod.rs5
-rw-r--r--library/core/src/cmp.rs9
-rw-r--r--library/core/src/marker.rs33
-rw-r--r--library/core/src/mem/transmutability.rs6
-rw-r--r--library/core/src/num/bignum.rs37
-rw-r--r--library/core/src/tuple.rs10
-rw-r--r--library/coretests/tests/ascii.rs7
-rw-r--r--library/coretests/tests/fmt/builders.rs15
-rw-r--r--library/coretests/tests/fmt/mod.rs30
-rw-r--r--library/coretests/tests/fmt/num.rs6
-rw-r--r--library/coretests/tests/lib.rs1
-rw-r--r--library/coretests/tests/num/bignum.rs19
-rw-r--r--library/coretests/tests/ptr.rs8
-rw-r--r--library/std/src/sys/fs/unix.rs120
-rw-r--r--src/bootstrap/README.md15
-rw-r--r--src/bootstrap/bootstrap.py6
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs3
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs5
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs7
-rw-r--r--src/bootstrap/src/core/sanity.rs2
-rw-r--r--src/doc/rustc/src/target-tier-policy.md2
-rw-r--r--src/tools/compiletest/src/common.rs4
-rw-r--r--src/tools/compiletest/src/directives.rs9
-rw-r--r--src/tools/compiletest/src/directives/needs.rs13
-rw-r--r--src/tools/compiletest/src/directives/tests.rs8
-rw-r--r--src/tools/compiletest/src/executor.rs14
-rw-r--r--src/tools/compiletest/src/lib.rs39
-rw-r--r--src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr2
-rw-r--r--src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs18
-rw-r--r--src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr15
-rw-r--r--src/tools/miri/tests/fail/validity/nonzero.stderr2
-rw-r--r--src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs19
-rw-r--r--src/tools/opt-dist/src/training.rs1
-rw-r--r--src/tools/tidy/src/deps.rs177
-rw-r--r--src/tools/tidy/src/extdeps.rs12
-rw-r--r--tests/codegen-llvm/asm/riscv-clobbers.rs2
-rw-r--r--tests/codegen-llvm/c-variadic-lifetime.rs4
-rw-r--r--tests/codegen-llvm/rust-abi-arch-specific-adjustment.rs8
-rw-r--r--tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-abort.diff19
-rw-r--r--tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-unwind.diff19
-rw-r--r--tests/mir-opt/dest-prop/aggregate.rs51
-rw-r--r--tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-abort.diff22
-rw-r--r--tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-unwind.diff22
-rw-r--r--tests/ui/associated-types/associated-types-for-unimpl-trait.fixed2
-rw-r--r--tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs2
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs2
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr42
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs5
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr19
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs2
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr24
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_good.rs8
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr10
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs8
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr28
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr10
-rw-r--r--tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs3
-rw-r--r--tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr63
-rw-r--r--tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr6
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr6
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr6
-rw-r--r--tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr6
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-1.rs5
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-1.stderr28
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-2.rs14
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-2.stderr27
-rw-r--r--tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs1
-rw-r--r--tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr51
-rw-r--r--tests/ui/const-generics/const-param-with-additional-obligations.rs4
-rw-r--r--tests/ui/const-generics/generic_arg_infer/paren_infer.rs (renamed from tests/ui/const-generics/generic_arg_infer/parend_infer.rs)1
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/no_const_param_ty_bound.stderr2
-rw-r--r--tests/ui/const-generics/issue-66451.rs6
-rw-r--r--tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr2
-rw-r--r--tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr22
-rw-r--r--tests/ui/const-generics/slice-const-param.rs2
-rw-r--r--tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr12
-rw-r--r--tests/ui/const-generics/transmute-const-param-static-reference.rs2
-rw-r--r--tests/ui/const-generics/unsized_const_params/symbol_mangling_v0_str.rs4
-rw-r--r--tests/ui/consts/const_refs_to_static_fail.stderr2
-rw-r--r--tests/ui/consts/const_refs_to_static_fail_invalid.stderr4
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static.stderr2
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr6
-rw-r--r--tests/ui/dist/cranelift-x86_64-unknown-linux-gnu-dist.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-adt_const_params.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-adt_const_params.stderr12
-rw-r--r--tests/ui/layout/thaw-transmute-invalid-enum.rs1
-rw-r--r--tests/ui/layout/thaw-transmute-invalid-enum.stderr19
-rw-r--r--tests/ui/lifetimes/issue-105507.fixed2
-rw-r--r--tests/ui/lint/unused_parens_follow_ident.fixed17
-rw-r--r--tests/ui/lint/unused_parens_follow_ident.rs17
-rw-r--r--tests/ui/lint/unused_parens_follow_ident.stderr31
-rw-r--r--tests/ui/parser/expr-as-stmt.fixed4
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed2
-rw-r--r--tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed2
-rw-r--r--tests/ui/suggestions/trait-impl-bound-suggestions.fixed4
-rw-r--r--tests/ui/symbol-names/const-generics-structural-demangling.rs8
132 files changed, 2516 insertions, 1804 deletions
diff --git a/.mailmap b/.mailmap
index 6e3eed1226e..0f7bc5e38bd 100644
--- a/.mailmap
+++ b/.mailmap
@@ -609,6 +609,7 @@ Shohei Wada <pc@wada314.jp>
 Shotaro Yamada <sinkuu@sinkuu.xyz>
 Shotaro Yamada <sinkuu@sinkuu.xyz> <sinkuu@users.noreply.github.com>
 Shyam Sundar B <shyambaskaran@outlook.com>
+Sidney Cammeresi <sac@cheesecake.org> <sac@readyset.io>
 Simon Barber-Dueck <sbarberdueck@gmail.com> Simon BD <simon@server>
 Simon Sapin <simon@exyr.org> <simon.sapin@exyr.org>
 Simonas Kazlauskas <git@kazlauskas.me> Simonas Kazlauskas <github@kazlauskas.me>
diff --git a/Cargo.lock b/Cargo.lock
index 4677d34d2a6..d39cfefea0c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4817,9 +4817,9 @@ dependencies = [
 
 [[package]]
 name = "rustfix"
-version = "0.8.1"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4"
+checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a"
 dependencies = [
  "serde",
  "serde_json",
diff --git a/RELEASES.md b/RELEASES.md
index 33abe45ce46..2b65d070d5f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,129 @@
+Version 1.90 (2025-09-18)
+==========================
+
+<a id="1.90-Language"></a>
+
+Language
+--------
+- [Split up the `unknown_or_malformed_diagnostic_attributes` lint](https://github.com/rust-lang/rust/pull/140717). This lint has been split up into four finer-grained lints, with `unknown_or_malformed_diagnostic_attributes` now being the lint group that contains these lints:
+    1. `unknown_diagnostic_attributes`: unknown to the current compiler
+    2. `misplaced_diagnostic_attributes`: placed on the wrong item
+    3. `malformed_diagnostic_attributes`: malformed attribute syntax or options
+    4. `malformed_diagnostic_format_literals`: malformed format string literal
+- [Allow constants whose final value has references to mutable/external memory, but reject such constants as patterns](https://github.com/rust-lang/rust/pull/140942)
+- [Allow volatile access to non-Rust memory, including address 0](https://github.com/rust-lang/rust/pull/141260)
+
+
+<a id="1.90-Compiler"></a>
+
+Compiler
+--------
+- [Use `lld` by default on `x86_64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/140525).
+- [Tier 3 `musl` targets now link dynamically by default](https://github.com/rust-lang/rust/pull/144410). Affected targets:
+    - `mips64-unknown-linux-muslabi64`
+    - `powerpc64-unknown-linux-musl`
+    - `powerpc-unknown-linux-musl`
+    - `powerpc-unknown-linux-muslspe`
+    - `riscv32gc-unknown-linux-musl`
+    - `s390x-unknown-linux-musl`
+    - `thumbv7neon-unknown-linux-musleabihf`
+
+
+<a id="1.90-Platform-Support"></a>
+
+Platform Support
+----------------
+- [Demote `x86_64-apple-darwin` to Tier 2 with host tools](https://github.com/rust-lang/rust/pull/145252)
+
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
+
+<a id="1.90-Libraries"></a>
+
+Libraries
+---------
+- [Stabilize `u*::{checked,overflowing,saturating,wrapping}_sub_signed`](https://github.com/rust-lang/rust/issues/126043)
+- [Allow comparisons between `CStr`, `CString`, and `Cow<CStr>`](https://github.com/rust-lang/rust/pull/137268)
+- [Remove some unsized tuple impls since unsized tuples can't be constructed](https://github.com/rust-lang/rust/pull/138340)
+- [Set `MSG_NOSIGNAL` for `UnixStream`](https://github.com/rust-lang/rust/pull/140005)
+- [`proc_macro::Ident::new` now supports `$crate`.](https://github.com/rust-lang/rust/pull/141996)
+- [Guarantee the pointer returned from `Thread::into_raw` has at least 8 bytes of alignment](https://github.com/rust-lang/rust/pull/143859)
+
+
+<a id="1.90-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`u{n}::checked_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.checked_sub_signed)
+- [`u{n}::overflowing_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.overflowing_sub_signed)
+- [`u{n}::saturating_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.saturating_sub_signed)
+- [`u{n}::wrapping_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.wrapping_sub_signed)
+- [`impl Copy for IntErrorKind`](https://doc.rust-lang.org/stable/std/num/enum.IntErrorKind.html#impl-Copy-for-IntErrorKind)
+- [`impl Hash for IntErrorKind`](https://doc.rust-lang.org/stable/std/num/enum.IntErrorKind.html#impl-Hash-for-IntErrorKind)
+- [`impl PartialEq<&CStr> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3C%26CStr%3E-for-CStr)
+- [`impl PartialEq<CString> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3CCString%3E-for-CStr)
+- [`impl PartialEq<Cow<CStr>> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3CCow%3C'_,+CStr%3E%3E-for-CStr)
+- [`impl PartialEq<&CStr> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3C%26CStr%3E-for-CString)
+- [`impl PartialEq<CStr> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3CCStr%3E-for-CString)
+- [`impl PartialEq<Cow<CStr>> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3CCow%3C'_,+CStr%3E%3E-for-CString)
+- [`impl PartialEq<&CStr> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3C%26CStr%3E-for-Cow%3C'_,+CStr%3E)
+- [`impl PartialEq<CStr> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3CCStr%3E-for-Cow%3C'_,+CStr%3E)
+- [`impl PartialEq<CString> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3CCString%3E-for-Cow%3C'_,+CStr%3E)
+
+
+These previously stable APIs are now stable in const contexts:
+
+- [`<[T]>::reverse`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.reverse)
+- [`f32::floor`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.floor)
+- [`f32::ceil`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.ceil)
+- [`f32::trunc`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.trunc)
+- [`f32::fract`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.fract)
+- [`f32::round`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round)
+- [`f32::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round_ties_even)
+- [`f64::floor`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.floor)
+- [`f64::ceil`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.ceil)
+- [`f64::trunc`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.trunc)
+- [`f64::fract`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.fract)
+- [`f64::round`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round)
+- [`f64::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round_ties_even)
+
+
+<a id="1.90-Cargo"></a>
+
+Cargo
+-----
+- [Add `http.proxy-cainfo` config for proxy certs](https://github.com/rust-lang/cargo/pull/15374/)
+- [Use `gix` for `cargo package`](https://github.com/rust-lang/cargo/pull/15534/)
+- [feat(publish): Stabilize multi-package publishing](https://github.com/rust-lang/cargo/pull/15636/)
+
+<a id="1.90-Rustdoc"></a>
+
+Rustdoc
+-----
+- [Add ways to collapse all impl blocks](https://github.com/rust-lang/rust/pull/141663). Previously the "Summary" button and "-" keyboard shortcut would never collapse `impl` blocks, now they do when shift is held
+- [Display unsafe attributes with `unsafe()` wrappers](https://github.com/rust-lang/rust/pull/143662)
+
+
+<a id="1.90-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+- [Use `lld` by default on `x86_64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/140525).
+  See also <https://blog.rust-lang.org/2025/09/01/rust-lld-on-1.90.0-stable/>.
+- [Make `core::iter::Fuse`'s `Default` impl construct `I::default()` internally as promised in the docs instead of always being empty](https://github.com/rust-lang/rust/pull/140985)
+- [Set `MSG_NOSIGNAL` for `UnixStream`](https://github.com/rust-lang/rust/pull/140005)
+  This may change program behavior but results in the same behavior as other primitives (e.g., stdout, network sockets).
+  Programs relying on signals to terminate them should update handling of sockets to handle errors on write by exiting.
+- [On Unix `std::env::home_dir` will use the fallback if the `HOME` environment variable is empty](https://github.com/rust-lang/rust/pull/141840)
+- We now [reject unsupported `extern "{abi}"`s consistently in all positions](https://github.com/rust-lang/rust/pull/142134). This primarily affects the use of implementing traits on an `extern "{abi}"` function pointer, like `extern "stdcall" fn()`, on a platform that doesn't support that, like aarch64-unknown-linux-gnu. Direct usage of these unsupported ABI strings by declaring or defining functions was already rejected, so this is only a change for consistency.
+- [const-eval: error when initializing a static writes to that static](https://github.com/rust-lang/rust/pull/143084)
+- [Check that the `proc_macro_derive` macro has correct arguments when applied to the crate root](https://github.com/rust-lang/rust/pull/143607)
+
+
 Version 1.89.0 (2025-08-07)
 ==========================
 
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index dd8f0e46a0e..63342880b09 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -51,43 +51,4 @@ pub(crate) fn expand_deriving_const_param_ty(
     };
 
     trait_def.expand(cx, mitem, item, push);
-
-    let trait_def = TraitDef {
-        span,
-        path: path_std!(marker::UnsizedConstParamTy),
-        skip_path_as_bound: false,
-        needs_copy_as_bound_if_packed: false,
-        additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
-        supports_unions: false,
-        methods: Vec::new(),
-        associated_types: Vec::new(),
-        is_const,
-        is_staged_api_crate: cx.ecfg.features.staged_api(),
-    };
-
-    trait_def.expand(cx, mitem, item, push);
-}
-
-pub(crate) fn expand_deriving_unsized_const_param_ty(
-    cx: &ExtCtxt<'_>,
-    span: Span,
-    mitem: &MetaItem,
-    item: &Annotatable,
-    push: &mut dyn FnMut(Annotatable),
-    is_const: bool,
-) {
-    let trait_def = TraitDef {
-        span,
-        path: path_std!(marker::UnsizedConstParamTy),
-        skip_path_as_bound: false,
-        needs_copy_as_bound_if_packed: false,
-        additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
-        supports_unions: false,
-        methods: Vec::new(),
-        associated_types: Vec::new(),
-        is_const,
-        is_staged_api_crate: cx.ecfg.features.staged_api(),
-    };
-
-    trait_def.expand(cx, mitem, item, push);
 }
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 1bcea95fbb7..4541e2cd3b4 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -129,7 +129,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         Clone: clone::expand_deriving_clone,
         Copy: bounds::expand_deriving_copy,
         ConstParamTy: bounds::expand_deriving_const_param_ty,
-        UnsizedConstParamTy: bounds::expand_deriving_unsized_const_param_ty,
         Debug: debug::expand_deriving_debug,
         Default: default::expand_deriving_default,
         Eq: eq::expand_deriving_eq,
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 38c1d3b53e8..b79176e9098 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -240,6 +240,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 }
                 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
                     constraints.extend_from_slice(&[
+                        "~{fflags}".to_string(),
                         "~{vtype}".to_string(),
                         "~{vl}".to_string(),
                         "~{vxsat}".to_string(),
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index f6f2e3f2a3a..f8755874014 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -1,5 +1,5 @@
 use itertools::Itertools as _;
-use rustc_abi::{self as abi, FIRST_VARIANT};
+use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT};
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@@ -25,6 +25,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         match *rvalue {
             mir::Rvalue::Use(ref operand) => {
                 let cg_operand = self.codegen_operand(bx, operand);
+                // Crucially, we do *not* use `OperandValue::Ref` for types with
+                // `BackendRepr::Scalar | BackendRepr::ScalarPair`. This ensures we match the MIR
+                // semantics regarding when assignment operators allow overlap of LHS and RHS.
+                if matches!(
+                    cg_operand.layout.backend_repr,
+                    BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..),
+                ) {
+                    debug_assert!(!matches!(cg_operand.val, OperandValue::Ref(..)));
+                }
                 // FIXME: consider not copying constants through stack. (Fixable by codegen'ing
                 // constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?)
                 cg_operand.val.store(bx, dest);
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index a86fdf80f60..cd34892f029 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -858,7 +858,7 @@ where
     /// Also, if you use this you are responsible for validating that things get copied at the
     /// right type.
     #[instrument(skip(self), level = "trace")]
-    fn copy_op_no_validate(
+    pub(super) fn copy_op_no_validate(
         &mut self,
         src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 23d362de308..46950d60f8c 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -310,7 +310,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         operands: &IndexSlice<FieldIdx, mir::Operand<'tcx>>,
         dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        self.write_uninit(dest)?; // make sure all the padding ends up as uninit
         let (variant_index, variant_dest, active_field_index) = match *kind {
             mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
                 let variant_dest = self.project_downcast(dest, variant_index)?;
@@ -346,9 +345,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             let field_index = active_field_index.unwrap_or(field_index);
             let field_dest = self.project_field(&variant_dest, field_index)?;
             let op = self.eval_operand(operand, Some(field_dest.layout))?;
-            self.copy_op(&op, &field_dest)?;
+            // We validate manually below so we don't have to do it here.
+            self.copy_op_no_validate(&op, &field_dest, /*allow_transmute*/ false)?;
         }
-        self.write_discriminant(variant_index, dest)
+        self.write_discriminant(variant_index, dest)?;
+        // Validate that the entire thing is valid, and reset padding that might be in between the
+        // fields.
+        if M::enforce_validity(self, dest.layout()) {
+            self.validate_operand(
+                dest,
+                M::enforce_validity_recursively(self, dest.layout()),
+                /*reset_provenance_and_padding*/ true,
+            )?;
+        }
+        interp_ok(())
     }
 
     /// Repeats `operand` into the destination. `dest` must have array type, and that type
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 67d2f15d414..2e099a97b65 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -370,7 +370,6 @@ language_item_table! {
     CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait,     GenericRequirement::Exact(0);
 
     ConstParamTy,            sym::const_param_ty,      const_param_ty_trait,       Target::Trait,          GenericRequirement::Exact(0);
-    UnsizedConstParamTy,     sym::unsized_const_param_ty, unsized_const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
 
     Poll,                    sym::Poll,                poll,                       Target::Enum,           GenericRequirement::None;
     PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant,        GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d33f1f3e12a..0a555c7f6e9 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -819,17 +819,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
             let span = tcx.def_span(param.def_id);
             let def_id = param.def_id.expect_local();
 
-            if tcx.features().unsized_const_params() {
-                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
-                    wfcx.register_bound(
-                        ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
-                        wfcx.param_env,
-                        ty,
-                        tcx.require_lang_item(LangItem::UnsizedConstParamTy, span),
-                    );
-                    Ok(())
-                })
-            } else if tcx.features().adt_const_params() {
+            if tcx.features().adt_const_params() {
                 enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
                     wfcx.register_bound(
                         ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
@@ -880,7 +870,6 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
                     tcx,
                     tcx.param_env(param.def_id),
                     ty,
-                    LangItem::ConstParamTy,
                     cause,
                 ) {
                     // Can never implement `ConstParamTy`, don't suggest anything.
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 32b175611ce..0b9a01d6042 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -1,7 +1,6 @@
 //! Check properties that are required by built-in traits and set
 //! up data structures required by type-checking/codegen.
 
-use std::assert_matches::assert_matches;
 use std::collections::BTreeMap;
 
 use rustc_data_structures::fx::FxHashSet;
@@ -40,10 +39,7 @@ pub(super) fn check_trait<'tcx>(
     checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
     checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
     checker.check(lang_items.const_param_ty_trait(), |checker| {
-        visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
-    })?;
-    checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
-        visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
+        visit_implementation_of_const_param_ty(checker)
     })?;
     checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
     checker
@@ -138,12 +134,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
     }
 }
 
-fn visit_implementation_of_const_param_ty(
-    checker: &Checker<'_>,
-    kind: LangItem,
-) -> Result<(), ErrorGuaranteed> {
-    assert_matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
-
+fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
     let tcx = checker.tcx;
     let header = checker.impl_header;
     let impl_did = checker.impl_def_id;
@@ -157,7 +148,7 @@ fn visit_implementation_of_const_param_ty(
     }
 
     let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
-    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, kind, cause) {
+    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
         Ok(()) => Ok(()),
         Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
             let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 44a6084ebd5..7ca8580e098 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1,3 +1,4 @@
+use std::ops::Deref;
 use std::{fmt, iter, mem};
 
 use itertools::Itertools;
@@ -7,7 +8,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, lis
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::{ExprKind, HirId, LangItem, Node, QPath};
+use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath};
 use rustc_hir_analysis::check::potentially_plural_count;
 use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
 use rustc_index::IndexVec;
@@ -565,358 +566,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         tuple_arguments: TupleArgumentsFlag,
     ) -> ErrorGuaranteed {
         // Next, let's construct the error
-        let (error_span, call_ident, full_call_span, call_name, is_method) = match &call_expr.kind {
-            hir::ExprKind::Call(
-                hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
-                _,
-            ) => {
-                if let Res::Def(DefKind::Ctor(of, _), _) =
-                    self.typeck_results.borrow().qpath_res(qpath, *hir_id)
-                {
-                    let name = match of {
-                        CtorOf::Struct => "struct",
-                        CtorOf::Variant => "enum variant",
-                    };
-                    (call_span, None, *span, name, false)
-                } else {
-                    (call_span, None, *span, "function", false)
-                }
-            }
-            hir::ExprKind::Call(hir::Expr { span, .. }, _) => {
-                (call_span, None, *span, "function", false)
-            }
-            hir::ExprKind::MethodCall(path_segment, _, _, span) => {
-                let ident_span = path_segment.ident.span;
-                let ident_span = if let Some(args) = path_segment.args {
-                    ident_span.with_hi(args.span_ext.hi())
-                } else {
-                    ident_span
-                };
-                (*span, Some(path_segment.ident), ident_span, "method", true)
-            }
-            k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
-        };
-        let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
-
-        // Don't print if it has error types or is just plain `_`
-        fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
-            tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
-        }
-
-        let tcx = self.tcx;
-
-        // Get the argument span in the context of the call span so that
-        // suggestions and labels are (more) correct when an arg is a
-        // macro invocation.
-        let normalize_span = |span: Span| -> Span {
-            let normalized_span = span.find_ancestor_inside_same_ctxt(error_span).unwrap_or(span);
-            // Sometimes macros mess up the spans, so do not normalize the
-            // arg span to equal the error span, because that's less useful
-            // than pointing out the arg expr in the wrong context.
-            if normalized_span.source_equal(error_span) { span } else { normalized_span }
-        };
-
-        // Precompute the provided types and spans, since that's all we typically need for below
-        let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
-            .iter()
-            .map(|expr| {
-                let ty = self
-                    .typeck_results
-                    .borrow()
-                    .expr_ty_adjusted_opt(*expr)
-                    .unwrap_or_else(|| Ty::new_misc_error(tcx));
-                (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
-            })
-            .collect();
-        let callee_expr = match &call_expr.peel_blocks().kind {
-            hir::ExprKind::Call(callee, _) => Some(*callee),
-            hir::ExprKind::MethodCall(_, receiver, ..) => {
-                if let Some((DefKind::AssocFn, def_id)) =
-                    self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
-                    && let Some(assoc) = tcx.opt_associated_item(def_id)
-                    && assoc.is_method()
-                {
-                    Some(*receiver)
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        };
-        let callee_ty = callee_expr
-            .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
-
-        // Obtain another method on `Self` that have similar name.
-        let similar_assoc = |call_name: Ident| -> Option<(ty::AssocItem, ty::FnSig<'_>)> {
-            if let Some(callee_ty) = callee_ty
-                && let Ok(Some(assoc)) = self.probe_op(
-                    call_name.span,
-                    MethodCall,
-                    Some(call_name),
-                    None,
-                    IsSuggestion(true),
-                    callee_ty.peel_refs(),
-                    callee_expr.unwrap().hir_id,
-                    TraitsInScope,
-                    |mut ctxt| ctxt.probe_for_similar_candidate(),
-                )
-                && assoc.is_method()
-            {
-                let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
-                let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args);
-
-                self.instantiate_binder_with_fresh_vars(
-                    call_name.span,
-                    BoundRegionConversionTime::FnCall,
-                    fn_sig,
-                );
-            }
-            None
-        };
-
-        let suggest_confusable = |err: &mut Diag<'_>| {
-            let Some(call_name) = call_ident else {
-                return;
-            };
-            let Some(callee_ty) = callee_ty else {
-                return;
-            };
-            let input_types: Vec<Ty<'_>> = provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
-            // Check for other methods in the following order
-            //  - methods marked as `rustc_confusables` with the provided arguments
-            //  - methods with the same argument type/count and short levenshtein distance
-            //  - methods marked as `rustc_confusables` (done)
-            //  - methods with short levenshtein distance
-
-            // Look for commonly confusable method names considering arguments.
-            if let Some(_name) = self.confusable_method_name(
-                err,
-                callee_ty.peel_refs(),
-                call_name,
-                Some(input_types.clone()),
-            ) {
-                return;
-            }
-            // Look for method names with short levenshtein distance, considering arguments.
-            if let Some((assoc, fn_sig)) = similar_assoc(call_name)
-                && fn_sig.inputs()[1..]
-                    .iter()
-                    .zip(input_types.iter())
-                    .all(|(expected, found)| self.may_coerce(*expected, *found))
-                && fn_sig.inputs()[1..].len() == input_types.len()
-            {
-                let assoc_name = assoc.name();
-                err.span_suggestion_verbose(
-                    call_name.span,
-                    format!("you might have meant to use `{}`", assoc_name),
-                    assoc_name,
-                    Applicability::MaybeIncorrect,
-                );
-                return;
-            }
-            // Look for commonly confusable method names disregarding arguments.
-            if let Some(_name) =
-                self.confusable_method_name(err, callee_ty.peel_refs(), call_name, None)
-            {
-                return;
-            }
-            // Look for similarly named methods with levenshtein distance with the right
-            // number of arguments.
-            if let Some((assoc, fn_sig)) = similar_assoc(call_name)
-                && fn_sig.inputs()[1..].len() == input_types.len()
-            {
-                err.span_note(
-                    tcx.def_span(assoc.def_id),
-                    format!(
-                        "there's is a method with similar name `{}`, but the arguments don't match",
-                        assoc.name(),
-                    ),
-                );
-                return;
-            }
-            // Fallthrough: look for similarly named methods with levenshtein distance.
-            if let Some((assoc, _)) = similar_assoc(call_name) {
-                err.span_note(
-                    tcx.def_span(assoc.def_id),
-                    format!(
-                        "there's is a method with similar name `{}`, but their argument count \
-                         doesn't match",
-                        assoc.name(),
-                    ),
-                );
-                return;
-            }
-        };
-        // A "softer" version of the `demand_compatible`, which checks types without persisting them,
-        // and treats error types differently
-        // This will allow us to "probe" for other argument orders that would likely have been correct
-        let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
-            if provided_idx.as_usize() == expected_idx.as_usize() {
-                return compatibility_diagonal[provided_idx].clone();
-            }
-
-            let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
-            // If either is an error type, we defy the usual convention and consider them to *not* be
-            // coercible. This prevents our error message heuristic from trying to pass errors into
-            // every argument.
-            if (formal_input_ty, expected_input_ty).references_error() {
-                return Compatibility::Incompatible(None);
-            }
 
-            let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
-
-            let expectation = Expectation::rvalue_hint(self, expected_input_ty);
-            let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
-            let can_coerce = self.may_coerce(arg_ty, coerced_ty);
-            if !can_coerce {
-                return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
-                    ty::error::ExpectedFound::new(coerced_ty, arg_ty),
-                )));
-            }
-
-            // Using probe here, since we don't want this subtyping to affect inference.
-            let subtyping_error = self.probe(|_| {
-                self.at(&self.misc(arg_span), self.param_env)
-                    .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
-                    .err()
-            });
-
-            // Same as above: if either the coerce type or the checked type is an error type,
-            // consider them *not* compatible.
-            let references_error = (coerced_ty, arg_ty).references_error();
-            match (references_error, subtyping_error) {
-                (false, None) => Compatibility::Compatible,
-                (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
-            }
-        };
-
-        let mk_trace = |span, (formal_ty, expected_ty), provided_ty| {
-            let mismatched_ty = if expected_ty == provided_ty {
-                // If expected == provided, then we must have failed to sup
-                // the formal type. Avoid printing out "expected Ty, found Ty"
-                // in that case.
-                formal_ty
-            } else {
-                expected_ty
-            };
-            TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
-        };
-
-        // The algorithm here is inspired by levenshtein distance and longest common subsequence.
-        // We'll try to detect 4 different types of mistakes:
-        // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
-        // - An input is missing, which isn't satisfied by *any* of the other arguments
-        // - Some number of arguments have been provided in the wrong order
-        // - A type is straight up invalid
-
-        // First, let's find the errors
-        let (mut errors, matched_inputs) =
-            ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
-                .find_errors();
+        let mut fn_call_diag_ctxt = FnCallDiagCtxt::new(
+            self,
+            compatibility_diagonal,
+            formal_and_expected_inputs,
+            provided_args,
+            c_variadic,
+            err_code,
+            fn_def_id,
+            call_span,
+            call_expr,
+            tuple_arguments,
+        );
 
         // First, check if we just need to wrap some arguments in a tuple.
-        if let Some((mismatch_idx, terr)) =
-            compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
-                if let Compatibility::Incompatible(Some(terr)) = c {
-                    Some((i, *terr))
-                } else {
-                    None
-                }
-            })
-        {
-            // Is the first bad expected argument a tuple?
-            // Do we have as many extra provided arguments as the tuple's length?
-            // If so, we might have just forgotten to wrap some args in a tuple.
-            if let Some(ty::Tuple(tys)) =
-                formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
-                // If the tuple is unit, we're not actually wrapping any arguments.
-                && !tys.is_empty()
-                && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
-            {
-                // Wrap up the N provided arguments starting at this position in a tuple.
-                let provided_args_to_tuple = &provided_arg_tys[mismatch_idx..];
-                let (provided_args_to_tuple, provided_args_after_tuple) =
-                    provided_args_to_tuple.split_at(tys.len());
-                let provided_as_tuple =
-                    Ty::new_tup_from_iter(tcx, provided_args_to_tuple.iter().map(|&(ty, _)| ty));
-
-                let mut satisfied = true;
-                // Check if the newly wrapped tuple + rest of the arguments are compatible.
-                for ((_, expected_ty), provided_ty) in std::iter::zip(
-                    formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
-                    [provided_as_tuple]
-                        .into_iter()
-                        .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
-                ) {
-                    if !self.may_coerce(provided_ty, *expected_ty) {
-                        satisfied = false;
-                        break;
-                    }
-                }
+        if let Some(err) = fn_call_diag_ctxt.check_wrap_args_in_tuple() {
+            return err;
+        }
 
-                // If they're compatible, suggest wrapping in an arg, and we're done!
-                // Take some care with spans, so we don't suggest wrapping a macro's
-                // innards in parenthesis, for example.
-                if satisfied
-                    && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
-                {
-                    let mut err;
-                    if tys.len() == 1 {
-                        // A tuple wrap suggestion actually occurs within,
-                        // so don't do anything special here.
-                        err = self.err_ctxt().report_and_explain_type_error(
-                            mk_trace(
-                                lo,
-                                formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
-                                provided_arg_tys[mismatch_idx].0,
-                            ),
-                            self.param_env,
-                            terr,
-                        );
-                        err.span_label(
-                            full_call_span,
-                            format!("arguments to this {call_name} are incorrect"),
-                        );
-                    } else {
-                        err = self.dcx().struct_span_err(
-                            full_call_span,
-                            format!(
-                                "{call_name} takes {}{} but {} {} supplied",
-                                if c_variadic { "at least " } else { "" },
-                                potentially_plural_count(
-                                    formal_and_expected_inputs.len(),
-                                    "argument"
-                                ),
-                                potentially_plural_count(provided_args.len(), "argument"),
-                                pluralize!("was", provided_args.len())
-                            ),
-                        );
-                        err.code(err_code.to_owned());
-                        err.multipart_suggestion_verbose(
-                            "wrap these arguments in parentheses to construct a tuple",
-                            vec![
-                                (lo.shrink_to_lo(), "(".to_string()),
-                                (hi.shrink_to_hi(), ")".to_string()),
-                            ],
-                            Applicability::MachineApplicable,
-                        );
-                    };
-                    self.label_fn_like(
-                        &mut err,
-                        fn_def_id,
-                        callee_ty,
-                        call_expr,
-                        None,
-                        Some(mismatch_idx.as_usize()),
-                        &matched_inputs,
-                        &formal_and_expected_inputs,
-                        is_method,
-                        tuple_arguments,
-                    );
-                    suggest_confusable(&mut err);
-                    return err.emit();
-                }
-            }
+        if let Some(fallback_error) = fn_call_diag_ctxt.ensure_has_errors() {
+            return fallback_error;
         }
 
         // Okay, so here's where it gets complicated in regards to what errors
@@ -926,608 +596,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //   2) Valid but incorrect arguments
         //   3) Invalid arguments
         //      - Currently I think this only comes up with `CyclicTy`
-        //
+
         // We first need to go through, remove those from (3) and emit those
         // as their own error, particularly since they're error code and
         // message is special. From what I can tell, we *must* emit these
         // here (vs somewhere prior to this function) since the arguments
         // become invalid *because* of how they get used in the function.
         // It is what it is.
-
-        if errors.is_empty() {
-            if cfg!(debug_assertions) {
-                span_bug!(error_span, "expected errors from argument matrix");
-            } else {
-                let mut err =
-                    self.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
-                suggest_confusable(&mut err);
-                return err.emit();
-            }
+        if let Some(err) = fn_call_diag_ctxt.filter_out_invalid_arguments()
+            && fn_call_diag_ctxt.errors.is_empty()
+        {
+            // We're done if we found errors, but we already emitted them.
+            return err;
         }
 
-        let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
-            if let ty::Adt(adt, _) = ty.kind()
-                && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
-                && let hir::ExprKind::Struct(
-                    hir::QPath::LangItem(hir::LangItem::RangeFull, _),
-                    [],
-                    _,
-                ) = expr.kind
-            {
-                // We have `Foo(a, .., c)`, where the user might be trying to use the "rest" syntax
-                // from default field values, which is not supported on tuples.
-                let explanation = if self.tcx.features().default_field_values() {
-                    "this is only supported on non-tuple struct literals"
-                } else if self.tcx.sess.is_nightly_build() {
-                    "this is only supported on non-tuple struct literals when \
-                     `#![feature(default_field_values)]` is enabled"
-                } else {
-                    "this is not supported"
-                };
-                let msg = format!(
-                    "you might have meant to use `..` to skip providing a value for \
-                     expected fields, but {explanation}; it is instead interpreted as a \
-                     `std::ops::RangeFull` literal",
-                );
-                err.span_help(expr.span, msg);
-            }
-        };
+        assert!(!fn_call_diag_ctxt.errors.is_empty());
 
-        let mut reported = None;
-        errors.retain(|error| {
-            let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
-                error
-            else {
-                return true;
-            };
-            let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
-            let trace =
-                mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
-            if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
-                let mut err =
-                    self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *e);
-                suggest_confusable(&mut err);
-                reported = Some(err.emit());
-                return false;
-            }
-            true
-        });
-
-        // We're done if we found errors, but we already emitted them.
-        if let Some(reported) = reported
-            && errors.is_empty()
-        {
-            return reported;
+        // Last special case: if there is only one "Incompatible" error, just emit that
+        if let Some(err) = fn_call_diag_ctxt.check_single_incompatible() {
+            return err;
         }
-        assert!(!errors.is_empty());
 
         // Okay, now that we've emitted the special errors separately, we
         // are only left missing/extra/swapped and mismatched arguments, both
         // can be collated pretty easily if needed.
 
-        // Next special case: if there is only one "Incompatible" error, just emit that
-        if let &[
-            Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
-        ] = &errors[..]
-        {
-            let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
-            let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx];
-            let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
-            let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
-            self.emit_coerce_suggestions(
-                &mut err,
-                provided_args[provided_idx],
-                provided_ty,
-                Expectation::rvalue_hint(self, expected_ty)
-                    .only_has_type(self)
-                    .unwrap_or(formal_ty),
-                None,
-                None,
-            );
-            err.span_label(full_call_span, format!("arguments to this {call_name} are incorrect"));
-
-            self.label_generic_mismatches(
-                &mut err,
-                fn_def_id,
-                &matched_inputs,
-                &provided_arg_tys,
-                &formal_and_expected_inputs,
-                is_method,
-            );
-
-            if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
-                && provided_idx.as_usize() == expected_idx.as_usize()
-            {
-                self.note_source_of_type_mismatch_constraint(
-                    &mut err,
-                    rcvr,
-                    crate::demand::TypeMismatchSource::Arg {
-                        call_expr,
-                        incompatible_arg: provided_idx.as_usize(),
-                    },
-                );
-            }
-
-            self.suggest_ptr_null_mut(
-                expected_ty,
-                provided_ty,
-                provided_args[provided_idx],
-                &mut err,
-            );
-
-            self.suggest_deref_unwrap_or(
-                &mut err,
-                callee_ty,
-                call_ident,
-                expected_ty,
-                provided_ty,
-                provided_args[provided_idx],
-                is_method,
-            );
-
-            // Call out where the function is defined
-            self.label_fn_like(
-                &mut err,
-                fn_def_id,
-                callee_ty,
-                call_expr,
-                Some(expected_ty),
-                Some(expected_idx.as_usize()),
-                &matched_inputs,
-                &formal_and_expected_inputs,
-                is_method,
-                tuple_arguments,
-            );
-            suggest_confusable(&mut err);
-            detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
-            return err.emit();
-        }
-
         // Special case, we found an extra argument is provided, which is very common in practice.
         // but there is a obviously better removing suggestion compared to the current one,
         // try to find the argument with Error type, if we removed it all the types will become good,
         // then we will replace the current suggestion.
-        if let [Error::Extra(provided_idx)] = &errors[..] {
-            let remove_idx_is_perfect = |idx: usize| -> bool {
-                let removed_arg_tys = provided_arg_tys
-                    .iter()
-                    .enumerate()
-                    .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
-                    .collect::<IndexVec<ProvidedIdx, _>>();
-                std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
-                    |((expected_ty, _), (provided_ty, _))| {
-                        !provided_ty.references_error()
-                            && self.may_coerce(*provided_ty, *expected_ty)
-                    },
-                )
-            };
+        fn_call_diag_ctxt.maybe_optimize_extra_arg_suggestion();
 
-            if !remove_idx_is_perfect(provided_idx.as_usize()) {
-                if let Some(i) = (0..provided_args.len()).find(|&i| remove_idx_is_perfect(i)) {
-                    errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
-                }
-            }
-        }
+        let mut err = fn_call_diag_ctxt.initial_final_diagnostic();
+        fn_call_diag_ctxt.suggest_confusable(&mut err);
 
-        let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
-            struct_span_code_err!(
-                self.dcx(),
-                full_call_span,
-                E0308,
-                "arguments to this {} are incorrect",
-                call_name,
-            )
-        } else {
-            self.dcx()
-                .struct_span_err(
-                    full_call_span,
-                    format!(
-                        "this {} takes {}{} but {} {} supplied",
-                        call_name,
-                        if c_variadic { "at least " } else { "" },
-                        potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
-                        potentially_plural_count(provided_args.len(), "argument"),
-                        pluralize!("was", provided_args.len())
-                    ),
-                )
-                .with_code(err_code.to_owned())
-        };
+        // As we encounter issues, keep track of what we want to provide for the suggestion.
 
-        suggest_confusable(&mut err);
-        // As we encounter issues, keep track of what we want to provide for the suggestion
-        let mut labels = vec![];
-        // If there is a single error, we give a specific suggestion; otherwise, we change to
-        // "did you mean" with the suggested function call
-        enum SuggestionText {
-            None,
-            Provide(bool),
-            Remove(bool),
-            Swap,
-            Reorder,
-            DidYouMean,
-        }
-        let mut suggestion_text = SuggestionText::None;
-
-        let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| {
-            if ty.is_unit() {
-                "()".to_string()
-            } else if ty.is_suggestable(tcx, false) {
-                format!("/* {ty} */")
-            } else if let Some(fn_def_id) = fn_def_id
-                && self.tcx.def_kind(fn_def_id).is_fn_like()
-                && let self_implicit =
-                    matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
-                && let Some(Some(arg)) =
-                    self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
-                && arg.name != kw::SelfLower
-            {
-                format!("/* {} */", arg.name)
-            } else {
-                "/* value */".to_string()
-            }
-        };
-
-        let mut errors = errors.into_iter().peekable();
-        let mut only_extras_so_far = errors
-            .peek()
-            .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
-        let mut prev_extra_idx = None;
-        let mut suggestions = vec![];
-        while let Some(error) = errors.next() {
-            only_extras_so_far &= matches!(error, Error::Extra(_));
-
-            match error {
-                Error::Invalid(provided_idx, expected_idx, compatibility) => {
-                    let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
-                    let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
-                    if let Compatibility::Incompatible(error) = compatibility {
-                        let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
-                        if let Some(e) = error {
-                            self.err_ctxt().note_type_err(
-                                &mut err,
-                                &trace.cause,
-                                None,
-                                Some(self.param_env.and(trace.values)),
-                                e,
-                                true,
-                                None,
-                            );
-                        }
-                    }
+        let (mut suggestions, labels, suggestion_text) =
+            fn_call_diag_ctxt.labels_and_suggestion_text(&mut err);
 
-                    self.emit_coerce_suggestions(
-                        &mut err,
-                        provided_args[provided_idx],
-                        provided_ty,
-                        Expectation::rvalue_hint(self, expected_ty)
-                            .only_has_type(self)
-                            .unwrap_or(formal_ty),
-                        None,
-                        None,
-                    );
-                    detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
-                }
-                Error::Extra(arg_idx) => {
-                    let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
-                    let provided_ty_name = if !has_error_or_infer([provided_ty]) {
-                        // FIXME: not suggestable, use something else
-                        format!(" of type `{provided_ty}`")
-                    } else {
-                        "".to_string()
-                    };
-                    let idx = if provided_arg_tys.len() == 1 {
-                        "".to_string()
-                    } else {
-                        format!(" #{}", arg_idx.as_usize() + 1)
-                    };
-                    labels.push((
-                        provided_span,
-                        format!("unexpected argument{idx}{provided_ty_name}"),
-                    ));
-                    let mut span = provided_span;
-                    if span.can_be_used_for_suggestions()
-                        && error_span.can_be_used_for_suggestions()
-                    {
-                        if arg_idx.index() > 0
-                            && let Some((_, prev)) =
-                                provided_arg_tys.get(ProvidedIdx::from_usize(arg_idx.index() - 1))
-                        {
-                            // Include previous comma
-                            span = prev.shrink_to_hi().to(span);
-                        }
-
-                        // Is last argument for deletion in a row starting from the 0-th argument?
-                        // Then delete the next comma, so we are not left with `f(, ...)`
-                        //
-                        //     fn f() {}
-                        //   - f(0, 1,)
-                        //   + f()
-                        let trim_next_comma = match errors.peek() {
-                            Some(Error::Extra(provided_idx))
-                                if only_extras_so_far
-                                    && provided_idx.index() > arg_idx.index() + 1 =>
-                            // If the next Error::Extra ("next") doesn't next to current ("current"),
-                            // fn foo(_: (), _: u32) {}
-                            // - foo("current", (), 1u32, "next")
-                            // + foo((), 1u32)
-                            // If the previous error is not a `Error::Extra`, then do not trim the next comma
-                            // - foo((), "current", 42u32, "next")
-                            // + foo((), 42u32)
-                            {
-                                prev_extra_idx.is_none_or(|prev_extra_idx| {
-                                    prev_extra_idx + 1 == arg_idx.index()
-                                })
-                            }
-                            // If no error left, we need to delete the next comma
-                            None if only_extras_so_far => true,
-                            // Not sure if other error type need to be handled as well
-                            _ => false,
-                        };
-
-                        if trim_next_comma {
-                            let next = provided_arg_tys
-                                .get(arg_idx + 1)
-                                .map(|&(_, sp)| sp)
-                                .unwrap_or_else(|| {
-                                    // Try to move before `)`. Note that `)` here is not necessarily
-                                    // the latin right paren, it could be a Unicode-confusable that
-                                    // looks like a `)`, so we must not use `- BytePos(1)`
-                                    // manipulations here.
-                                    self.tcx().sess.source_map().end_point(call_expr.span)
-                                });
-
-                            // Include next comma
-                            span = span.until(next);
-                        }
-
-                        suggestions.push((span, String::new()));
-
-                        suggestion_text = match suggestion_text {
-                            SuggestionText::None => SuggestionText::Remove(false),
-                            SuggestionText::Remove(_) => SuggestionText::Remove(true),
-                            _ => SuggestionText::DidYouMean,
-                        };
-                        prev_extra_idx = Some(arg_idx.index())
-                    }
-                    detect_dotdot(&mut err, provided_ty, provided_args[arg_idx]);
-                }
-                Error::Missing(expected_idx) => {
-                    // If there are multiple missing arguments adjacent to each other,
-                    // then we can provide a single error.
-
-                    let mut missing_idxs = vec![expected_idx];
-                    while let Some(e) = errors.next_if(|e| {
-                        matches!(e, Error::Missing(next_expected_idx)
-                            if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
-                    }) {
-                        match e {
-                            Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
-                            _ => unreachable!(
-                                "control flow ensures that we should always get an `Error::Missing`"
-                            ),
-                        }
-                    }
-
-                    // NOTE: Because we might be re-arranging arguments, might have extra
-                    // arguments, etc. it's hard to *really* know where we should provide
-                    // this error label, so as a heuristic, we point to the provided arg, or
-                    // to the call if the missing inputs pass the provided args.
-                    match &missing_idxs[..] {
-                        &[expected_idx] => {
-                            let (_, input_ty) = formal_and_expected_inputs[expected_idx];
-                            let span = if let Some((_, arg_span)) =
-                                provided_arg_tys.get(expected_idx.to_provided_idx())
-                            {
-                                *arg_span
-                            } else {
-                                args_span
-                            };
-                            let rendered = if !has_error_or_infer([input_ty]) {
-                                format!(" of type `{input_ty}`")
-                            } else {
-                                "".to_string()
-                            };
-                            labels.push((
-                                span,
-                                format!(
-                                    "argument #{}{rendered} is missing",
-                                    expected_idx.as_usize() + 1
-                                ),
-                            ));
-
-                            suggestion_text = match suggestion_text {
-                                SuggestionText::None => SuggestionText::Provide(false),
-                                SuggestionText::Provide(_) => SuggestionText::Provide(true),
-                                _ => SuggestionText::DidYouMean,
-                            };
-                        }
-                        &[first_idx, second_idx] => {
-                            let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
-                            let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
-                            let span = if let (Some((_, first_span)), Some((_, second_span))) = (
-                                provided_arg_tys.get(first_idx.to_provided_idx()),
-                                provided_arg_tys.get(second_idx.to_provided_idx()),
-                            ) {
-                                first_span.to(*second_span)
-                            } else {
-                                args_span
-                            };
-                            let rendered =
-                                if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
-                                    format!(
-                                        " of type `{first_expected_ty}` and `{second_expected_ty}`"
-                                    )
-                                } else {
-                                    "".to_string()
-                                };
-                            labels.push((span, format!("two arguments{rendered} are missing")));
-                            suggestion_text = match suggestion_text {
-                                SuggestionText::None | SuggestionText::Provide(_) => {
-                                    SuggestionText::Provide(true)
-                                }
-                                _ => SuggestionText::DidYouMean,
-                            };
-                        }
-                        &[first_idx, second_idx, third_idx] => {
-                            let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
-                            let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
-                            let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
-                            let span = if let (Some((_, first_span)), Some((_, third_span))) = (
-                                provided_arg_tys.get(first_idx.to_provided_idx()),
-                                provided_arg_tys.get(third_idx.to_provided_idx()),
-                            ) {
-                                first_span.to(*third_span)
-                            } else {
-                                args_span
-                            };
-                            let rendered = if !has_error_or_infer([
-                                first_expected_ty,
-                                second_expected_ty,
-                                third_expected_ty,
-                            ]) {
-                                format!(
-                                    " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
-                                )
-                            } else {
-                                "".to_string()
-                            };
-                            labels.push((span, format!("three arguments{rendered} are missing")));
-                            suggestion_text = match suggestion_text {
-                                SuggestionText::None | SuggestionText::Provide(_) => {
-                                    SuggestionText::Provide(true)
-                                }
-                                _ => SuggestionText::DidYouMean,
-                            };
-                        }
-                        missing_idxs => {
-                            let first_idx = *missing_idxs.first().unwrap();
-                            let last_idx = *missing_idxs.last().unwrap();
-                            // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
-                            // It's hard to *really* know where we should provide this error label, so this is a
-                            // decent heuristic
-                            let span = if let (Some((_, first_span)), Some((_, last_span))) = (
-                                provided_arg_tys.get(first_idx.to_provided_idx()),
-                                provided_arg_tys.get(last_idx.to_provided_idx()),
-                            ) {
-                                first_span.to(*last_span)
-                            } else {
-                                args_span
-                            };
-                            labels.push((span, "multiple arguments are missing".to_string()));
-                            suggestion_text = match suggestion_text {
-                                SuggestionText::None | SuggestionText::Provide(_) => {
-                                    SuggestionText::Provide(true)
-                                }
-                                _ => SuggestionText::DidYouMean,
-                            };
-                        }
-                    }
-                }
-                Error::Swap(
-                    first_provided_idx,
-                    second_provided_idx,
-                    first_expected_idx,
-                    second_expected_idx,
-                ) => {
-                    let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
-                    let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
-                    let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
-                        format!(", found `{first_provided_ty}`")
-                    } else {
-                        String::new()
-                    };
-                    labels.push((
-                        first_span,
-                        format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
-                    ));
-
-                    let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
-                    let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
-                    let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
-                        format!(", found `{second_provided_ty}`")
-                    } else {
-                        String::new()
-                    };
-                    labels.push((
-                        second_span,
-                        format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
-                    ));
-
-                    suggestion_text = match suggestion_text {
-                        SuggestionText::None => SuggestionText::Swap,
-                        _ => SuggestionText::DidYouMean,
-                    };
-                }
-                Error::Permutation(args) => {
-                    for (dst_arg, dest_input) in args {
-                        let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
-                        let (provided_ty, provided_span) = provided_arg_tys[dest_input];
-                        let provided_ty_name = if !has_error_or_infer([provided_ty]) {
-                            format!(", found `{provided_ty}`")
-                        } else {
-                            String::new()
-                        };
-                        labels.push((
-                            provided_span,
-                            format!("expected `{expected_ty}`{provided_ty_name}"),
-                        ));
-                    }
-
-                    suggestion_text = match suggestion_text {
-                        SuggestionText::None => SuggestionText::Reorder,
-                        _ => SuggestionText::DidYouMean,
-                    };
-                }
-            }
-        }
-
-        self.label_generic_mismatches(
-            &mut err,
-            fn_def_id,
-            &matched_inputs,
-            &provided_arg_tys,
-            &formal_and_expected_inputs,
-            is_method,
-        );
-
-        // Incorporate the argument changes in the removal suggestion.
-        // When a type is *missing*, and the rest are additional, we want to suggest these with a
-        // multipart suggestion, but in order to do so we need to figure out *where* the arg that
-        // was provided but had the wrong type should go, because when looking at `expected_idx`
-        // that is the position in the argument list in the definition, while `provided_idx` will
-        // not be present. So we have to look at what the *last* provided position was, and point
-        // one after to suggest the replacement. FIXME(estebank): This is hacky, and there's
-        // probably a better more involved change we can make to make this work.
-        // For example, if we have
-        // ```
-        // fn foo(i32, &'static str) {}
-        // foo((), (), ());
-        // ```
-        // what should be suggested is
-        // ```
-        // foo(/* i32 */, /* &str */);
-        // ```
-        // which includes the replacement of the first two `()` for the correct type, and the
-        // removal of the last `()`.
-        let mut prev = -1;
-        for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
-            // We want to point not at the *current* argument expression index, but rather at the
-            // index position where it *should have been*, which is *after* the previous one.
-            if let Some(provided_idx) = provided_idx {
-                prev = provided_idx.index() as i64;
-                continue;
-            }
-            let idx = ProvidedIdx::from_usize((prev + 1) as usize);
-            if let Some((_, arg_span)) = provided_arg_tys.get(idx) {
-                prev += 1;
-                // There is a type that was *not* found anywhere, so it isn't a move, but a
-                // replacement and we look at what type it should have been. This will allow us
-                // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
-                // was `fn foo(())`.
-                let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
-                suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
-            }
-        }
+        fn_call_diag_ctxt.label_generic_mismatches(&mut err);
+        fn_call_diag_ctxt.append_arguments_changes(&mut suggestions);
 
         // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
         if labels.len() <= 5 {
@@ -1537,113 +646,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // Call out where the function is defined
-        self.label_fn_like(
+        fn_call_diag_ctxt.label_fn_like(
             &mut err,
             fn_def_id,
-            callee_ty,
+            fn_call_diag_ctxt.callee_ty,
             call_expr,
             None,
             None,
-            &matched_inputs,
-            &formal_and_expected_inputs,
-            is_method,
+            &fn_call_diag_ctxt.matched_inputs,
+            &fn_call_diag_ctxt.formal_and_expected_inputs,
+            fn_call_diag_ctxt.call_metadata.is_method,
             tuple_arguments,
         );
 
         // And add a suggestion block for all of the parameters
-        let suggestion_text = match suggestion_text {
-            SuggestionText::None => None,
-            SuggestionText::Provide(plural) => {
-                Some(format!("provide the argument{}", if plural { "s" } else { "" }))
-            }
-            SuggestionText::Remove(plural) => {
-                err.multipart_suggestion_verbose(
-                    format!("remove the extra argument{}", if plural { "s" } else { "" }),
-                    suggestions,
-                    Applicability::HasPlaceholders,
-                );
-                None
-            }
-            SuggestionText::Swap => Some("swap these arguments".to_string()),
-            SuggestionText::Reorder => Some("reorder these arguments".to_string()),
-            SuggestionText::DidYouMean => Some("did you mean".to_string()),
-        };
-        if let Some(suggestion_text) = suggestion_text
-            && !full_call_span.in_external_macro(self.sess().source_map())
+        if let Some(suggestion_message) =
+            FnCallDiagCtxt::format_suggestion_text(&mut err, suggestions, suggestion_text)
+            && !fn_call_diag_ctxt.call_is_in_macro()
         {
-            let source_map = self.sess().source_map();
-            let suggestion_span = if let Some(args_span) = error_span.trim_start(full_call_span) {
-                // Span of the braces, e.g. `(a, b, c)`.
-                args_span
-            } else {
-                // The arg span of a function call that wasn't even given braces
-                // like what might happen with delegation reuse.
-                // e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`.
-                full_call_span.shrink_to_hi()
-            };
-
-            // Controls how the arguments should be listed in the suggestion.
-            enum ArgumentsFormatting {
-                SingleLine,
-                Multiline { fallback_indent: String, brace_indent: String },
-            }
-            let arguments_formatting = {
-                let mut provided_inputs = matched_inputs.iter().filter_map(|a| *a);
-                if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
-                    && let Some(first_idx) = provided_inputs.by_ref().next()
-                    && let Some(last_idx) = provided_inputs.by_ref().next()
-                    && let (_, first_span) = provided_arg_tys[first_idx]
-                    && let (_, last_span) = provided_arg_tys[last_idx]
-                    && source_map.is_multiline(first_span.to(last_span))
-                    && let Some(fallback_indent) = source_map.indentation_before(first_span)
-                {
-                    ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
-                } else {
-                    ArgumentsFormatting::SingleLine
-                }
-            };
+            let (suggestion_span, suggestion_code) = fn_call_diag_ctxt.suggestion_code();
 
-            let mut suggestion = "(".to_owned();
-            let mut needs_comma = false;
-            for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
-                if needs_comma {
-                    suggestion += ",";
-                }
-                match &arguments_formatting {
-                    ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
-                    ArgumentsFormatting::SingleLine => {}
-                    ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
-                }
-                needs_comma = true;
-                let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
-                    && let (_, provided_span) = provided_arg_tys[*provided_idx]
-                    && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
-                {
-                    (Some(provided_span), arg_text)
-                } else {
-                    // Propose a placeholder of the correct type
-                    let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
-                    (None, ty_to_snippet(expected_ty, expected_idx))
-                };
-                if let ArgumentsFormatting::Multiline { fallback_indent, .. } =
-                    &arguments_formatting
-                {
-                    let indent = suggestion_span
-                        .and_then(|span| source_map.indentation_before(span))
-                        .unwrap_or_else(|| fallback_indent.clone());
-                    suggestion += &indent;
-                }
-                suggestion += &suggestion_text;
-            }
-            if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
-                suggestion += ",\n";
-                suggestion += &brace_indent;
-            }
-            suggestion += ")";
             err.span_suggestion_verbose(
                 suggestion_span,
-                suggestion_text,
-                suggestion,
+                suggestion_message,
+                suggestion_code,
                 Applicability::HasPlaceholders,
             );
         }
@@ -2836,3 +1862,1333 @@ impl FnParam<'_> {
         D(*self, idx)
     }
 }
+
+struct FnCallDiagCtxt<'a, 'b, 'tcx> {
+    arg_matching_ctxt: ArgMatchingCtxt<'a, 'b, 'tcx>,
+    errors: Vec<Error<'tcx>>,
+    matched_inputs: IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
+}
+
+impl<'a, 'b, 'tcx> Deref for FnCallDiagCtxt<'a, 'b, 'tcx> {
+    type Target = ArgMatchingCtxt<'a, 'b, 'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.arg_matching_ctxt
+    }
+}
+
+// Controls how the arguments should be listed in the suggestion.
+enum ArgumentsFormatting {
+    SingleLine,
+    Multiline { fallback_indent: String, brace_indent: String },
+}
+
+impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> {
+    fn new(
+        arg: &'a FnCtxt<'b, 'tcx>,
+        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
+        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
+        provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
+        c_variadic: bool,
+        err_code: ErrCode,
+        fn_def_id: Option<DefId>,
+        call_span: Span,
+        call_expr: &'tcx Expr<'tcx>,
+        tuple_arguments: TupleArgumentsFlag,
+    ) -> Self {
+        let arg_matching_ctxt = ArgMatchingCtxt::new(
+            arg,
+            compatibility_diagonal,
+            formal_and_expected_inputs,
+            provided_args,
+            c_variadic,
+            err_code,
+            fn_def_id,
+            call_span,
+            call_expr,
+            tuple_arguments,
+        );
+
+        // The algorithm here is inspired by levenshtein distance and longest common subsequence.
+        // We'll try to detect 4 different types of mistakes:
+        // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
+        // - An input is missing, which isn't satisfied by *any* of the other arguments
+        // - Some number of arguments have been provided in the wrong order
+        // - A type is straight up invalid
+        let (errors, matched_inputs) = ArgMatrix::new(
+            arg_matching_ctxt.provided_args.len(),
+            arg_matching_ctxt.formal_and_expected_inputs.len(),
+            |provided, expected| arg_matching_ctxt.check_compatible(provided, expected),
+        )
+        .find_errors();
+
+        FnCallDiagCtxt { arg_matching_ctxt, errors, matched_inputs }
+    }
+
+    fn check_wrap_args_in_tuple(&self) -> Option<ErrorGuaranteed> {
+        if let Some((mismatch_idx, terr)) = self.first_incompatible_error() {
+            // Is the first bad expected argument a tuple?
+            // Do we have as many extra provided arguments as the tuple's length?
+            // If so, we might have just forgotten to wrap some args in a tuple.
+            if let Some(ty::Tuple(tys)) =
+               self.formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
+                // If the tuple is unit, we're not actually wrapping any arguments.
+                && !tys.is_empty()
+                && self.provided_arg_tys.len() == self.formal_and_expected_inputs.len() - 1 + tys.len()
+            {
+                // Wrap up the N provided arguments starting at this position in a tuple.
+                let provided_args_to_tuple = &self.provided_arg_tys[mismatch_idx..];
+                let (provided_args_to_tuple, provided_args_after_tuple) =
+                    provided_args_to_tuple.split_at(tys.len());
+                let provided_as_tuple = Ty::new_tup_from_iter(
+                    self.tcx,
+                    provided_args_to_tuple.iter().map(|&(ty, _)| ty),
+                );
+
+                let mut satisfied = true;
+                // Check if the newly wrapped tuple + rest of the arguments are compatible.
+                for ((_, expected_ty), provided_ty) in std::iter::zip(
+                    self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
+                    [provided_as_tuple]
+                        .into_iter()
+                        .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
+                ) {
+                    if !self.may_coerce(provided_ty, *expected_ty) {
+                        satisfied = false;
+                        break;
+                    }
+                }
+
+                // If they're compatible, suggest wrapping in an arg, and we're done!
+                // Take some care with spans, so we don't suggest wrapping a macro's
+                // innards in parenthesis, for example.
+                if satisfied
+                    && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
+                {
+                    let mut err;
+                    if tys.len() == 1 {
+                        // A tuple wrap suggestion actually occurs within,
+                        // so don't do anything special here.
+                        err = self.err_ctxt().report_and_explain_type_error(
+                            self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
+                                lo,
+                                self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
+                                self.provided_arg_tys[mismatch_idx].0,
+                            ),
+                            self.param_env,
+                            terr,
+                        );
+                        let call_name = self.call_metadata.call_name;
+                        err.span_label(
+                            self.call_metadata.full_call_span,
+                            format!("arguments to this {call_name} are incorrect"),
+                        );
+                    } else {
+                        let call_name = self.call_metadata.call_name;
+                        err = self.dcx().struct_span_err(
+                            self.arg_matching_ctxt.args_ctxt.call_metadata.full_call_span,
+                            format!(
+                                "{call_name} takes {}{} but {} {} supplied",
+                                if self.c_variadic { "at least " } else { "" },
+                                potentially_plural_count(
+                                    self.formal_and_expected_inputs.len(),
+                                    "argument"
+                                ),
+                                potentially_plural_count(self.provided_args.len(), "argument"),
+                                pluralize!("was", self.provided_args.len())
+                            ),
+                        );
+                        err.code(self.err_code.to_owned());
+                        err.multipart_suggestion_verbose(
+                            "wrap these arguments in parentheses to construct a tuple",
+                            vec![
+                                (lo.shrink_to_lo(), "(".to_string()),
+                                (hi.shrink_to_hi(), ")".to_string()),
+                            ],
+                            Applicability::MachineApplicable,
+                        );
+                    };
+                    self.arg_matching_ctxt.args_ctxt.call_ctxt.fn_ctxt.label_fn_like(
+                        &mut err,
+                        self.fn_def_id,
+                        self.callee_ty,
+                        self.call_expr,
+                        None,
+                        Some(mismatch_idx.as_usize()),
+                        &self.matched_inputs,
+                        &self.formal_and_expected_inputs,
+                        self.call_metadata.is_method,
+                        self.tuple_arguments,
+                    );
+                    self.suggest_confusable(&mut err);
+                    Some(err.emit())
+                } else {
+                    None
+                }
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
+    fn ensure_has_errors(&self) -> Option<ErrorGuaranteed> {
+        if self.errors.is_empty() {
+            if cfg!(debug_assertions) {
+                span_bug!(self.call_metadata.error_span, "expected errors from argument matrix");
+            } else {
+                let mut err = self.dcx().create_err(errors::ArgMismatchIndeterminate {
+                    span: self.call_metadata.error_span,
+                });
+                self.arg_matching_ctxt.suggest_confusable(&mut err);
+                return Some(err.emit());
+            }
+        }
+
+        None
+    }
+
+    fn detect_dotdot(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'tcx>) {
+        if let ty::Adt(adt, _) = ty.kind()
+            && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
+            && let hir::ExprKind::Struct(hir::QPath::LangItem(hir::LangItem::RangeFull, _), [], _) =
+                expr.kind
+        {
+            // We have `Foo(a, .., c)`, where the user might be trying to use the "rest" syntax
+            // from default field values, which is not supported on tuples.
+            let explanation = if self.tcx.features().default_field_values() {
+                "this is only supported on non-tuple struct literals"
+            } else if self.tcx.sess.is_nightly_build() {
+                "this is only supported on non-tuple struct literals when \
+                 `#![feature(default_field_values)]` is enabled"
+            } else {
+                "this is not supported"
+            };
+            let msg = format!(
+                "you might have meant to use `..` to skip providing a value for \
+                 expected fields, but {explanation}; it is instead interpreted as a \
+                 `std::ops::RangeFull` literal",
+            );
+            err.span_help(expr.span, msg);
+        }
+    }
+
+    fn filter_out_invalid_arguments(&mut self) -> Option<ErrorGuaranteed> {
+        let mut reported = None;
+
+        self.errors.retain(|error| {
+            let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
+                error
+            else {
+                return true;
+            };
+            let (provided_ty, provided_span) =
+                self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
+            let trace = self.arg_matching_ctxt.mk_trace(
+                provided_span,
+                self.arg_matching_ctxt.formal_and_expected_inputs[*expected_idx],
+                provided_ty,
+            );
+            if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
+                let mut err = self.arg_matching_ctxt.err_ctxt().report_and_explain_type_error(
+                    trace,
+                    self.arg_matching_ctxt.param_env,
+                    *e,
+                );
+                self.arg_matching_ctxt.suggest_confusable(&mut err);
+                reported = Some(err.emit());
+                return false;
+            }
+            true
+        });
+
+        reported
+    }
+
+    fn check_single_incompatible(&self) -> Option<ErrorGuaranteed> {
+        if let &[
+            Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
+        ] = &self.errors[..]
+        {
+            let (formal_ty, expected_ty) = self.formal_and_expected_inputs[expected_idx];
+            let (provided_ty, provided_arg_span) = self.provided_arg_tys[provided_idx];
+            let trace = self.mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
+            let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
+            self.emit_coerce_suggestions(
+                &mut err,
+                self.provided_args[provided_idx],
+                provided_ty,
+                Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
+                    .only_has_type(self.fn_ctxt)
+                    .unwrap_or(formal_ty),
+                None,
+                None,
+            );
+            let call_name = self.call_metadata.call_name;
+            err.span_label(
+                self.call_metadata.full_call_span,
+                format!("arguments to this {call_name} are incorrect"),
+            );
+
+            self.fn_ctxt.label_generic_mismatches(
+                &mut err,
+                self.fn_def_id,
+                &self.matched_inputs,
+                &self.provided_arg_tys,
+                &self.formal_and_expected_inputs,
+                self.call_metadata.is_method,
+            );
+
+            if let hir::ExprKind::MethodCall(_, rcvr, _, _) =
+                self.arg_matching_ctxt.args_ctxt.call_ctxt.call_expr.kind
+                && provided_idx.as_usize() == expected_idx.as_usize()
+            {
+                self.note_source_of_type_mismatch_constraint(
+                    &mut err,
+                    rcvr,
+                    crate::demand::TypeMismatchSource::Arg {
+                        call_expr: self.call_expr,
+                        incompatible_arg: provided_idx.as_usize(),
+                    },
+                );
+            }
+
+            self.suggest_ptr_null_mut(
+                expected_ty,
+                provided_ty,
+                self.provided_args[provided_idx],
+                &mut err,
+            );
+
+            self.suggest_deref_unwrap_or(
+                &mut err,
+                self.callee_ty,
+                self.call_metadata.call_ident,
+                expected_ty,
+                provided_ty,
+                self.provided_args[provided_idx],
+                self.call_metadata.is_method,
+            );
+
+            // Call out where the function is defined
+            self.label_fn_like(
+                &mut err,
+                self.fn_def_id,
+                self.callee_ty,
+                self.call_expr,
+                Some(expected_ty),
+                Some(expected_idx.as_usize()),
+                &self.matched_inputs,
+                &self.formal_and_expected_inputs,
+                self.call_metadata.is_method,
+                self.tuple_arguments,
+            );
+            self.arg_matching_ctxt.suggest_confusable(&mut err);
+            self.detect_dotdot(&mut err, provided_ty, self.provided_args[provided_idx]);
+            return Some(err.emit());
+        }
+
+        None
+    }
+
+    fn maybe_optimize_extra_arg_suggestion(&mut self) {
+        if let [Error::Extra(provided_idx)] = &self.errors[..] {
+            if !self.remove_idx_is_perfect(provided_idx.as_usize()) {
+                if let Some(i) = (0..self.args_ctxt.call_ctxt.provided_args.len())
+                    .find(|&i| self.remove_idx_is_perfect(i))
+                {
+                    self.errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
+                }
+            }
+        }
+    }
+
+    fn initial_final_diagnostic(&self) -> Diag<'_> {
+        if self.formal_and_expected_inputs.len() == self.provided_args.len() {
+            struct_span_code_err!(
+                self.dcx(),
+                self.call_metadata.full_call_span,
+                E0308,
+                "arguments to this {} are incorrect",
+                self.call_metadata.call_name,
+            )
+        } else {
+            self.arg_matching_ctxt
+                .dcx()
+                .struct_span_err(
+                    self.call_metadata.full_call_span,
+                    format!(
+                        "this {} takes {}{} but {} {} supplied",
+                        self.call_metadata.call_name,
+                        if self.c_variadic { "at least " } else { "" },
+                        potentially_plural_count(self.formal_and_expected_inputs.len(), "argument"),
+                        potentially_plural_count(self.provided_args.len(), "argument"),
+                        pluralize!("was", self.provided_args.len())
+                    ),
+                )
+                .with_code(self.err_code.to_owned())
+        }
+    }
+
+    fn labels_and_suggestion_text(
+        &self,
+        err: &mut Diag<'_>,
+    ) -> (Vec<(Span, String)>, Vec<(Span, String)>, SuggestionText) {
+        // Don't print if it has error types or is just plain `_`
+        fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
+            tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
+        }
+
+        let mut labels = Vec::new();
+        let mut suggestion_text = SuggestionText::None;
+
+        let mut errors = self.errors.iter().peekable();
+        let mut only_extras_so_far = errors
+            .peek()
+            .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
+        let mut prev_extra_idx = None;
+        let mut suggestions = vec![];
+        while let Some(error) = errors.next() {
+            only_extras_so_far &= matches!(error, Error::Extra(_));
+
+            match error {
+                Error::Invalid(provided_idx, expected_idx, compatibility) => {
+                    let (formal_ty, expected_ty) =
+                        self.arg_matching_ctxt.args_ctxt.call_ctxt.formal_and_expected_inputs
+                            [*expected_idx];
+                    let (provided_ty, provided_span) =
+                        self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
+                    if let Compatibility::Incompatible(error) = compatibility {
+                        let trace = self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
+                            provided_span,
+                            (formal_ty, expected_ty),
+                            provided_ty,
+                        );
+                        if let Some(e) = error {
+                            self.err_ctxt().note_type_err(
+                                err,
+                                &trace.cause,
+                                None,
+                                Some(self.param_env.and(trace.values)),
+                                *e,
+                                true,
+                                None,
+                            );
+                        }
+                    }
+
+                    self.emit_coerce_suggestions(
+                        err,
+                        self.provided_args[*provided_idx],
+                        provided_ty,
+                        Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
+                            .only_has_type(self.fn_ctxt)
+                            .unwrap_or(formal_ty),
+                        None,
+                        None,
+                    );
+                    self.detect_dotdot(err, provided_ty, self.provided_args[*provided_idx]);
+                }
+                Error::Extra(arg_idx) => {
+                    let (provided_ty, provided_span) = self.provided_arg_tys[*arg_idx];
+                    let provided_ty_name = if !has_error_or_infer([provided_ty]) {
+                        // FIXME: not suggestable, use something else
+                        format!(" of type `{provided_ty}`")
+                    } else {
+                        "".to_string()
+                    };
+                    let idx = if self.provided_arg_tys.len() == 1 {
+                        "".to_string()
+                    } else {
+                        format!(" #{}", arg_idx.as_usize() + 1)
+                    };
+                    labels.push((
+                        provided_span,
+                        format!("unexpected argument{idx}{provided_ty_name}"),
+                    ));
+                    let mut span = provided_span;
+                    if span.can_be_used_for_suggestions()
+                        && self.call_metadata.error_span.can_be_used_for_suggestions()
+                    {
+                        if arg_idx.index() > 0
+                            && let Some((_, prev)) = self
+                                .provided_arg_tys
+                                .get(ProvidedIdx::from_usize(arg_idx.index() - 1))
+                        {
+                            // Include previous comma
+                            span = prev.shrink_to_hi().to(span);
+                        }
+
+                        // Is last argument for deletion in a row starting from the 0-th argument?
+                        // Then delete the next comma, so we are not left with `f(, ...)`
+                        //
+                        //     fn f() {}
+                        //   - f(0, 1,)
+                        //   + f()
+                        let trim_next_comma = match errors.peek() {
+                            Some(Error::Extra(provided_idx))
+                                if only_extras_so_far
+                                    && provided_idx.index() > arg_idx.index() + 1 =>
+                            // If the next Error::Extra ("next") doesn't next to current ("current"),
+                            // fn foo(_: (), _: u32) {}
+                            // - foo("current", (), 1u32, "next")
+                            // + foo((), 1u32)
+                            // If the previous error is not a `Error::Extra`, then do not trim the next comma
+                            // - foo((), "current", 42u32, "next")
+                            // + foo((), 42u32)
+                            {
+                                prev_extra_idx.is_none_or(|prev_extra_idx| {
+                                    prev_extra_idx + 1 == arg_idx.index()
+                                })
+                            }
+                            // If no error left, we need to delete the next comma
+                            None if only_extras_so_far => true,
+                            // Not sure if other error type need to be handled as well
+                            _ => false,
+                        };
+
+                        if trim_next_comma {
+                            let next = self
+                                .provided_arg_tys
+                                .get(*arg_idx + 1)
+                                .map(|&(_, sp)| sp)
+                                .unwrap_or_else(|| {
+                                    // Try to move before `)`. Note that `)` here is not necessarily
+                                    // the latin right paren, it could be a Unicode-confusable that
+                                    // looks like a `)`, so we must not use `- BytePos(1)`
+                                    // manipulations here.
+                                    self.arg_matching_ctxt
+                                        .tcx()
+                                        .sess
+                                        .source_map()
+                                        .end_point(self.call_expr.span)
+                                });
+
+                            // Include next comma
+                            span = span.until(next);
+                        }
+
+                        suggestions.push((span, String::new()));
+
+                        suggestion_text = match suggestion_text {
+                            SuggestionText::None => SuggestionText::Remove(false),
+                            SuggestionText::Remove(_) => SuggestionText::Remove(true),
+                            _ => SuggestionText::DidYouMean,
+                        };
+                        prev_extra_idx = Some(arg_idx.index())
+                    }
+                    self.detect_dotdot(err, provided_ty, self.provided_args[*arg_idx]);
+                }
+                Error::Missing(expected_idx) => {
+                    // If there are multiple missing arguments adjacent to each other,
+                    // then we can provide a single error.
+
+                    let mut missing_idxs = vec![*expected_idx];
+                    while let Some(e) = errors.next_if(|e| {
+                        matches!(e, Error::Missing(next_expected_idx)
+                            if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
+                    }) {
+                        match e {
+                            Error::Missing(expected_idx) => missing_idxs.push(*expected_idx),
+                            _ => unreachable!(
+                                "control flow ensures that we should always get an `Error::Missing`"
+                            ),
+                        }
+                    }
+
+                    // NOTE: Because we might be re-arranging arguments, might have extra
+                    // arguments, etc. it's hard to *really* know where we should provide
+                    // this error label, so as a heuristic, we point to the provided arg, or
+                    // to the call if the missing inputs pass the provided args.
+                    match &missing_idxs[..] {
+                        &[expected_idx] => {
+                            let (_, input_ty) = self.formal_and_expected_inputs[expected_idx];
+                            let span = if let Some((_, arg_span)) =
+                                self.provided_arg_tys.get(expected_idx.to_provided_idx())
+                            {
+                                *arg_span
+                            } else {
+                                self.args_span
+                            };
+                            let rendered = if !has_error_or_infer([input_ty]) {
+                                format!(" of type `{input_ty}`")
+                            } else {
+                                "".to_string()
+                            };
+                            labels.push((
+                                span,
+                                format!(
+                                    "argument #{}{rendered} is missing",
+                                    expected_idx.as_usize() + 1
+                                ),
+                            ));
+
+                            suggestion_text = match suggestion_text {
+                                SuggestionText::None => SuggestionText::Provide(false),
+                                SuggestionText::Provide(_) => SuggestionText::Provide(true),
+                                _ => SuggestionText::DidYouMean,
+                            };
+                        }
+                        &[first_idx, second_idx] => {
+                            let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
+                            let (_, second_expected_ty) =
+                                self.formal_and_expected_inputs[second_idx];
+                            let span = if let (Some((_, first_span)), Some((_, second_span))) = (
+                                self.provided_arg_tys.get(first_idx.to_provided_idx()),
+                                self.provided_arg_tys.get(second_idx.to_provided_idx()),
+                            ) {
+                                first_span.to(*second_span)
+                            } else {
+                                self.args_span
+                            };
+                            let rendered =
+                                if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
+                                    format!(
+                                        " of type `{first_expected_ty}` and `{second_expected_ty}`"
+                                    )
+                                } else {
+                                    "".to_string()
+                                };
+                            labels.push((span, format!("two arguments{rendered} are missing")));
+                            suggestion_text = match suggestion_text {
+                                SuggestionText::None | SuggestionText::Provide(_) => {
+                                    SuggestionText::Provide(true)
+                                }
+                                _ => SuggestionText::DidYouMean,
+                            };
+                        }
+                        &[first_idx, second_idx, third_idx] => {
+                            let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
+                            let (_, second_expected_ty) =
+                                self.formal_and_expected_inputs[second_idx];
+                            let (_, third_expected_ty) = self.formal_and_expected_inputs[third_idx];
+                            let span = if let (Some((_, first_span)), Some((_, third_span))) = (
+                                self.provided_arg_tys.get(first_idx.to_provided_idx()),
+                                self.provided_arg_tys.get(third_idx.to_provided_idx()),
+                            ) {
+                                first_span.to(*third_span)
+                            } else {
+                                self.args_span
+                            };
+                            let rendered = if !has_error_or_infer([
+                                first_expected_ty,
+                                second_expected_ty,
+                                third_expected_ty,
+                            ]) {
+                                format!(
+                                    " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
+                                )
+                            } else {
+                                "".to_string()
+                            };
+                            labels.push((span, format!("three arguments{rendered} are missing")));
+                            suggestion_text = match suggestion_text {
+                                SuggestionText::None | SuggestionText::Provide(_) => {
+                                    SuggestionText::Provide(true)
+                                }
+                                _ => SuggestionText::DidYouMean,
+                            };
+                        }
+                        missing_idxs => {
+                            let first_idx = *missing_idxs.first().unwrap();
+                            let last_idx = *missing_idxs.last().unwrap();
+                            // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
+                            // It's hard to *really* know where we should provide this error label, so this is a
+                            // decent heuristic
+                            let span = if let (Some((_, first_span)), Some((_, last_span))) = (
+                                self.provided_arg_tys.get(first_idx.to_provided_idx()),
+                                self.provided_arg_tys.get(last_idx.to_provided_idx()),
+                            ) {
+                                first_span.to(*last_span)
+                            } else {
+                                self.args_span
+                            };
+                            labels.push((span, "multiple arguments are missing".to_string()));
+                            suggestion_text = match suggestion_text {
+                                SuggestionText::None | SuggestionText::Provide(_) => {
+                                    SuggestionText::Provide(true)
+                                }
+                                _ => SuggestionText::DidYouMean,
+                            };
+                        }
+                    }
+                }
+                Error::Swap(
+                    first_provided_idx,
+                    second_provided_idx,
+                    first_expected_idx,
+                    second_expected_idx,
+                ) => {
+                    let (first_provided_ty, first_span) =
+                        self.provided_arg_tys[*first_provided_idx];
+                    let (_, first_expected_ty) =
+                        self.formal_and_expected_inputs[*first_expected_idx];
+                    let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
+                        format!(", found `{first_provided_ty}`")
+                    } else {
+                        String::new()
+                    };
+                    labels.push((
+                        first_span,
+                        format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
+                    ));
+
+                    let (second_provided_ty, second_span) =
+                        self.provided_arg_tys[*second_provided_idx];
+                    let (_, second_expected_ty) =
+                        self.formal_and_expected_inputs[*second_expected_idx];
+                    let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
+                        format!(", found `{second_provided_ty}`")
+                    } else {
+                        String::new()
+                    };
+                    labels.push((
+                        second_span,
+                        format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
+                    ));
+
+                    suggestion_text = match suggestion_text {
+                        SuggestionText::None => SuggestionText::Swap,
+                        _ => SuggestionText::DidYouMean,
+                    };
+                }
+                Error::Permutation(args) => {
+                    for (dst_arg, dest_input) in args {
+                        let (_, expected_ty) = self.formal_and_expected_inputs[*dst_arg];
+                        let (provided_ty, provided_span) = self.provided_arg_tys[*dest_input];
+                        let provided_ty_name = if !has_error_or_infer([provided_ty]) {
+                            format!(", found `{provided_ty}`")
+                        } else {
+                            String::new()
+                        };
+                        labels.push((
+                            provided_span,
+                            format!("expected `{expected_ty}`{provided_ty_name}"),
+                        ));
+                    }
+
+                    suggestion_text = match suggestion_text {
+                        SuggestionText::None => SuggestionText::Reorder,
+                        _ => SuggestionText::DidYouMean,
+                    };
+                }
+            }
+        }
+
+        (suggestions, labels, suggestion_text)
+    }
+
+    fn label_generic_mismatches(&self, err: &mut Diag<'b>) {
+        self.fn_ctxt.label_generic_mismatches(
+            err,
+            self.fn_def_id,
+            &self.matched_inputs,
+            &self.provided_arg_tys,
+            &self.formal_and_expected_inputs,
+            self.call_metadata.is_method,
+        );
+    }
+
+    /// Incorporate the argument changes in the removal suggestion.
+    ///
+    /// When a type is *missing*, and the rest are additional, we want to suggest these with a
+    /// multipart suggestion, but in order to do so we need to figure out *where* the arg that
+    /// was provided but had the wrong type should go, because when looking at `expected_idx`
+    /// that is the position in the argument list in the definition, while `provided_idx` will
+    /// not be present. So we have to look at what the *last* provided position was, and point
+    /// one after to suggest the replacement.
+    fn append_arguments_changes(&self, suggestions: &mut Vec<(Span, String)>) {
+        // FIXME(estebank): This is hacky, and there's
+        // probably a better more involved change we can make to make this work.
+        // For example, if we have
+        // ```
+        // fn foo(i32, &'static str) {}
+        // foo((), (), ());
+        // ```
+        // what should be suggested is
+        // ```
+        // foo(/* i32 */, /* &str */);
+        // ```
+        // which includes the replacement of the first two `()` for the correct type, and the
+        // removal of the last `()`.
+
+        let mut prev = -1;
+        for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
+            // We want to point not at the *current* argument expression index, but rather at the
+            // index position where it *should have been*, which is *after* the previous one.
+            if let Some(provided_idx) = provided_idx {
+                prev = provided_idx.index() as i64;
+                continue;
+            }
+            let idx = ProvidedIdx::from_usize((prev + 1) as usize);
+            if let Some((_, arg_span)) = self.provided_arg_tys.get(idx) {
+                prev += 1;
+                // There is a type that was *not* found anywhere, so it isn't a move, but a
+                // replacement and we look at what type it should have been. This will allow us
+                // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
+                // was `fn foo(())`.
+                let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
+                suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx)));
+            }
+        }
+    }
+
+    fn format_suggestion_text(
+        err: &mut Diag<'_>,
+        suggestions: Vec<(Span, String)>,
+        suggestion_text: SuggestionText,
+    ) -> Option<String> {
+        let suggestion_text = match suggestion_text {
+            SuggestionText::None => None,
+            SuggestionText::Provide(plural) => {
+                Some(format!("provide the argument{}", if plural { "s" } else { "" }))
+            }
+            SuggestionText::Remove(plural) => {
+                err.multipart_suggestion_verbose(
+                    format!("remove the extra argument{}", if plural { "s" } else { "" }),
+                    suggestions,
+                    Applicability::HasPlaceholders,
+                );
+                None
+            }
+            SuggestionText::Swap => Some("swap these arguments".to_string()),
+            SuggestionText::Reorder => Some("reorder these arguments".to_string()),
+            SuggestionText::DidYouMean => Some("did you mean".to_string()),
+        };
+        suggestion_text
+    }
+
+    fn arguments_formatting(&self, suggestion_span: Span) -> ArgumentsFormatting {
+        let source_map = self.sess().source_map();
+        let mut provided_inputs = self.matched_inputs.iter().filter_map(|a| *a);
+        if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
+            && let Some(first_idx) = provided_inputs.by_ref().next()
+            && let Some(last_idx) = provided_inputs.by_ref().next()
+            && let (_, first_span) = self.provided_arg_tys[first_idx]
+            && let (_, last_span) = self.provided_arg_tys[last_idx]
+            && source_map.is_multiline(first_span.to(last_span))
+            && let Some(fallback_indent) = source_map.indentation_before(first_span)
+        {
+            ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
+        } else {
+            ArgumentsFormatting::SingleLine
+        }
+    }
+
+    fn suggestion_code(&self) -> (Span, String) {
+        let source_map = self.sess().source_map();
+        let suggestion_span = if let Some(args_span) =
+            self.call_metadata.error_span.trim_start(self.call_metadata.full_call_span)
+        {
+            // Span of the braces, e.g. `(a, b, c)`.
+            args_span
+        } else {
+            // The arg span of a function call that wasn't even given braces
+            // like what might happen with delegation reuse.
+            // e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`.
+            self.call_metadata.full_call_span.shrink_to_hi()
+        };
+
+        let arguments_formatting = self.arguments_formatting(suggestion_span);
+
+        let mut suggestion = "(".to_owned();
+        let mut needs_comma = false;
+        for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
+            if needs_comma {
+                suggestion += ",";
+            }
+            match &arguments_formatting {
+                ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
+                ArgumentsFormatting::SingleLine => {}
+                ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
+            }
+            needs_comma = true;
+            let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
+                && let (_, provided_span) = self.provided_arg_tys[*provided_idx]
+                && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
+            {
+                (Some(provided_span), arg_text)
+            } else {
+                // Propose a placeholder of the correct type
+                let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
+                (None, self.ty_to_snippet(expected_ty, expected_idx))
+            };
+            if let ArgumentsFormatting::Multiline { fallback_indent, .. } = &arguments_formatting {
+                let indent = suggestion_span
+                    .and_then(|span| source_map.indentation_before(span))
+                    .unwrap_or_else(|| fallback_indent.clone());
+                suggestion += &indent;
+            }
+            suggestion += &suggestion_text;
+        }
+        if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
+            suggestion += ",\n";
+            suggestion += &brace_indent;
+        }
+        suggestion += ")";
+
+        (suggestion_span, suggestion)
+    }
+}
+
+struct ArgMatchingCtxt<'a, 'b, 'tcx> {
+    args_ctxt: ArgsCtxt<'a, 'b, 'tcx>,
+    provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
+}
+
+impl<'a, 'b, 'tcx> Deref for ArgMatchingCtxt<'a, 'b, 'tcx> {
+    type Target = ArgsCtxt<'a, 'b, 'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.args_ctxt
+    }
+}
+
+impl<'a, 'b, 'tcx> ArgMatchingCtxt<'a, 'b, 'tcx> {
+    fn new(
+        arg: &'a FnCtxt<'b, 'tcx>,
+        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
+        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
+        provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
+        c_variadic: bool,
+        err_code: ErrCode,
+        fn_def_id: Option<DefId>,
+        call_span: Span,
+        call_expr: &'tcx Expr<'tcx>,
+        tuple_arguments: TupleArgumentsFlag,
+    ) -> Self {
+        let args_ctxt = ArgsCtxt::new(
+            arg,
+            compatibility_diagonal,
+            formal_and_expected_inputs,
+            provided_args,
+            c_variadic,
+            err_code,
+            fn_def_id,
+            call_span,
+            call_expr,
+            tuple_arguments,
+        );
+        let provided_arg_tys = args_ctxt.provided_arg_tys();
+
+        ArgMatchingCtxt { args_ctxt, provided_arg_tys }
+    }
+
+    fn suggest_confusable(&self, err: &mut Diag<'_>) {
+        let Some(call_name) = self.call_metadata.call_ident else {
+            return;
+        };
+        let Some(callee_ty) = self.callee_ty else {
+            return;
+        };
+        let input_types: Vec<Ty<'_>> = self.provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
+
+        // Check for other methods in the following order
+        //  - methods marked as `rustc_confusables` with the provided arguments
+        //  - methods with the same argument type/count and short levenshtein distance
+        //  - methods marked as `rustc_confusables` (done)
+        //  - methods with short levenshtein distance
+
+        // Look for commonly confusable method names considering arguments.
+        if let Some(_name) = self.confusable_method_name(
+            err,
+            callee_ty.peel_refs(),
+            call_name,
+            Some(input_types.clone()),
+        ) {
+            return;
+        }
+        // Look for method names with short levenshtein distance, considering arguments.
+        if let Some((assoc, fn_sig)) = self.similar_assoc(call_name)
+            && fn_sig.inputs()[1..]
+                .iter()
+                .zip(input_types.iter())
+                .all(|(expected, found)| self.may_coerce(*expected, *found))
+            && fn_sig.inputs()[1..].len() == input_types.len()
+        {
+            let assoc_name = assoc.name();
+            err.span_suggestion_verbose(
+                call_name.span,
+                format!("you might have meant to use `{}`", assoc_name),
+                assoc_name,
+                Applicability::MaybeIncorrect,
+            );
+            return;
+        }
+    }
+
+    /// A "softer" version of the `demand_compatible`, which checks types without persisting them,
+    /// and treats error types differently
+    /// This will allow us to "probe" for other argument orders that would likely have been correct
+    fn check_compatible(
+        &self,
+        provided_idx: ProvidedIdx,
+        expected_idx: ExpectedIdx,
+    ) -> Compatibility<'tcx> {
+        if provided_idx.as_usize() == expected_idx.as_usize() {
+            return self.compatibility_diagonal[provided_idx].clone();
+        }
+
+        let (formal_input_ty, expected_input_ty) = self.formal_and_expected_inputs[expected_idx];
+        // If either is an error type, we defy the usual convention and consider them to *not* be
+        // coercible. This prevents our error message heuristic from trying to pass errors into
+        // every argument.
+        if (formal_input_ty, expected_input_ty).references_error() {
+            return Compatibility::Incompatible(None);
+        }
+
+        let (arg_ty, arg_span) = self.provided_arg_tys[provided_idx];
+
+        let expectation = Expectation::rvalue_hint(self.fn_ctxt, expected_input_ty);
+        let coerced_ty = expectation.only_has_type(self.fn_ctxt).unwrap_or(formal_input_ty);
+        let can_coerce = self.may_coerce(arg_ty, coerced_ty);
+        if !can_coerce {
+            return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
+                ty::error::ExpectedFound::new(coerced_ty, arg_ty),
+            )));
+        }
+
+        // Using probe here, since we don't want this subtyping to affect inference.
+        let subtyping_error = self.probe(|_| {
+            self.at(&self.misc(arg_span), self.param_env)
+                .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
+                .err()
+        });
+
+        // Same as above: if either the coerce type or the checked type is an error type,
+        // consider them *not* compatible.
+        let references_error = (coerced_ty, arg_ty).references_error();
+        match (references_error, subtyping_error) {
+            (false, None) => Compatibility::Compatible,
+            (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
+        }
+    }
+
+    fn remove_idx_is_perfect(&self, idx: usize) -> bool {
+        let removed_arg_tys = self
+            .provided_arg_tys
+            .iter()
+            .enumerate()
+            .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
+            .collect::<IndexVec<ProvidedIdx, _>>();
+        std::iter::zip(self.formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
+            |((expected_ty, _), (provided_ty, _))| {
+                !provided_ty.references_error() && self.may_coerce(*provided_ty, *expected_ty)
+            },
+        )
+    }
+}
+
+struct ArgsCtxt<'a, 'b, 'tcx> {
+    call_ctxt: CallCtxt<'a, 'b, 'tcx>,
+    call_metadata: CallMetadata,
+    args_span: Span,
+}
+
+impl<'a, 'b, 'tcx> Deref for ArgsCtxt<'a, 'b, 'tcx> {
+    type Target = CallCtxt<'a, 'b, 'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.call_ctxt
+    }
+}
+
+impl<'a, 'b, 'tcx> ArgsCtxt<'a, 'b, 'tcx> {
+    fn new(
+        arg: &'a FnCtxt<'b, 'tcx>,
+        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
+        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
+        provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
+        c_variadic: bool,
+        err_code: ErrCode,
+        fn_def_id: Option<DefId>,
+        call_span: Span,
+        call_expr: &'tcx Expr<'tcx>,
+        tuple_arguments: TupleArgumentsFlag,
+    ) -> Self {
+        let call_ctxt: CallCtxt<'_, '_, '_> = CallCtxt::new(
+            arg,
+            compatibility_diagonal,
+            formal_and_expected_inputs,
+            provided_args,
+            c_variadic,
+            err_code,
+            fn_def_id,
+            call_span,
+            call_expr,
+            tuple_arguments,
+        );
+
+        let call_metadata = call_ctxt.call_metadata();
+        let args_span = call_metadata
+            .error_span
+            .trim_start(call_metadata.full_call_span)
+            .unwrap_or(call_metadata.error_span);
+
+        ArgsCtxt { args_span, call_metadata, call_ctxt }
+    }
+
+    /// Get the argument span in the context of the call span so that
+    /// suggestions and labels are (more) correct when an arg is a
+    /// macro invocation.
+    fn normalize_span(&self, span: Span) -> Span {
+        let normalized_span =
+            span.find_ancestor_inside_same_ctxt(self.call_metadata.error_span).unwrap_or(span);
+        // Sometimes macros mess up the spans, so do not normalize the
+        // arg span to equal the error span, because that's less useful
+        // than pointing out the arg expr in the wrong context.
+        if normalized_span.source_equal(self.call_metadata.error_span) {
+            span
+        } else {
+            normalized_span
+        }
+    }
+
+    /// Computes the provided types and spans.
+    fn provided_arg_tys(&self) -> IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> {
+        self.call_ctxt
+            .provided_args
+            .iter()
+            .map(|expr| {
+                let ty = self
+                    .call_ctxt
+                    .fn_ctxt
+                    .typeck_results
+                    .borrow()
+                    .expr_ty_adjusted_opt(*expr)
+                    .unwrap_or_else(|| Ty::new_misc_error(self.call_ctxt.fn_ctxt.tcx));
+                (
+                    self.call_ctxt.fn_ctxt.resolve_vars_if_possible(ty),
+                    self.normalize_span(expr.span),
+                )
+            })
+            .collect()
+    }
+
+    // Obtain another method on `Self` that have similar name.
+    fn similar_assoc(&self, call_name: Ident) -> Option<(ty::AssocItem, ty::FnSig<'tcx>)> {
+        if let Some(callee_ty) = self.call_ctxt.callee_ty
+            && let Ok(Some(assoc)) = self.call_ctxt.fn_ctxt.probe_op(
+                call_name.span,
+                MethodCall,
+                Some(call_name),
+                None,
+                IsSuggestion(true),
+                callee_ty.peel_refs(),
+                self.call_ctxt.callee_expr.unwrap().hir_id,
+                TraitsInScope,
+                |mut ctxt| ctxt.probe_for_similar_candidate(),
+            )
+            && assoc.is_method()
+        {
+            let args =
+                self.call_ctxt.fn_ctxt.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
+            let fn_sig = self
+                .call_ctxt
+                .fn_ctxt
+                .tcx
+                .fn_sig(assoc.def_id)
+                .instantiate(self.call_ctxt.fn_ctxt.tcx, args);
+
+            self.call_ctxt.fn_ctxt.instantiate_binder_with_fresh_vars(
+                call_name.span,
+                BoundRegionConversionTime::FnCall,
+                fn_sig,
+            );
+        }
+        None
+    }
+
+    fn call_is_in_macro(&self) -> bool {
+        self.call_metadata.full_call_span.in_external_macro(self.sess().source_map())
+    }
+}
+
+struct CallMetadata {
+    error_span: Span,
+    call_ident: Option<Ident>,
+    full_call_span: Span,
+    call_name: &'static str,
+    is_method: bool,
+}
+
+struct CallCtxt<'a, 'b, 'tcx> {
+    fn_ctxt: &'a FnCtxt<'b, 'tcx>,
+    compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
+    formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
+    provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
+    c_variadic: bool,
+    err_code: ErrCode,
+    fn_def_id: Option<DefId>,
+    call_span: Span,
+    call_expr: &'tcx hir::Expr<'tcx>,
+    tuple_arguments: TupleArgumentsFlag,
+    callee_expr: Option<&'tcx Expr<'tcx>>,
+    callee_ty: Option<Ty<'tcx>>,
+}
+
+impl<'a, 'b, 'tcx> Deref for CallCtxt<'a, 'b, 'tcx> {
+    type Target = &'a FnCtxt<'b, 'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.fn_ctxt
+    }
+}
+
+impl<'a, 'b, 'tcx> CallCtxt<'a, 'b, 'tcx> {
+    fn new(
+        fn_ctxt: &'a FnCtxt<'b, 'tcx>,
+        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
+        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
+        provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
+        c_variadic: bool,
+        err_code: ErrCode,
+        fn_def_id: Option<DefId>,
+        call_span: Span,
+        call_expr: &'tcx hir::Expr<'tcx>,
+        tuple_arguments: TupleArgumentsFlag,
+    ) -> CallCtxt<'a, 'b, 'tcx> {
+        let callee_expr = match &call_expr.peel_blocks().kind {
+            hir::ExprKind::Call(callee, _) => Some(*callee),
+            hir::ExprKind::MethodCall(_, receiver, ..) => {
+                if let Some((DefKind::AssocFn, def_id)) =
+                    fn_ctxt.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
+                    && let Some(assoc) = fn_ctxt.tcx.opt_associated_item(def_id)
+                    && assoc.is_method()
+                {
+                    Some(*receiver)
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        };
+
+        let callee_ty = callee_expr.and_then(|callee_expr| {
+            fn_ctxt.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
+        });
+
+        CallCtxt {
+            fn_ctxt,
+            compatibility_diagonal,
+            formal_and_expected_inputs,
+            provided_args,
+            c_variadic,
+            err_code,
+            fn_def_id,
+            call_span,
+            call_expr,
+            tuple_arguments,
+            callee_expr,
+            callee_ty,
+        }
+    }
+
+    fn call_metadata(&self) -> CallMetadata {
+        match &self.call_expr.kind {
+            hir::ExprKind::Call(
+                hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
+                _,
+            ) => {
+                if let Res::Def(DefKind::Ctor(of, _), _) =
+                    self.typeck_results.borrow().qpath_res(qpath, *hir_id)
+                {
+                    let name = match of {
+                        CtorOf::Struct => "struct",
+                        CtorOf::Variant => "enum variant",
+                    };
+                    CallMetadata {
+                        error_span: self.call_span,
+                        call_ident: None,
+                        full_call_span: *span,
+                        call_name: name,
+                        is_method: false,
+                    }
+                } else {
+                    CallMetadata {
+                        error_span: self.call_span,
+                        call_ident: None,
+                        full_call_span: *span,
+                        call_name: "function",
+                        is_method: false,
+                    }
+                }
+            }
+            hir::ExprKind::Call(hir::Expr { span, .. }, _) => CallMetadata {
+                error_span: self.call_span,
+                call_ident: None,
+                full_call_span: *span,
+                call_name: "function",
+                is_method: false,
+            },
+            hir::ExprKind::MethodCall(path_segment, _, _, span) => {
+                let ident_span = path_segment.ident.span;
+                let ident_span = if let Some(args) = path_segment.args {
+                    ident_span.with_hi(args.span_ext.hi())
+                } else {
+                    ident_span
+                };
+                CallMetadata {
+                    error_span: *span,
+                    call_ident: Some(path_segment.ident),
+                    full_call_span: ident_span,
+                    call_name: "method",
+                    is_method: true,
+                }
+            }
+            k => span_bug!(self.call_span, "checking argument types on a non-call: `{:?}`", k),
+        }
+    }
+
+    fn mk_trace(
+        &self,
+        span: Span,
+        (formal_ty, expected_ty): (Ty<'tcx>, Ty<'tcx>),
+        provided_ty: Ty<'tcx>,
+    ) -> TypeTrace<'tcx> {
+        let mismatched_ty = if expected_ty == provided_ty {
+            // If expected == provided, then we must have failed to sup
+            // the formal type. Avoid printing out "expected Ty, found Ty"
+            // in that case.
+            formal_ty
+        } else {
+            expected_ty
+        };
+        TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
+    }
+
+    fn ty_to_snippet(&self, ty: Ty<'tcx>, expected_idx: ExpectedIdx) -> String {
+        if ty.is_unit() {
+            "()".to_string()
+        } else if ty.is_suggestable(self.tcx, false) {
+            format!("/* {ty} */")
+        } else if let Some(fn_def_id) = self.fn_def_id
+            && self.tcx.def_kind(fn_def_id).is_fn_like()
+            && let self_implicit =
+                matches!(self.call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
+            && let Some(Some(arg)) =
+                self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
+            && arg.name != kw::SelfLower
+        {
+            format!("/* {} */", arg.name)
+        } else {
+            "/* value */".to_string()
+        }
+    }
+
+    fn first_incompatible_error(&self) -> Option<(ProvidedIdx, TypeError<'tcx>)> {
+        self.compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
+            if let Compatibility::Incompatible(Some(terr)) = c { Some((i, *terr)) } else { None }
+        })
+    }
+}
+
+enum SuggestionText {
+    None,
+    Provide(bool),
+    Remove(bool),
+    Swap,
+    Reorder,
+    DidYouMean,
+}
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 9a66bd0574c..4a252719694 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -72,12 +72,27 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
             self.register_predicate_obligation(infcx, obligation);
         }
     }
-
+    /// Go over the list of pending obligations and try to evaluate them.
+    ///
+    /// For each result:
+    /// Ok: remove the obligation from the list
+    /// Ambiguous: leave the obligation in the list to be evaluated later
+    /// Err: remove the obligation from the list and return an error
+    ///
+    /// Returns a list of errors from obligations that evaluated to Err.
     #[must_use]
     fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
 
     fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
 
+    /// Evaluate all pending obligations, return error if they can't be evaluated.
+    ///
+    /// For each result:
+    /// Ok: remove the obligation from the list
+    /// Ambiguous: remove the obligation from the list and return an error
+    /// Err: remove the obligation from the list and return an error
+    ///
+    /// Returns a list of errors from obligations that evaluated to Ambiguous or Err.
     #[must_use]
     fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
         let errors = self.select_where_possible(infcx);
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 22d89d24612..edbbfba4f34 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -843,6 +843,10 @@ trait UnusedDelimLint {
                 && !snip.ends_with(' ')
             {
                 " "
+            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
+                && snip.ends_with(|c: char| c.is_alphanumeric())
+            {
+                " "
             } else {
                 ""
             };
@@ -852,6 +856,10 @@ trait UnusedDelimLint {
                 && !snip.starts_with(' ')
             {
                 " "
+            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
+                && snip.starts_with(|c: char| c.is_alphanumeric())
+            {
+                " "
             } else {
                 ""
             };
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 9d21d0d22e3..2cfda7a5fb4 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -16,7 +16,6 @@ const OPTIONAL_COMPONENTS: &[&str] = &[
     "mips",
     "powerpc",
     "systemz",
-    "jsbackend",
     "webassembly",
     "msp430",
     "sparc",
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 3bb1533c2fe..91d11ba317a 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -79,122 +79,6 @@ extern "C" void LLVMRustTimeTraceProfilerFinish(const char *FileName) {
   timeTraceProfilerCleanup();
 }
 
-#ifdef LLVM_COMPONENT_X86
-#define SUBTARGET_X86 SUBTARGET(X86)
-#else
-#define SUBTARGET_X86
-#endif
-
-#ifdef LLVM_COMPONENT_ARM
-#define SUBTARGET_ARM SUBTARGET(ARM)
-#else
-#define SUBTARGET_ARM
-#endif
-
-#ifdef LLVM_COMPONENT_AARCH64
-#define SUBTARGET_AARCH64 SUBTARGET(AArch64)
-#else
-#define SUBTARGET_AARCH64
-#endif
-
-#ifdef LLVM_COMPONENT_AVR
-#define SUBTARGET_AVR SUBTARGET(AVR)
-#else
-#define SUBTARGET_AVR
-#endif
-
-#ifdef LLVM_COMPONENT_M68k
-#define SUBTARGET_M68K SUBTARGET(M68k)
-#else
-#define SUBTARGET_M68K
-#endif
-
-#ifdef LLVM_COMPONENT_CSKY
-#define SUBTARGET_CSKY SUBTARGET(CSKY)
-#else
-#define SUBTARGET_CSKY
-#endif
-
-#ifdef LLVM_COMPONENT_MIPS
-#define SUBTARGET_MIPS SUBTARGET(Mips)
-#else
-#define SUBTARGET_MIPS
-#endif
-
-#ifdef LLVM_COMPONENT_POWERPC
-#define SUBTARGET_PPC SUBTARGET(PPC)
-#else
-#define SUBTARGET_PPC
-#endif
-
-#ifdef LLVM_COMPONENT_SYSTEMZ
-#define SUBTARGET_SYSTEMZ SUBTARGET(SystemZ)
-#else
-#define SUBTARGET_SYSTEMZ
-#endif
-
-#ifdef LLVM_COMPONENT_MSP430
-#define SUBTARGET_MSP430 SUBTARGET(MSP430)
-#else
-#define SUBTARGET_MSP430
-#endif
-
-#ifdef LLVM_COMPONENT_RISCV
-#define SUBTARGET_RISCV SUBTARGET(RISCV)
-#else
-#define SUBTARGET_RISCV
-#endif
-
-#ifdef LLVM_COMPONENT_SPARC
-#define SUBTARGET_SPARC SUBTARGET(Sparc)
-#else
-#define SUBTARGET_SPARC
-#endif
-
-#ifdef LLVM_COMPONENT_XTENSA
-#define SUBTARGET_XTENSA SUBTARGET(XTENSA)
-#else
-#define SUBTARGET_XTENSA
-#endif
-
-#ifdef LLVM_COMPONENT_HEXAGON
-#define SUBTARGET_HEXAGON SUBTARGET(Hexagon)
-#else
-#define SUBTARGET_HEXAGON
-#endif
-
-#ifdef LLVM_COMPONENT_LOONGARCH
-#define SUBTARGET_LOONGARCH SUBTARGET(LoongArch)
-#else
-#define SUBTARGET_LOONGARCH
-#endif
-
-#define GEN_SUBTARGETS                                                         \
-  SUBTARGET_X86                                                                \
-  SUBTARGET_ARM                                                                \
-  SUBTARGET_AARCH64                                                            \
-  SUBTARGET_AVR                                                                \
-  SUBTARGET_M68K                                                               \
-  SUBTARGET_CSKY                                                               \
-  SUBTARGET_MIPS                                                               \
-  SUBTARGET_PPC                                                                \
-  SUBTARGET_SYSTEMZ                                                            \
-  SUBTARGET_MSP430                                                             \
-  SUBTARGET_SPARC                                                              \
-  SUBTARGET_HEXAGON                                                            \
-  SUBTARGET_XTENSA                                                             \
-  SUBTARGET_RISCV                                                              \
-  SUBTARGET_LOONGARCH
-
-#define SUBTARGET(x)                                                           \
-  namespace llvm {                                                             \
-  extern const SubtargetFeatureKV x##FeatureKV[];                              \
-  extern const SubtargetFeatureKV x##SubTypeKV[];                              \
-  }
-
-GEN_SUBTARGETS
-#undef SUBTARGET
-
 // This struct and various functions are sort of a hack right now, but the
 // problem is that we've got in-memory LLVM modules after we generate and
 // optimize all codegen-units for one compilation in rustc. To be compatible
@@ -340,14 +224,6 @@ static FloatABI::ABIType fromRust(LLVMRustFloatABI RustFloatAbi) {
   report_fatal_error("Bad FloatABI.");
 }
 
-/// getLongestEntryLength - Return the length of the longest entry in the table.
-template <typename KV> static size_t getLongestEntryLength(ArrayRef<KV> Table) {
-  size_t MaxLen = 0;
-  for (auto &I : Table)
-    MaxLen = std::max(MaxLen, std::strlen(I.Key));
-  return MaxLen;
-}
-
 extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM,
                                         RustStringRef OutStr) {
   ArrayRef<SubtargetSubTypeKV> CPUTable =
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index ed5edeef161..14e94121d1c 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -180,12 +180,6 @@ pub fn initialize_available_targets() {
         LLVMInitializeSystemZAsmParser
     );
     init_target!(
-        llvm_component = "jsbackend",
-        LLVMInitializeJSBackendTargetInfo,
-        LLVMInitializeJSBackendTarget,
-        LLVMInitializeJSBackendTargetMC
-    );
-    init_target!(
         llvm_component = "msp430",
         LLVMInitializeMSP430TargetInfo,
         LLVMInitializeMSP430Target,
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 69adb2fe391..279ab9a9d8f 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -84,7 +84,7 @@ middle_failed_writing_file =
 # Note: We only mention patterns here since the error can only occur with references, and those
 # are forbidden in const generics.
 middle_invalid_const_in_valtree = constant {$global_const_id} cannot be used as pattern
-    .note = constants that reference mutable or external memory cannot be used as pattern
+    .note = constants that reference mutable or external memory cannot be used as patterns
 
 middle_layout_cycle =
     a cycle occurred during layout computation
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 3b8def67f92..d402ea4b04f 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -327,9 +327,11 @@ pub enum StatementKind<'tcx> {
     /// interesting for optimizations? Do we want to allow such optimizations?
     ///
     /// **Needs clarification**: We currently require that the LHS place not overlap with any place
-    /// read as part of computation of the RHS for some rvalues (generally those not producing
-    /// primitives). This requirement is under discussion in [#68364]. As a part of this discussion,
-    /// it is also unclear in what order the components are evaluated.
+    /// read as part of computation of the RHS for some rvalues. This requirement is under
+    /// discussion in [#68364]. Specifically, overlap is permitted only for assignments of a type
+    /// with `BackendRepr::Scalar | BackendRepr::ScalarPair` where all the scalar fields are
+    /// [`Scalar::Initialized`][rustc_abi::Scalar::Initialized]. As a part of this discussion, it is
+    /// also unclear in what order the components are evaluated.
     ///
     /// [#68364]: https://github.com/rust-lang/rust/issues/68364
     ///
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 9ba2d274691..c57483a6811 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -567,13 +567,15 @@ fn save_as_intervals<'tcx>(
         // the written-to locals as live in the second half of the statement.
         // We also ensure that operands read by terminators conflict with writes by that terminator.
         // For instance a function call may read args after having written to the destination.
-        VisitPlacesWith(|place, ctxt| match DefUse::for_place(place, ctxt) {
-            DefUse::Def | DefUse::Use | DefUse::PartialWrite => {
-                if let Some(relevant) = relevant.shrink[place.local] {
-                    values.insert(relevant, twostep);
+        VisitPlacesWith(|place: Place<'tcx>, ctxt| {
+            if let Some(relevant) = relevant.shrink[place.local] {
+                match DefUse::for_place(place, ctxt) {
+                    DefUse::Def | DefUse::Use | DefUse::PartialWrite => {
+                        values.insert(relevant, twostep);
+                    }
+                    DefUse::NonUse => {}
                 }
             }
-            DefUse::NonUse => {}
         })
         .visit_terminator(term, loc);
 
@@ -588,15 +590,32 @@ fn save_as_intervals<'tcx>(
             twostep = TwoStepIndex::from_u32(twostep.as_u32() + 1);
             debug_assert_eq!(twostep, two_step_loc(loc, Effect::After));
             append_at(&mut values, &state, twostep);
-            // Ensure we have a non-zero live range even for dead stores. This is done by marking
-            // all the written-to locals as live in the second half of the statement.
-            VisitPlacesWith(|place, ctxt| match DefUse::for_place(place, ctxt) {
-                DefUse::Def | DefUse::PartialWrite => {
-                    if let Some(relevant) = relevant.shrink[place.local] {
-                        values.insert(relevant, twostep);
+            // Like terminators, ensure we have a non-zero live range even for dead stores.
+            // Some rvalues interleave reads and writes, for instance `Rvalue::Aggregate`, see
+            // https://github.com/rust-lang/rust/issues/146383. By precaution, treat statements
+            // as behaving so by default.
+            // We make an exception for simple assignments `_a.stuff = {copy|move} _b.stuff`,
+            // as marking `_b` live here would prevent unification.
+            let is_simple_assignment = match stmt.kind {
+                StatementKind::Assign(box (
+                    lhs,
+                    Rvalue::CopyForDeref(rhs)
+                    | Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
+                )) => lhs.projection == rhs.projection,
+                _ => false,
+            };
+            VisitPlacesWith(|place: Place<'tcx>, ctxt| {
+                if let Some(relevant) = relevant.shrink[place.local] {
+                    match DefUse::for_place(place, ctxt) {
+                        DefUse::Def | DefUse::PartialWrite => {
+                            values.insert(relevant, twostep);
+                        }
+                        DefUse::Use if !is_simple_assignment => {
+                            values.insert(relevant, twostep);
+                        }
+                        DefUse::Use | DefUse::NonUse => {}
                     }
                 }
-                DefUse::Use | DefUse::NonUse => {}
             })
             .visit_statement(stmt, loc);
 
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 393f458bea2..4c25882daa9 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -1,15 +1,14 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
-use std::assert_matches::assert_matches;
-
 use hir::LangItem;
 use rustc_ast::Mutability;
 use rustc_hir as hir;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
+use rustc_span::sym;
 
 use crate::regions::InferCtxtRegionExt;
-use crate::traits::{self, FulfillmentError, ObligationCause};
+use crate::traits::{self, FulfillmentError, Obligation, ObligationCause};
 
 pub enum CopyImplementationError<'tcx> {
     InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
@@ -98,10 +97,9 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     self_type: Ty<'tcx>,
-    lang_item: LangItem,
     parent_cause: ObligationCause<'tcx>,
 ) -> Result<(), ConstParamTyImplementationError<'tcx>> {
-    assert_matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
+    let mut need_unstable_feature_bound = false;
 
     let inner_tys: Vec<_> = match *self_type.kind() {
         // Trivially okay as these types are all:
@@ -112,18 +110,14 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
 
         // Handle types gated under `feature(unsized_const_params)`
         // FIXME(unsized_const_params): Make `const N: [u8]` work then forbid references
-        ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not)
-            if lang_item == LangItem::UnsizedConstParamTy =>
-        {
+        ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not) => {
+            need_unstable_feature_bound = true;
             vec![inner_ty]
         }
-        ty::Str if lang_item == LangItem::UnsizedConstParamTy => {
+        ty::Str => {
+            need_unstable_feature_bound = true;
             vec![Ty::new_slice(tcx, tcx.types.u8)]
         }
-        ty::Str | ty::Slice(..) | ty::Ref(_, _, Mutability::Not) => {
-            return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
-        }
-
         ty::Array(inner_ty, _) => vec![inner_ty],
 
         // `str` morally acts like a newtype around `[u8]`
@@ -137,7 +131,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
                 adt,
                 args,
                 parent_cause.clone(),
-                lang_item,
+                LangItem::ConstParamTy,
             )
             .map_err(ConstParamTyImplementationError::InfrigingFields)?;
 
@@ -153,11 +147,25 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
         let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
 
+        // Make sure impls certain types are gated with #[unstable_feature_bound(unsized_const_params)]
+        if need_unstable_feature_bound {
+            ocx.register_obligation(Obligation::new(
+                tcx,
+                parent_cause.clone(),
+                param_env,
+                ty::ClauseKind::UnstableFeature(sym::unsized_const_params),
+            ));
+
+            if !ocx.select_all_or_error().is_empty() {
+                return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
+            }
+        }
+
         ocx.register_bound(
             parent_cause.clone(),
             param_env,
             inner_ty,
-            tcx.require_lang_item(lang_item, parent_cause.span),
+            tcx.require_lang_item(LangItem::ConstParamTy, parent_cause.span),
         );
 
         let errors = ocx.select_all_or_error();
diff --git a/library/alloc/src/vec/peek_mut.rs b/library/alloc/src/vec/peek_mut.rs
index c0dd941ed39..caeaf2799d7 100644
--- a/library/alloc/src/vec/peek_mut.rs
+++ b/library/alloc/src/vec/peek_mut.rs
@@ -29,9 +29,9 @@ impl<'a, T> PeekMut<'a, T> {
 
     /// Removes the peeked value from the vector and returns it.
     #[unstable(feature = "vec_peek_mut", issue = "122742")]
-    pub fn pop(self) -> T {
+    pub fn pop(this: Self) -> T {
         // SAFETY: PeekMut is only constructed if the vec is non-empty
-        unsafe { self.vec.pop().unwrap_unchecked() }
+        unsafe { this.vec.pop().unwrap_unchecked() }
     }
 }
 
diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs
index 00f640cd17e..404eb49e1ea 100644
--- a/library/alloctests/tests/vec.rs
+++ b/library/alloctests/tests/vec.rs
@@ -15,7 +15,7 @@ use std::ops::Bound::*;
 use std::panic::{AssertUnwindSafe, catch_unwind};
 use std::rc::Rc;
 use std::sync::atomic::{AtomicU32, Ordering};
-use std::vec::{Drain, IntoIter};
+use std::vec::{Drain, IntoIter, PeekMut};
 
 use crate::testing::macros::struct_with_counted_drop;
 
@@ -2647,7 +2647,7 @@ fn test_peek_mut() {
         assert_eq!(*p, 2);
         *p = 0;
         assert_eq!(*p, 0);
-        p.pop();
+        PeekMut::pop(p);
         assert_eq!(vec.len(), 1);
     } else {
         unreachable!()
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index d14419a23a1..d713e575b58 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -472,6 +472,11 @@ impl<T: Copy> SpecArrayClone for T {
 // The Default impls cannot be done with const generics because `[T; 0]` doesn't
 // require Default to be implemented, and having different impl blocks for
 // different numbers isn't supported yet.
+//
+// Trying to improve the `[T; 0]` situation has proven to be difficult.
+// Please see these issues for more context on past attempts and crater runs:
+// - https://github.com/rust-lang/rust/issues/61415
+// - https://github.com/rust-lang/rust/pull/145457
 
 macro_rules! array_impl_default {
     {$n:expr, $t:ident $($ts:ident)*} => {
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 94536f25b41..95896ab1441 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -334,9 +334,8 @@ pub macro PartialEq($item:item) {
 #[doc(alias = "!=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Eq"]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-pub trait Eq: [const] PartialEq<Self> + PointeeSized {
+pub const trait Eq: [const] PartialEq<Self> + PointeeSized {
     // this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
     // type implements `Eq` itself. The current deriving infrastructure means doing this assertion
     // without using a method on this trait is nearly impossible.
@@ -966,9 +965,8 @@ impl<T: Clone> Clone for Reverse<T> {
 #[doc(alias = ">=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Ord"]
-#[const_trait]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-pub trait Ord: [const] Eq + [const] PartialOrd<Self> + PointeeSized {
+pub const trait Ord: [const] Eq + [const] PartialOrd<Self> + PointeeSized {
     /// This method returns an [`Ordering`] between `self` and `other`.
     ///
     /// By convention, `self.cmp(&other)` returns the ordering matching the expression
@@ -1352,9 +1350,8 @@ pub macro Ord($item:item) {
 )]
 #[rustc_diagnostic_item = "PartialOrd"]
 #[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this
-#[const_trait]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
-pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
+pub const trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
     /// This method returns an ordering between `self` and `other` values if one exists.
     ///
     /// # Examples
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index d03d7a43469..1c100312a9a 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -1083,7 +1083,7 @@ pub trait Tuple {}
 // We name this differently than the derive macro so that the `adt_const_params` can
 // be used independently of `unsized_const_params` without requiring a full path
 // to the derive macro every time it is used. This should be renamed on stabilization.
-pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {}
+pub trait ConstParamTy_: StructuralPartialEq + Eq {}
 
 /// Derive macro generating an impl of the trait `ConstParamTy`.
 #[rustc_builtin_macro]
@@ -1093,23 +1093,6 @@ pub macro ConstParamTy($item:item) {
     /* compiler built-in */
 }
 
-#[lang = "unsized_const_param_ty"]
-#[unstable(feature = "unsized_const_params", issue = "95174")]
-#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
-/// A marker for types which can be used as types of `const` generic parameters.
-///
-/// Equivalent to [`ConstParamTy_`] except that this is used by
-/// the `unsized_const_params` to allow for fake unstable impls.
-pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {}
-
-/// Derive macro generating an impl of the trait `ConstParamTy`.
-#[rustc_builtin_macro]
-#[allow_internal_unstable(unsized_const_params)]
-#[unstable(feature = "unsized_const_params", issue = "95174")]
-pub macro UnsizedConstParamTy($item:item) {
-    /* compiler built-in */
-}
-
 // FIXME(adt_const_params): handle `ty::FnDef`/`ty::Closure`
 marker_impls! {
     #[unstable(feature = "adt_const_params", issue = "95174")]
@@ -1124,17 +1107,11 @@ marker_impls! {
 
 marker_impls! {
     #[unstable(feature = "unsized_const_params", issue = "95174")]
-    UnsizedConstParamTy for
-        usize, u8, u16, u32, u64, u128,
-        isize, i8, i16, i32, i64, i128,
-        bool,
-        char,
-        (),
-        {T: UnsizedConstParamTy, const N: usize} [T; N],
-
+    #[unstable_feature_bound(unsized_const_params)]
+    ConstParamTy_ for
         str,
-        {T: UnsizedConstParamTy} [T],
-        {T: UnsizedConstParamTy + ?Sized} &T,
+        {T: ConstParamTy_} [T],
+        {T: ConstParamTy_ + ?Sized} &T,
 }
 
 /// A common trait implemented by all function pointers.
diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs
index 782b826448a..f36cb8cddb8 100644
--- a/library/core/src/mem/transmutability.rs
+++ b/library/core/src/mem/transmutability.rs
@@ -1,4 +1,4 @@
-use crate::marker::{ConstParamTy_, UnsizedConstParamTy};
+use crate::marker::ConstParamTy_;
 
 /// Marks that `Src` is transmutable into `Self`.
 ///
@@ -83,6 +83,7 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy};
 /// Furthermore, stability does not imply portability. For example, the size of
 /// `usize` is stable, but not portable.
 #[unstable(feature = "transmutability", issue = "99571")]
+#[unstable_feature_bound(transmutability)]
 #[lang = "transmute_trait"]
 #[rustc_deny_explicit_impl]
 #[rustc_do_not_implement_via_object]
@@ -288,9 +289,8 @@ pub struct Assume {
 }
 
 #[unstable(feature = "transmutability", issue = "99571")]
+#[unstable_feature_bound(transmutability)]
 impl ConstParamTy_ for Assume {}
-#[unstable(feature = "transmutability", issue = "99571")]
-impl UnsizedConstParamTy for Assume {}
 
 impl Assume {
     /// With this, [`TransmuteFrom`] does not assume you have ensured any safety
diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs
index e33f58197bb..f21fe0b4438 100644
--- a/library/core/src/num/bignum.rs
+++ b/library/core/src/num/bignum.rs
@@ -335,43 +335,6 @@ macro_rules! define_bignum {
                 }
                 (self, borrow)
             }
-
-            /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
-            /// remainder.
-            pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) {
-                // Stupid slow base-2 long division taken from
-                // https://en.wikipedia.org/wiki/Division_algorithm
-                // FIXME use a greater base ($ty) for the long division.
-                assert!(!d.is_zero());
-                let digitbits = <$ty>::BITS as usize;
-                for digit in &mut q.base[..] {
-                    *digit = 0;
-                }
-                for digit in &mut r.base[..] {
-                    *digit = 0;
-                }
-                r.size = d.size;
-                q.size = 1;
-                let mut q_is_zero = true;
-                let end = self.bit_length();
-                for i in (0..end).rev() {
-                    r.mul_pow2(1);
-                    r.base[0] |= self.get_bit(i) as $ty;
-                    if &*r >= d {
-                        r.sub(d);
-                        // Set bit `i` of q to 1.
-                        let digit_idx = i / digitbits;
-                        let bit_idx = i % digitbits;
-                        if q_is_zero {
-                            q.size = digit_idx + 1;
-                            q_is_zero = false;
-                        }
-                        q.base[digit_idx] |= 1 << bit_idx;
-                    }
-                }
-                debug_assert!(q.base[q.size..].iter().all(|&d| d == 0));
-                debug_assert!(r.base[r.size..].iter().all(|&d| d == 0));
-            }
         }
 
         impl crate::cmp::PartialEq for $name {
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 3892f831076..c57a8d81ade 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -1,7 +1,7 @@
 // See core/src/primitive_docs.rs for documentation.
 
 use crate::cmp::Ordering::{self, *};
-use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
+use crate::marker::{ConstParamTy_, StructuralPartialEq};
 use crate::ops::ControlFlow::{self, Break, Continue};
 
 // Recursive macro for implementing n-ary tuple functions and operations
@@ -47,19 +47,13 @@ macro_rules! tuple_impls {
         maybe_tuple_doc! {
             $($T)+ @
             #[unstable(feature = "adt_const_params", issue = "95174")]
+            #[unstable_feature_bound(unsized_const_params)]
             impl<$($T: ConstParamTy_),+> ConstParamTy_ for ($($T,)+)
             {}
         }
 
         maybe_tuple_doc! {
             $($T)+ @
-            #[unstable(feature = "unsized_const_params", issue = "95174")]
-            impl<$($T: UnsizedConstParamTy),+> UnsizedConstParamTy for ($($T,)+)
-            {}
-        }
-
-        maybe_tuple_doc! {
-            $($T)+ @
             #[unstable(feature = "structural_match", issue = "31434")]
             impl<$($T),+> StructuralPartialEq for ($($T,)+)
             {}
diff --git a/library/coretests/tests/ascii.rs b/library/coretests/tests/ascii.rs
index ce09ee507f1..297aa114e00 100644
--- a/library/coretests/tests/ascii.rs
+++ b/library/coretests/tests/ascii.rs
@@ -505,3 +505,10 @@ fn test_escape_ascii_iter() {
     let _ = it.advance_back_by(4);
     assert_eq!(it.to_string(), r#"fastpath\xffremainder"#);
 }
+
+#[test]
+fn test_invalid_u8() {
+    for c in 128..=255 {
+        assert_eq!(core::ascii::Char::from_u8(c), None);
+    }
+}
diff --git a/library/coretests/tests/fmt/builders.rs b/library/coretests/tests/fmt/builders.rs
index ba4801f5912..156eebb1e9d 100644
--- a/library/coretests/tests/fmt/builders.rs
+++ b/library/coretests/tests/fmt/builders.rs
@@ -173,6 +173,21 @@ mod debug_struct {
             format!("{Bar:#?}")
         );
     }
+
+    #[test]
+    fn test_field_with() {
+        struct Foo;
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field_with("bar", |f| f.write_str("true"))
+                    .field_with("baz", |f| f.write_str("false"))
+                    .finish()
+            }
+        }
+
+        assert_eq!("Foo {\n    bar: true,\n    baz: false,\n}", format!("{Foo:#?}"))
+    }
 }
 
 mod debug_tuple {
diff --git a/library/coretests/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs
index 16f116d2590..586e890befe 100644
--- a/library/coretests/tests/fmt/mod.rs
+++ b/library/coretests/tests/fmt/mod.rs
@@ -58,6 +58,36 @@ fn test_fmt_debug_of_raw_pointers() {
 }
 
 #[test]
+fn test_fmt_debug_of_mut_reference() {
+    let mut x: u32 = 0;
+
+    assert_eq!(format!("{:?}", &mut x), "0");
+}
+
+#[test]
+fn test_default_write_impls() {
+    use core::fmt::Write;
+
+    struct Buf(String);
+
+    impl Write for Buf {
+        fn write_str(&mut self, s: &str) -> core::fmt::Result {
+            self.0.write_str(s)
+        }
+    }
+
+    let mut buf = Buf(String::new());
+    buf.write_char('a').unwrap();
+
+    assert_eq!(buf.0, "a");
+
+    let mut buf = Buf(String::new());
+    buf.write_fmt(format_args!("a")).unwrap();
+
+    assert_eq!(buf.0, "a");
+}
+
+#[test]
 fn test_estimated_capacity() {
     assert_eq!(format_args!("").estimated_capacity(), 0);
     assert_eq!(format_args!("{}", { "" }).estimated_capacity(), 0);
diff --git a/library/coretests/tests/fmt/num.rs b/library/coretests/tests/fmt/num.rs
index 4c145b484dd..052b16db521 100644
--- a/library/coretests/tests/fmt/num.rs
+++ b/library/coretests/tests/fmt/num.rs
@@ -323,3 +323,9 @@ fn test_format_debug_hex() {
     assert_eq!(format!("{:02x?}", b"Foo\0"), "[46, 6f, 6f, 00]");
     assert_eq!(format!("{:02X?}", b"Foo\0"), "[46, 6F, 6F, 00]");
 }
+
+#[test]
+#[should_panic = "Formatting argument out of range"]
+fn test_rt_width_too_long() {
+    let _ = format!("Hello {:width$}!", "x", width = u16::MAX as usize + 1);
+}
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index a246c806140..5c519f3a499 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -33,6 +33,7 @@
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(cstr_display)]
+#![feature(debug_closure_helpers)]
 #![feature(dec2flt)]
 #![feature(drop_guard)]
 #![feature(duration_constants)]
diff --git a/library/coretests/tests/num/bignum.rs b/library/coretests/tests/num/bignum.rs
index f213fd5366c..6dfa496e018 100644
--- a/library/coretests/tests/num/bignum.rs
+++ b/library/coretests/tests/num/bignum.rs
@@ -168,25 +168,6 @@ fn test_div_rem_small() {
 }
 
 #[test]
-fn test_div_rem() {
-    fn div_rem(n: u64, d: u64) -> (Big, Big) {
-        let mut q = Big::from_small(42);
-        let mut r = Big::from_small(42);
-        Big::from_u64(n).div_rem(&Big::from_u64(d), &mut q, &mut r);
-        (q, r)
-    }
-    assert_eq!(div_rem(1, 1), (Big::from_small(1), Big::from_small(0)));
-    assert_eq!(div_rem(4, 3), (Big::from_small(1), Big::from_small(1)));
-    assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1)));
-    assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0)));
-    assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4)));
-    assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25)));
-    assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0)));
-    assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee)));
-    assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0)));
-}
-
-#[test]
 fn test_is_zero() {
     assert!(Big::from_small(0).is_zero());
     assert!(!Big::from_small(3).is_zero());
diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs
index f8774833d0a..4d5138d539b 100644
--- a/library/coretests/tests/ptr.rs
+++ b/library/coretests/tests/ptr.rs
@@ -490,6 +490,14 @@ fn is_aligned() {
 }
 
 #[test]
+#[should_panic = "is_aligned_to: align is not a power-of-two"]
+fn invalid_is_aligned() {
+    let data = 42;
+    let ptr: *const i32 = &data;
+    assert!(ptr.is_aligned_to(3));
+}
+
+#[test]
 fn offset_from() {
     let mut a = [0; 5];
     let ptr1: *mut i32 = &mut a[1];
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index dfd6ce56a76..33a1e7ff5e4 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -21,29 +21,31 @@ use libc::fstatat as fstatat64;
 #[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))]
 use libc::fstatat64;
 #[cfg(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "solaris",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
     target_os = "illumos",
-    target_os = "aix",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
     all(target_os = "linux", target_env = "musl"),
 ))]
 use libc::readdir as readdir64;
 #[cfg(not(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
+    target_os = "freebsd",
+    target_os = "fuchsia",
+    target_os = "hurd",
     target_os = "illumos",
     target_os = "l4re",
-    target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 )))]
 use libc::readdir_r as readdir64_r;
 #[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))]
@@ -271,16 +273,17 @@ unsafe impl Send for Dir {}
 unsafe impl Sync for Dir {}
 
 #[cfg(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "hurd",
+    target_os = "illumos",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 ))]
 pub struct DirEntry {
     dir: Arc<InnerReadDir>,
@@ -295,16 +298,17 @@ pub struct DirEntry {
 // we're not using the immediate `d_name` on these targets. Keeping this as an
 // `entry` field in `DirEntry` helps reduce the `cfg` boilerplate elsewhere.
 #[cfg(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "hurd",
+    target_os = "illumos",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 ))]
 struct dirent64_min {
     d_ino: u64,
@@ -319,16 +323,17 @@ struct dirent64_min {
 }
 
 #[cfg(not(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "hurd",
+    target_os = "illumos",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 )))]
 pub struct DirEntry {
     dir: Arc<InnerReadDir>,
@@ -698,16 +703,17 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     #[cfg(any(
+        target_os = "aix",
         target_os = "android",
-        target_os = "linux",
-        target_os = "solaris",
+        target_os = "freebsd",
         target_os = "fuchsia",
-        target_os = "redox",
+        target_os = "hurd",
         target_os = "illumos",
-        target_os = "aix",
+        target_os = "linux",
         target_os = "nto",
+        target_os = "redox",
+        target_os = "solaris",
         target_os = "vita",
-        target_os = "hurd",
     ))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         use crate::sys::os::{errno, set_errno};
@@ -768,6 +774,9 @@ impl Iterator for ReadDir {
                 // only access those bytes.
                 #[cfg(not(target_os = "vita"))]
                 let entry = dirent64_min {
+                    #[cfg(target_os = "freebsd")]
+                    d_ino: (*entry_ptr).d_fileno,
+                    #[cfg(not(target_os = "freebsd"))]
                     d_ino: (*entry_ptr).d_ino as u64,
                     #[cfg(not(any(
                         target_os = "solaris",
@@ -791,16 +800,17 @@ impl Iterator for ReadDir {
     }
 
     #[cfg(not(any(
+        target_os = "aix",
         target_os = "android",
-        target_os = "linux",
-        target_os = "solaris",
+        target_os = "freebsd",
         target_os = "fuchsia",
-        target_os = "redox",
+        target_os = "hurd",
         target_os = "illumos",
-        target_os = "aix",
+        target_os = "linux",
         target_os = "nto",
+        target_os = "redox",
+        target_os = "solaris",
         target_os = "vita",
-        target_os = "hurd",
     )))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         if self.end_of_stream {
@@ -970,36 +980,32 @@ impl DirEntry {
     }
 
     #[cfg(any(
-        target_os = "linux",
+        target_os = "aix",
+        target_os = "android",
         target_os = "cygwin",
         target_os = "emscripten",
-        target_os = "android",
-        target_os = "solaris",
-        target_os = "illumos",
-        target_os = "haiku",
-        target_os = "l4re",
-        target_os = "fuchsia",
-        target_os = "redox",
-        target_os = "vxworks",
         target_os = "espidf",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "haiku",
         target_os = "horizon",
-        target_os = "vita",
-        target_os = "aix",
-        target_os = "nto",
         target_os = "hurd",
+        target_os = "illumos",
+        target_os = "l4re",
+        target_os = "linux",
+        target_os = "nto",
+        target_os = "redox",
         target_os = "rtems",
+        target_os = "solaris",
+        target_os = "vita",
+        target_os = "vxworks",
         target_vendor = "apple",
     ))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
     }
 
-    #[cfg(any(
-        target_os = "freebsd",
-        target_os = "openbsd",
-        target_os = "netbsd",
-        target_os = "dragonfly"
-    ))]
+    #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "dragonfly"))]
     pub fn ino(&self) -> u64 {
         self.entry.d_fileno as u64
     }
@@ -1014,7 +1020,6 @@ impl DirEntry {
     #[cfg(any(
         target_os = "netbsd",
         target_os = "openbsd",
-        target_os = "freebsd",
         target_os = "dragonfly",
         target_vendor = "apple",
     ))]
@@ -1030,7 +1035,6 @@ impl DirEntry {
     #[cfg(not(any(
         target_os = "netbsd",
         target_os = "openbsd",
-        target_os = "freebsd",
         target_os = "dragonfly",
         target_vendor = "apple",
     )))]
@@ -1040,6 +1044,7 @@ impl DirEntry {
 
     #[cfg(not(any(
         target_os = "android",
+        target_os = "freebsd",
         target_os = "linux",
         target_os = "solaris",
         target_os = "illumos",
@@ -1055,6 +1060,7 @@ impl DirEntry {
     }
     #[cfg(any(
         target_os = "android",
+        target_os = "freebsd",
         target_os = "linux",
         target_os = "solaris",
         target_os = "illumos",
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 2965174b45b..12e09cb07db 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -63,6 +63,21 @@ build/
     debug/
     release/
 
+  # Build directory for various tools like `typos` that are only ever
+  # built for the host system, and always with stage0 cargo.
+  misc-tools/
+    bin/
+    target/
+
+  # Directory where js dependencies like tsc and eslint are stored.
+  node_modules/
+    .bin/
+
+  # Copy of package.json and package-lock.json, because npm requires these
+  # to be in the same directory as `node_modules`.
+  package.json
+  package-lock.json
+
   # Output of the dist-related steps like dist-std, dist-rustc, and dist-docs
   dist/
 
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 2ece53eb0cc..19e87f9c293 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1039,6 +1039,9 @@ class RustBuild(object):
         # See also: <https://github.com/rust-lang/rust/issues/70208>.
         if "CARGO_BUILD_TARGET" in env:
             del env["CARGO_BUILD_TARGET"]
+        # if in CI, don't use incremental build when building bootstrap.
+        if "GITHUB_ACTIONS" in env:
+            env["CARGO_INCREMENTAL"] = "0"
         env["CARGO_TARGET_DIR"] = build_dir
         env["RUSTC"] = self.rustc()
         env["LD_LIBRARY_PATH"] = (
@@ -1145,7 +1148,8 @@ class RustBuild(object):
             os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"),
             "-Zroot-dir=" + self.rust_root,
         ]
-        args.extend("--verbose" for _ in range(self.verbose))
+        # verbose cargo output is very noisy, so only enable it with -vv
+        args.extend("--verbose" for _ in range(self.verbose - 1))
 
         if "BOOTSTRAP_TRACING" in env:
             args.append("--features=tracing")
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 723ba80eaf8..e7f5879b5f5 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3418,9 +3418,6 @@ impl Step for TierCheck {
         );
         cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
         cargo.arg(builder.rustc(self.test_compiler));
-        if builder.is_verbose() {
-            cargo.arg("--verbose");
-        }
 
         let _guard = builder.msg_test(
             "platform support check",
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index dcc4898cae1..4f096d50ea5 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -394,6 +394,9 @@ macro_rules! bootstrap_tool {
         }
 
         impl<'a> Builder<'a> {
+            /// Ensure a tool is built, then get the path to its executable.
+            ///
+            /// The actual building, if any, will be handled via [`ToolBuild`].
             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                 match tool {
                     $(Tool::$name =>
@@ -1552,6 +1555,8 @@ pub const TEST_FLOAT_PARSE_ALLOW_FEATURES: &str = "f16,cfg_target_has_reliable_f
 impl Builder<'_> {
     /// Gets a `BootstrapCommand` which is ready to run `tool` in `stage` built for
     /// `host`.
+    ///
+    /// This also ensures that the given tool is built (using [`ToolBuild`]).
     pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand {
         let mut cmd = command(self.tool_exe(tool));
         let compiler = self.compiler(0, self.config.host_target);
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 924bb4adb42..8e65ec7ce50 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -1133,7 +1133,7 @@ impl Builder<'_> {
             cargo.env("RUSTC_BACKTRACE_ON_ICE", "1");
         }
 
-        if self.is_verbose() {
+        if self.is_verbose_than(1) {
             // This provides very useful logs especially when debugging build cache-related stuff.
             cargo.env("CARGO_LOG", "cargo::core::compiler::fingerprint=info");
         }
@@ -1275,8 +1275,9 @@ impl Builder<'_> {
             cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
         }
 
-        for _ in 0..self.verbosity {
-            cargo.arg("-v");
+        // verbose cargo output is very noisy, so only enable it with -vv
+        for _ in 0..self.verbosity.saturating_sub(1) {
+            cargo.arg("--verbose");
         }
 
         match (mode, self.config.rust_codegen_units_std, self.config.rust_codegen_units) {
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 04cf63f1c6d..68202500d97 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -287,7 +287,7 @@ than building it.
 
             if !has_target {
                 panic!(
-                    "No such target exists in the target list,\n\
+                    "{target_str}: No such target exists in the target list,\n\
                      make sure to correctly specify the location \
                      of the JSON specification file \
                      for custom targets!\n\
diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md
index 28d3dc32a63..f6b78eed24f 100644
--- a/src/doc/rustc/src/target-tier-policy.md
+++ b/src/doc/rustc/src/target-tier-policy.md
@@ -701,4 +701,4 @@ RFC process, with approval by the compiler and infra teams. Any such proposal
 will be communicated widely to the Rust community, both when initially proposed
 and before being dropped from a stable release.
 
-[MCP]: https://forge.rust-lang.org/compiler/mcp.html
+[MCP]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#how-do-i-submit-an-mcp
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 143ccdcb9e5..6da102b1b5f 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -203,6 +203,10 @@ impl CodegenBackend {
             Self::Llvm => "llvm",
         }
     }
+
+    pub fn is_llvm(self) -> bool {
+        matches!(self, Self::Llvm)
+    }
 }
 
 /// Configuration for `compiletest` *per invocation*.
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 857953072c4..1277fd225eb 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -1446,6 +1446,7 @@ pub(crate) fn make_test_description<R: Read>(
     cache: &DirectivesCache,
     name: String,
     path: &Utf8Path,
+    filterable_path: &Utf8Path,
     src: R,
     test_revision: Option<&str>,
     poisoned: &mut bool,
@@ -1520,7 +1521,13 @@ pub(crate) fn make_test_description<R: Read>(
         _ => ShouldPanic::No,
     };
 
-    CollectedTestDesc { name, ignore, ignore_message, should_panic }
+    CollectedTestDesc {
+        name,
+        filterable_path: filterable_path.to_owned(),
+        ignore,
+        ignore_message,
+        should_panic,
+    }
 }
 
 fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision {
diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs
index ee46f4c70cb..3b7a9478717 100644
--- a/src/tools/compiletest/src/directives/needs.rs
+++ b/src/tools/compiletest/src/directives/needs.rs
@@ -81,8 +81,8 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-enzyme",
-            condition: config.has_enzyme,
-            ignore_reason: "ignored when LLVM Enzyme is disabled",
+            condition: config.has_enzyme && config.default_codegen_backend.is_llvm(),
+            ignore_reason: "ignored when LLVM Enzyme is disabled or LLVM is not the default codegen backend",
         },
         Need {
             name: "needs-run-enabled",
@@ -161,8 +161,8 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-llvm-zstd",
-            condition: cache.llvm_zstd,
-            ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
+            condition: cache.llvm_zstd && config.default_codegen_backend.is_llvm(),
+            ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression or LLVM is not the default codegen backend",
         },
         Need {
             name: "needs-rustc-debug-assertions",
@@ -279,7 +279,10 @@ pub(super) fn handle_needs(
 
     // Handled elsewhere.
     if name == "needs-llvm-components" {
-        return IgnoreDecision::Continue;
+        if config.default_codegen_backend.is_llvm() {
+            return IgnoreDecision::Continue;
+        }
+        return IgnoreDecision::Ignore { reason: "LLVM specific test".into() };
     }
 
     let mut found_valid = false;
diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs
index 33a02eb29fd..16cf76be9a5 100644
--- a/src/tools/compiletest/src/directives/tests.rs
+++ b/src/tools/compiletest/src/directives/tests.rs
@@ -14,6 +14,7 @@ fn make_test_description<R: Read>(
     config: &Config,
     name: String,
     path: &Utf8Path,
+    filterable_path: &Utf8Path,
     src: R,
     revision: Option<&str>,
 ) -> CollectedTestDesc {
@@ -24,6 +25,7 @@ fn make_test_description<R: Read>(
         &cache,
         name,
         path,
+        filterable_path,
         src,
         revision,
         &mut poisoned,
@@ -221,7 +223,7 @@ fn parse_rs(config: &Config, contents: &str) -> EarlyProps {
 fn check_ignore(config: &Config, contents: &str) -> bool {
     let tn = String::new();
     let p = Utf8Path::new("a.rs");
-    let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None);
+    let d = make_test_description(&config, tn, p, p, std::io::Cursor::new(contents), None);
     d.ignore
 }
 
@@ -231,9 +233,9 @@ fn should_fail() {
     let tn = String::new();
     let p = Utf8Path::new("a.rs");
 
-    let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None);
+    let d = make_test_description(&config, tn.clone(), p, p, std::io::Cursor::new(""), None);
     assert_eq!(d.should_panic, ShouldPanic::No);
-    let d = make_test_description(&config, tn, p, std::io::Cursor::new("//@ should-fail"), None);
+    let d = make_test_description(&config, tn, p, p, std::io::Cursor::new("//@ should-fail"), None);
     assert_eq!(d.should_panic, ShouldPanic::Yes);
 }
 
diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs
index b0dc24798b6..c8e13d44573 100644
--- a/src/tools/compiletest/src/executor.rs
+++ b/src/tools/compiletest/src/executor.rs
@@ -12,6 +12,8 @@ use std::num::NonZero;
 use std::sync::{Arc, Mutex, mpsc};
 use std::{env, hint, io, mem, panic, thread};
 
+use camino::Utf8PathBuf;
+
 use crate::common::{Config, TestPaths};
 use crate::output_capture::{self, ConsoleOut};
 use crate::panic_hook;
@@ -293,8 +295,15 @@ fn filter_tests(opts: &Config, tests: Vec<CollectedTest>) -> Vec<CollectedTest>
     let mut filtered = tests;
 
     let matches_filter = |test: &CollectedTest, filter_str: &str| {
-        let test_name = &test.desc.name;
-        if opts.filter_exact { test_name == filter_str } else { test_name.contains(filter_str) }
+        if opts.filter_exact {
+            // When `--exact` is used we must use `filterable_path` to get
+            // reasonable filtering behavior.
+            test.desc.filterable_path.as_str() == filter_str
+        } else {
+            // For compatibility we use the name (which includes the full path)
+            // if `--exact` is not used.
+            test.desc.name.contains(filter_str)
+        }
     };
 
     // Remove tests that don't match the test filter
@@ -339,6 +348,7 @@ pub(crate) struct CollectedTest {
 /// Information that was historically needed to create a libtest `TestDesc`.
 pub(crate) struct CollectedTestDesc {
     pub(crate) name: String,
+    pub(crate) filterable_path: Utf8PathBuf,
     pub(crate) ignore: bool,
     pub(crate) ignore_message: Option<Cow<'static, str>>,
     pub(crate) should_panic: ShouldPanic,
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index f647f96a9bf..ce2a3d4b5fb 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -317,11 +317,17 @@ pub fn parse_config(args: Vec<String>) -> Config {
             .free
             .iter()
             .map(|f| {
+                // Here `f` is relative to `./tests/run-make`. So if you run
+                //
+                //   ./x test tests/run-make/crate-loading
+                //
+                //  then `f` is "crate-loading".
                 let path = Utf8Path::new(f);
                 let mut iter = path.iter().skip(1);
 
-                // We skip the test folder and check if the user passed `rmake.rs`.
                 if iter.next().is_some_and(|s| s == "rmake.rs") && iter.next().is_none() {
+                    // Strip the "rmake.rs" suffix. For example, if `f` is
+                    // "crate-loading/rmake.rs" then this gives us "crate-loading".
                     path.parent().unwrap().to_string()
                 } else {
                     f.to_string()
@@ -329,6 +335,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
             })
             .collect::<Vec<_>>()
     } else {
+        // Note that the filters are relative to the root dir of the different test
+        // suites. For example, with:
+        //
+        //   ./x test tests/ui/lint/unused
+        //
+        // the filter is "lint/unused".
         matches.free.clone()
     };
     let compare_mode = matches.opt_str("compare-mode").map(|s| {
@@ -472,7 +484,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
             let value = matches
                 .opt_str("new-output-capture")
                 .or_else(|| env::var("COMPILETEST_NEW_OUTPUT_CAPTURE").ok())
-                .unwrap_or_else(|| "off".to_owned());
+                .unwrap_or_else(|| "on".to_owned());
             parse_bool_option(&value)
                 .unwrap_or_else(|| panic!("unknown `--new-output-capture` value `{value}` given"))
         },
@@ -911,7 +923,8 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
     collector.tests.extend(revisions.into_iter().map(|revision| {
         // Create a test name and description to hand over to the executor.
         let src_file = fs::File::open(&test_path).expect("open test file to parse ignores");
-        let test_name = make_test_name(&cx.config, testpaths, revision);
+        let (test_name, filterable_path) =
+            make_test_name_and_filterable_path(&cx.config, testpaths, revision);
         // Create a description struct for the test/revision.
         // This is where `ignore-*`/`only-*`/`needs-*` directives are handled,
         // because they historically needed to set the libtest ignored flag.
@@ -920,6 +933,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
             &cx.cache,
             test_name,
             &test_path,
+            &filterable_path,
             src_file,
             revision,
             &mut collector.poisoned,
@@ -1072,7 +1086,11 @@ impl Stamp {
 }
 
 /// Creates a name for this test/revision that can be handed over to the executor.
-fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String {
+fn make_test_name_and_filterable_path(
+    config: &Config,
+    testpaths: &TestPaths,
+    revision: Option<&str>,
+) -> (String, Utf8PathBuf) {
     // Print the name of the file, relative to the sources root.
     let path = testpaths.file.strip_prefix(&config.src_root).unwrap();
     let debugger = match config.debugger {
@@ -1084,14 +1102,23 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>
         None => String::new(),
     };
 
-    format!(
+    let name = format!(
         "[{}{}{}] {}{}",
         config.mode,
         debugger,
         mode_suffix,
         path,
         revision.map_or("".to_string(), |rev| format!("#{}", rev))
-    )
+    );
+
+    // `path` is the full path from the repo root like, `tests/ui/foo/bar.rs`.
+    // Filtering is applied without the `tests/ui/` part, so strip that off.
+    // First strip off "tests" to make sure we don't have some unexpected path.
+    let mut filterable_path = path.strip_prefix("tests").unwrap().to_owned();
+    // Now strip off e.g. "ui" or "run-make" component.
+    filterable_path = filterable_path.components().skip(1).collect();
+
+    (name, filterable_path)
 }
 
 /// Checks that test discovery didn't find any tests whose name stem is a prefix
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
index dd7dae9cecf..d907c5de797 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
@@ -1,4 +1,6 @@
 //@revisions: stack tree
+// Ensure this even hits the aliasing model
+//@compile-flags: -Zmiri-disable-validation
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@error-in-other-file: pointer not dereferenceable
 
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs
index 5c947e64142..b54f27bb8b2 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs
@@ -1,4 +1,6 @@
 //@revisions: stack tree
+// Ensure this even hits the aliasing model
+//@compile-flags: -Zmiri-disable-validation
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@error-in-other-file: is a dangling pointer
 use std::ptr::NonNull;
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr
index d52143500c4..7c4fe748701 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr
@@ -11,7 +11,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8]
    |
 LL |     let ret = unsafe { &(*xraw).1 };
    |                        ^^^^^^^^^^
-help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
+help: <TAG> was later invalidated at offsets [0x4..0x8] by a write access
   --> tests/fail/both_borrows/return_invalid_shr.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr
index ee0f313d980..a8e3553aae2 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Frozen
    |
 LL |     let ret = unsafe { &(*xraw).1 };
    |                        ^^^^^^^^^^
-help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
+help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
   --> tests/fail/both_borrows/return_invalid_shr.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
index d66c8eeb1af..8411437ea4c 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8]
    |
 LL |     let ret = Some(unsafe { &(*xraw).1 });
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
+help: <TAG> was later invalidated at offsets [0x4..0x8] by a write access
   --> tests/fail/both_borrows/return_invalid_shr_option.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
index 16110e5b062..39da45ad6db 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Frozen
    |
 LL |     let ret = Some(unsafe { &(*xraw).1 });
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
+help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
   --> tests/fail/both_borrows/return_invalid_shr_option.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
index 727b52ec729..a7c422aa73f 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0x8]
    |
 LL |     let ret = (unsafe { &(*xraw).1 },);
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
-help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
+help: <TAG> was later invalidated at offsets [0x4..0x8] by a write access
   --> tests/fail/both_borrows/return_invalid_shr_tuple.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
index f93698f570e..66b03e57905 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Frozen
    |
 LL |     let ret = (unsafe { &(*xraw).1 },);
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
-help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
+help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
   --> tests/fail/both_borrows/return_invalid_shr_tuple.rs:LL:CC
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
diff --git a/src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs
new file mode 100644
index 00000000000..8d7b1946242
--- /dev/null
+++ b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.rs
@@ -0,0 +1,18 @@
+//! This is like `pass/overlapping_assignment_aggregate_scalar.rs` but with a non-scalar
+//! type, and that makes it definite UB.
+#![feature(custom_mir, core_intrinsics)]
+#![allow(internal_features)]
+
+use std::intrinsics::mir::*;
+
+#[custom_mir(dialect = "runtime")]
+fn main() {
+    mir! {
+        let _1: ([u8; 1],);
+        {
+            _1.0 = [0_u8; 1];
+            _1 = (_1.0, ); //~ERROR: overlapping ranges
+            Return()
+        }
+    }
+}
diff --git a/src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr
new file mode 100644
index 00000000000..f2a6d326b71
--- /dev/null
+++ b/src/tools/miri/tests/fail/overlapping_assignment_aggregate.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
+  --> tests/fail/overlapping_assignment_aggregate.rs:LL:CC
+   |
+LL |             _1 = (_1.0, );
+   |             ^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at tests/fail/overlapping_assignment_aggregate.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/validity/nonzero.stderr b/src/tools/miri/tests/fail/validity/nonzero.stderr
index 0c3a35d6b9f..7be3ef46639 100644
--- a/src/tools/miri/tests/fail/validity/nonzero.stderr
+++ b/src/tools/miri/tests/fail/validity/nonzero.stderr
@@ -2,7 +2,7 @@ error: Undefined Behavior: constructing invalid value: encountered 0, but expect
   --> tests/fail/validity/nonzero.rs:LL:CC
    |
 LL |     let _x = Some(unsafe { NonZero(0) });
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |                            ^^^^^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs b/src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs
new file mode 100644
index 00000000000..0cb2f764242
--- /dev/null
+++ b/src/tools/miri/tests/pass/overlapping_assignment_aggregate_scalar.rs
@@ -0,0 +1,19 @@
+#![feature(custom_mir, core_intrinsics)]
+#![allow(internal_features)]
+
+use std::intrinsics::mir::*;
+
+#[custom_mir(dialect = "runtime")]
+fn main() {
+    mir! {
+        let _1: (u8,);
+        {
+            _1.0 = 0_u8;
+            // This is a scalar type, so overlap is (for now) not UB.
+            // However, we used to treat such overlapping assignments incorrectly
+            // (see <https://github.com/rust-lang/rust/issues/146383#issuecomment-3273224645>).
+            _1 = (_1.0, );
+            Return()
+        }
+    }
+}
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 4f9352d11b1..b3e95e087e3 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -39,7 +39,6 @@ fn init_compiler_benchmarks(
         "--exact-match",
         crates.join(",").as_str(),
     ])
-    .env("RUST_LOG", "collector=debug")
     .env("RUSTC", env.rustc_stage_0().as_str())
     .env("RUSTC_BOOTSTRAP", "1")
     .workdir(&env.rustc_perf_dir());
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index a9804761400..568ec0c1198 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -48,40 +48,116 @@ const LICENSES: &[&str] = &[
 
 type ExceptionList = &'static [(&'static str, &'static str)];
 
+#[derive(Clone, Copy)]
+pub(crate) struct WorkspaceInfo<'a> {
+    /// Path to the directory containing the workspace root Cargo.toml file.
+    pub(crate) path: &'a str,
+    /// The list of license exceptions.
+    pub(crate) exceptions: ExceptionList,
+    /// Optionally:
+    /// * A list of crates for which dependencies need to be explicitly allowed.
+    /// * The list of allowed dependencies.
+    /// * The source code location of the allowed dependencies list
+    crates_and_deps: Option<(&'a [&'a str], &'a [&'a str], ListLocation)>,
+    /// Submodules required for the workspace
+    pub(crate) submodules: &'a [&'a str],
+}
+
 /// The workspaces to check for licensing and optionally permitted dependencies.
-///
-/// Each entry consists of a tuple with the following elements:
-///
-/// * The path to the workspace root Cargo.toml file.
-/// * The list of license exceptions.
-/// * Optionally a tuple of:
-///     * A list of crates for which dependencies need to be explicitly allowed.
-///     * The list of allowed dependencies.
-/// * Submodules required for the workspace.
 // FIXME auto detect all cargo workspaces
-pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>, &[&str])] = &[
+pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[
     // The root workspace has to be first for check_rustfix to work.
-    (".", EXCEPTIONS, Some((&["rustc-main"], PERMITTED_RUSTC_DEPENDENCIES)), &[]),
-    ("library", EXCEPTIONS_STDLIB, Some((&["sysroot"], PERMITTED_STDLIB_DEPENDENCIES)), &[]),
-    // Outside of the alphabetical section because rustfmt formats it using multiple lines.
-    (
-        "compiler/rustc_codegen_cranelift",
-        EXCEPTIONS_CRANELIFT,
-        Some((&["rustc_codegen_cranelift"], PERMITTED_CRANELIFT_DEPENDENCIES)),
-        &[],
-    ),
-    // tidy-alphabetical-start
-    ("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None, &[]),
-    ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None, &[]),
-    ("src/tools/cargo", EXCEPTIONS_CARGO, None, &["src/tools/cargo"]),
-    //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
-    //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
-    ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]),
-    ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]),
-    ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]),
-    ("src/tools/test-float-parse", EXCEPTIONS, None, &[]),
-    ("tests/run-make-cargo/uefi-qemu/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None, &[]),
-    // tidy-alphabetical-end
+    WorkspaceInfo {
+        path: ".",
+        exceptions: EXCEPTIONS,
+        crates_and_deps: Some((
+            &["rustc-main"],
+            PERMITTED_RUSTC_DEPENDENCIES,
+            PERMITTED_RUSTC_DEPS_LOCATION,
+        )),
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "library",
+        exceptions: EXCEPTIONS_STDLIB,
+        crates_and_deps: Some((
+            &["sysroot"],
+            PERMITTED_STDLIB_DEPENDENCIES,
+            PERMITTED_STDLIB_DEPS_LOCATION,
+        )),
+        submodules: &[],
+    },
+    {
+        WorkspaceInfo {
+            path: "compiler/rustc_codegen_cranelift",
+            exceptions: EXCEPTIONS_CRANELIFT,
+            crates_and_deps: Some((
+                &["rustc_codegen_cranelift"],
+                PERMITTED_CRANELIFT_DEPENDENCIES,
+                PERMITTED_CRANELIFT_DEPS_LOCATION,
+            )),
+            submodules: &[],
+        }
+    },
+    WorkspaceInfo {
+        path: "compiler/rustc_codegen_gcc",
+        exceptions: EXCEPTIONS_GCC,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "src/bootstrap",
+        exceptions: EXCEPTIONS_BOOTSTRAP,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "src/tools/cargo",
+        exceptions: EXCEPTIONS_CARGO,
+        crates_and_deps: None,
+        submodules: &["src/tools/cargo"],
+    },
+    // FIXME uncomment once all deps are vendored
+    //  WorkspaceInfo {
+    //      path: "src/tools/miri/test-cargo-miri",
+    //      crates_and_deps: None
+    //      submodules: &[],
+    //  },
+    // WorkspaceInfo {
+    //      path: "src/tools/miri/test_dependencies",
+    //      crates_and_deps: None,
+    //      submodules: &[],
+    //  }
+    WorkspaceInfo {
+        path: "src/tools/rust-analyzer",
+        exceptions: EXCEPTIONS_RUST_ANALYZER,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "src/tools/rustbook",
+        exceptions: EXCEPTIONS_RUSTBOOK,
+        crates_and_deps: None,
+        submodules: &["src/doc/book", "src/doc/reference"],
+    },
+    WorkspaceInfo {
+        path: "src/tools/rustc-perf",
+        exceptions: EXCEPTIONS_RUSTC_PERF,
+        crates_and_deps: None,
+        submodules: &["src/tools/rustc-perf"],
+    },
+    WorkspaceInfo {
+        path: "src/tools/test-float-parse",
+        exceptions: EXCEPTIONS,
+        crates_and_deps: None,
+        submodules: &[],
+    },
+    WorkspaceInfo {
+        path: "tests/run-make-cargo/uefi-qemu/uefi_qemu_test",
+        exceptions: EXCEPTIONS_UEFI_QEMU_TEST,
+        crates_and_deps: None,
+        submodules: &[],
+    },
 ];
 
 /// These are exceptions to Rust's permissive licensing policy, and
@@ -226,7 +302,20 @@ const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[
     ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptable, but we use it under MIT OR Apache-2.0
 ];
 
-const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!());
+#[derive(Clone, Copy)]
+struct ListLocation {
+    path: &'static str,
+    line: u32,
+}
+
+/// Creates a [`ListLocation`] for the current location (with an additional offset to the actual list start);
+macro_rules! location {
+    (+ $offset:literal) => {
+        ListLocation { path: file!(), line: line!() + $offset }
+    };
+}
+
+const PERMITTED_RUSTC_DEPS_LOCATION: ListLocation = location!(+6);
 
 /// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
 ///
@@ -458,6 +547,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-end
 ];
 
+const PERMITTED_STDLIB_DEPS_LOCATION: ListLocation = location!(+2);
+
 const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-start
     "addr2line",
@@ -499,6 +590,8 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-end
 ];
 
+const PERMITTED_CRANELIFT_DEPS_LOCATION: ListLocation = location!(+2);
+
 const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-start
     "allocator-api2",
@@ -573,29 +666,30 @@ pub fn check(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) {
 
     check_proc_macro_dep_list(root, cargo, bless, bad);
 
-    for &(workspace, exceptions, permitted_deps, submodules) in WORKSPACES {
+    for &WorkspaceInfo { path, exceptions, crates_and_deps, submodules } in WORKSPACES {
         if has_missing_submodule(root, submodules) {
             continue;
         }
 
-        if !root.join(workspace).join("Cargo.lock").exists() {
-            tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
+        if !root.join(path).join("Cargo.lock").exists() {
+            tidy_error!(bad, "the `{path}` workspace doesn't have a Cargo.lock");
             continue;
         }
 
         let mut cmd = cargo_metadata::MetadataCommand::new();
         cmd.cargo_path(cargo)
-            .manifest_path(root.join(workspace).join("Cargo.toml"))
+            .manifest_path(root.join(path).join("Cargo.toml"))
             .features(cargo_metadata::CargoOpt::AllFeatures)
             .other_options(vec!["--locked".to_owned()]);
         let metadata = t!(cmd.exec());
 
-        check_license_exceptions(&metadata, workspace, exceptions, bad);
-        if let Some((crates, permitted_deps)) = permitted_deps {
-            check_permitted_dependencies(&metadata, workspace, permitted_deps, crates, bad);
+        check_license_exceptions(&metadata, path, exceptions, bad);
+        if let Some((crates, permitted_deps, location)) = crates_and_deps {
+            let descr = crates.get(0).unwrap_or(&path);
+            check_permitted_dependencies(&metadata, descr, permitted_deps, crates, location, bad);
         }
 
-        if workspace == "library" {
+        if path == "library" {
             check_runtime_license_exceptions(&metadata, bad);
             check_runtime_no_duplicate_dependencies(&metadata, bad);
             check_runtime_no_proc_macros(&metadata, bad);
@@ -840,6 +934,7 @@ fn check_permitted_dependencies(
     descr: &str,
     permitted_dependencies: &[&'static str],
     restricted_dependency_crates: &[&'static str],
+    permitted_location: ListLocation,
     bad: &mut bool,
 ) {
     let mut has_permitted_dep_error = false;
@@ -900,7 +995,7 @@ fn check_permitted_dependencies(
     }
 
     if has_permitted_dep_error {
-        eprintln!("Go to `{PERMITTED_DEPS_LOCATION}` for the list.");
+        eprintln!("Go to `{}:{}` for the list.", permitted_location.path, permitted_location.line);
     }
 }
 
diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs
index bc217a55cc1..2b212cfa67a 100644
--- a/src/tools/tidy/src/extdeps.rs
+++ b/src/tools/tidy/src/extdeps.rs
@@ -3,6 +3,8 @@
 use std::fs;
 use std::path::Path;
 
+use crate::deps::WorkspaceInfo;
+
 /// List of allowed sources for packages.
 const ALLOWED_SOURCES: &[&str] = &[
     r#""registry+https://github.com/rust-lang/crates.io-index""#,
@@ -13,22 +15,22 @@ const ALLOWED_SOURCES: &[&str] = &[
 /// Checks for external package sources. `root` is the path to the directory that contains the
 /// workspace `Cargo.toml`.
 pub fn check(root: &Path, bad: &mut bool) {
-    for &(workspace, _, _, submodules) in crate::deps::WORKSPACES {
+    for &WorkspaceInfo { path, submodules, .. } in crate::deps::WORKSPACES {
         if crate::deps::has_missing_submodule(root, submodules) {
             continue;
         }
 
         // FIXME check other workspaces too
         // `Cargo.lock` of rust.
-        let path = root.join(workspace).join("Cargo.lock");
+        let lockfile = root.join(path).join("Cargo.lock");
 
-        if !path.exists() {
-            tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
+        if !lockfile.exists() {
+            tidy_error!(bad, "the `{path}` workspace doesn't have a Cargo.lock");
             continue;
         }
 
         // Open and read the whole file.
-        let cargo_lock = t!(fs::read_to_string(&path));
+        let cargo_lock = t!(fs::read_to_string(&lockfile));
 
         // Process each line.
         for line in cargo_lock.lines() {
diff --git a/tests/codegen-llvm/asm/riscv-clobbers.rs b/tests/codegen-llvm/asm/riscv-clobbers.rs
index e55b6731098..0f235ddcdcc 100644
--- a/tests/codegen-llvm/asm/riscv-clobbers.rs
+++ b/tests/codegen-llvm/asm/riscv-clobbers.rs
@@ -17,7 +17,7 @@ extern crate minicore;
 use minicore::*;
 
 // CHECK-LABEL: @flags_clobber
-// CHECK: call void asm sideeffect "", "~{vtype},~{vl},~{vxsat},~{vxrm}"()
+// CHECK: call void asm sideeffect "", "~{fflags},~{vtype},~{vl},~{vxsat},~{vxrm}"()
 #[no_mangle]
 pub unsafe fn flags_clobber() {
     asm!("", options(nostack, nomem));
diff --git a/tests/codegen-llvm/c-variadic-lifetime.rs b/tests/codegen-llvm/c-variadic-lifetime.rs
index 5b2f8af18c8..c6d3602ef51 100644
--- a/tests/codegen-llvm/c-variadic-lifetime.rs
+++ b/tests/codegen-llvm/c-variadic-lifetime.rs
@@ -8,7 +8,7 @@
 
 #[unsafe(no_mangle)]
 unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
-    // CHECK: call void @llvm.lifetime.start.p0(i64 {{[0-9]+}}, ptr nonnull %args)
+    // CHECK: call void @llvm.lifetime.start.p0({{(i64 [0-9]+, )?}}ptr nonnull %args)
     // CHECK: call void @llvm.va_start.p0(ptr nonnull %args)
 
     let b = args.arg::<f64>();
@@ -17,5 +17,5 @@ unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
     a + b + c
 
     // CHECK: call void @llvm.va_end.p0(ptr nonnull %args)
-    // CHECK: call void @llvm.lifetime.end.p0(i64 {{[0-9]+}}, ptr nonnull %args)
+    // CHECK: call void @llvm.lifetime.end.p0({{(i64 [0-9]+, )?}}ptr nonnull %args)
 }
diff --git a/tests/codegen-llvm/rust-abi-arch-specific-adjustment.rs b/tests/codegen-llvm/rust-abi-arch-specific-adjustment.rs
index 561f081c700..ffff4b35994 100644
--- a/tests/codegen-llvm/rust-abi-arch-specific-adjustment.rs
+++ b/tests/codegen-llvm/rust-abi-arch-specific-adjustment.rs
@@ -1,15 +1,19 @@
+//@ add-core-stubs
 //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
 //@ revisions: riscv64 loongarch64
 
-//@[riscv64] only-riscv64
 //@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
 //@[riscv64] needs-llvm-components: riscv
 
-//@[loongarch64] only-loongarch64
 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
 //@[loongarch64] needs-llvm-components: loongarch
 
 #![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 #[no_mangle]
 // riscv64:     define noundef i8 @arg_attr_u8(i8 noundef zeroext %x)
diff --git a/tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-abort.diff
new file mode 100644
index 00000000000..e80660f176b
--- /dev/null
+++ b/tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-abort.diff
@@ -0,0 +1,19 @@
+- // MIR for `rewrap` before DestinationPropagation
++ // MIR for `rewrap` after DestinationPropagation
+  
+  fn rewrap() -> (u8,) {
+      let mut _0: (u8,);
+      let mut _1: (u8,);
+      let mut _2: (u8,);
+  
+      bb0: {
+-         (_1.0: u8) = const 0_u8;
+-         _0 = copy _1;
++         (_0.0: u8) = const 0_u8;
++         nop;
+          _2 = (copy (_0.0: u8),);
+          _0 = copy _2;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-unwind.diff
new file mode 100644
index 00000000000..e80660f176b
--- /dev/null
+++ b/tests/mir-opt/dest-prop/aggregate.rewrap.DestinationPropagation.panic-unwind.diff
@@ -0,0 +1,19 @@
+- // MIR for `rewrap` before DestinationPropagation
++ // MIR for `rewrap` after DestinationPropagation
+  
+  fn rewrap() -> (u8,) {
+      let mut _0: (u8,);
+      let mut _1: (u8,);
+      let mut _2: (u8,);
+  
+      bb0: {
+-         (_1.0: u8) = const 0_u8;
+-         _0 = copy _1;
++         (_0.0: u8) = const 0_u8;
++         nop;
+          _2 = (copy (_0.0: u8),);
+          _0 = copy _2;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/dest-prop/aggregate.rs b/tests/mir-opt/dest-prop/aggregate.rs
new file mode 100644
index 00000000000..636852159eb
--- /dev/null
+++ b/tests/mir-opt/dest-prop/aggregate.rs
@@ -0,0 +1,51 @@
+//@ test-mir-pass: DestinationPropagation
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
+#![feature(custom_mir, core_intrinsics)]
+#![allow(internal_features)]
+
+use std::intrinsics::mir::*;
+use std::mem::MaybeUninit;
+
+fn dump_var<T>(_: T) {}
+
+// EMIT_MIR aggregate.rewrap.DestinationPropagation.diff
+#[custom_mir(dialect = "runtime")]
+fn rewrap() -> (u8,) {
+    // CHECK-LABEL: fn rewrap(
+    // CHECK: (_0.0: u8) = const 0_u8;
+    // CHECK: _2 = (copy (_0.0: u8),);
+    // CHECK: _0 = copy _2;
+    mir! {
+        let _1: (u8,);
+        let _2: (u8,);
+        {
+            _1.0 = 0;
+            RET = _1;
+            _2 = (RET.0, );
+            RET = _2;
+            Return()
+        }
+    }
+}
+
+// EMIT_MIR aggregate.swap.DestinationPropagation.diff
+#[custom_mir(dialect = "runtime")]
+fn swap() -> (MaybeUninit<[u8; 10]>, MaybeUninit<[u8; 10]>) {
+    // CHECK-LABEL: fn swap(
+    // CHECK: _0 = const
+    // CHECK: _2 = copy _0;
+    // CHECK: _0 = (copy (_2.1: {{.*}}), copy (_2.0: {{.*}}));
+    mir! {
+        let _1: (MaybeUninit<[u8; 10]>, MaybeUninit<[u8; 10]>);
+        let _2: (MaybeUninit<[u8; 10]>, MaybeUninit<[u8; 10]>);
+        let _3: ();
+        {
+            _1 = const { (MaybeUninit::new([0; 10]), MaybeUninit::new([1; 10])) };
+            _2 = _1;
+            _1 = (_2.1, _2.0);
+            RET = _1;
+            Return()
+        }
+    }
+}
diff --git a/tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-abort.diff
new file mode 100644
index 00000000000..3aaad3aaf69
--- /dev/null
+++ b/tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-abort.diff
@@ -0,0 +1,22 @@
+- // MIR for `swap` before DestinationPropagation
++ // MIR for `swap` after DestinationPropagation
+  
+  fn swap() -> (MaybeUninit<[u8; 10]>, MaybeUninit<[u8; 10]>) {
+      let mut _0: (std::mem::MaybeUninit<[u8; 10]>, std::mem::MaybeUninit<[u8; 10]>);
+      let mut _1: (std::mem::MaybeUninit<[u8; 10]>, std::mem::MaybeUninit<[u8; 10]>);
+      let mut _2: (std::mem::MaybeUninit<[u8; 10]>, std::mem::MaybeUninit<[u8; 10]>);
+      let mut _3: ();
+  
+      bb0: {
+-         _1 = const swap::{constant#6};
+-         _2 = copy _1;
+-         _1 = (copy (_2.1: std::mem::MaybeUninit<[u8; 10]>), copy (_2.0: std::mem::MaybeUninit<[u8; 10]>));
+-         _0 = copy _1;
++         _0 = const swap::{constant#6};
++         _2 = copy _0;
++         _0 = (copy (_2.1: std::mem::MaybeUninit<[u8; 10]>), copy (_2.0: std::mem::MaybeUninit<[u8; 10]>));
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-unwind.diff
new file mode 100644
index 00000000000..3aaad3aaf69
--- /dev/null
+++ b/tests/mir-opt/dest-prop/aggregate.swap.DestinationPropagation.panic-unwind.diff
@@ -0,0 +1,22 @@
+- // MIR for `swap` before DestinationPropagation
++ // MIR for `swap` after DestinationPropagation
+  
+  fn swap() -> (MaybeUninit<[u8; 10]>, MaybeUninit<[u8; 10]>) {
+      let mut _0: (std::mem::MaybeUninit<[u8; 10]>, std::mem::MaybeUninit<[u8; 10]>);
+      let mut _1: (std::mem::MaybeUninit<[u8; 10]>, std::mem::MaybeUninit<[u8; 10]>);
+      let mut _2: (std::mem::MaybeUninit<[u8; 10]>, std::mem::MaybeUninit<[u8; 10]>);
+      let mut _3: ();
+  
+      bb0: {
+-         _1 = const swap::{constant#6};
+-         _2 = copy _1;
+-         _1 = (copy (_2.1: std::mem::MaybeUninit<[u8; 10]>), copy (_2.0: std::mem::MaybeUninit<[u8; 10]>));
+-         _0 = copy _1;
++         _0 = const swap::{constant#6};
++         _2 = copy _0;
++         _0 = (copy (_2.1: std::mem::MaybeUninit<[u8; 10]>), copy (_2.0: std::mem::MaybeUninit<[u8; 10]>));
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed
index bce6148f9e1..ae4d0107aee 100644
--- a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed
+++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed
@@ -8,7 +8,7 @@ trait Get {
 }
 
 trait Other {
-    fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get, Self: Get {}
+    fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get {}
     //~^ ERROR the trait bound `Self: Get` is not satisfied
     //~| ERROR the trait bound `Self: Get` is not satisfied
 }
diff --git a/tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs b/tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs
index e2ba459f8dd..1bfd7c34656 100644
--- a/tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs
+++ b/tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs
@@ -1,6 +1,6 @@
 #![feature(adt_const_params, unsized_const_params)]
 
-#[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
 pub struct Foo([u8]);
 
 #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs
index 35539193a27..d482e7fad06 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs
@@ -1,7 +1,7 @@
 #![allow(incomplete_features)]
 #![feature(adt_const_params, unsized_const_params)]
 
-fn check(_: impl std::marker::UnsizedConstParamTy) {}
+fn check(_: impl std::marker::ConstParamTy_) {}
 
 fn main() {
     check(main); //~ error: `fn() {main}` can't be used as a const parameter type
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
index c05584ef909..ff514f5608f 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
@@ -2,15 +2,15 @@ error[E0277]: `fn() {main}` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:7:11
    |
 LL |     check(main);
-   |     ----- ^^^^ the trait `UnsizedConstParamTy` is not implemented for fn item `fn() {main}`
+   |     ----- ^^^^ the trait `ConstParamTy_` is not implemented for fn item `fn() {main}`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::ConstParamTy_) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: use parentheses to call this function
    |
 LL |     check(main());
@@ -24,12 +24,12 @@ LL |     check(|| {});
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `UnsizedConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}`
+   = help: the trait `ConstParamTy_` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::ConstParamTy_) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: use parentheses to call this closure
    |
 LL -     check(|| {});
@@ -40,15 +40,15 @@ error[E0277]: `fn()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:9:11
    |
 LL |     check(main as fn());
-   |     ----- ^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `fn()`
+   |     ----- ^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `fn()`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::ConstParamTy_) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: use parentheses to call this function pointer
    |
 LL |     check(main as fn()());
@@ -58,16 +58,16 @@ error[E0277]: `&mut ()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:10:11
    |
 LL |     check(&mut ());
-   |     ----- ^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `&mut ()`
+   |     ----- ^^^^^^^ the trait `ConstParamTy_` is not implemented for `&mut ()`
    |     |
    |     required by a bound introduced by this call
    |
-   = note: `UnsizedConstParamTy` is implemented for `&()`, but not for `&mut ()`
+   = note: `ConstParamTy_` is implemented for `&()`, but not for `&mut ()`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::ConstParamTy_) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: consider removing the leading `&`-reference
    |
 LL -     check(&mut ());
@@ -78,31 +78,31 @@ error[E0277]: `*mut ()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:11:11
    |
 LL |     check(&mut () as *mut ());
-   |     ----- ^^^^^^^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `*mut ()`
+   |     ----- ^^^^^^^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `*mut ()`
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `UnsizedConstParamTy` is implemented for `()`
+   = help: the trait `ConstParamTy_` is implemented for `()`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::ConstParamTy_) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: `*const ()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:12:11
    |
 LL |     check(&() as *const ());
-   |     ----- ^^^^^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `*const ()`
+   |     ----- ^^^^^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `*const ()`
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `UnsizedConstParamTy` is implemented for `()`
+   = help: the trait `ConstParamTy_` is implemented for `()`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::ConstParamTy_) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs
index 6a553c2e085..2fcf872c99a 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs
@@ -1,12 +1,9 @@
 #![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::{ConstParamTy_, UnsizedConstParamTy};
+use std::marker::ConstParamTy_;
 
 fn foo(a: &dyn ConstParamTy_) {}
 //~^ ERROR: the trait `ConstParamTy_`
 
-fn bar(a: &dyn UnsizedConstParamTy) {}
-//~^ ERROR: the trait `UnsizedConstParamTy`
-
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr
index c71ec24dda3..ce695ff66d5 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr
@@ -15,23 +15,6 @@ LL - fn foo(a: &dyn ConstParamTy_) {}
 LL + fn foo(a: &impl ConstParamTy_) {}
    |
 
-error[E0038]: the trait `UnsizedConstParamTy` is not dyn compatible
-  --> $DIR/const_param_ty_dyn_compatibility.rs:9:16
-   |
-LL | fn bar(a: &dyn UnsizedConstParamTy) {}
-   |                ^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-   = note: the trait is not dyn compatible because it uses `Self` as a type parameter
-help: consider using an opaque type instead
-   |
-LL - fn bar(a: &dyn UnsizedConstParamTy) {}
-LL + fn bar(a: &impl UnsizedConstParamTy) {}
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs
index 7ffdafa33e9..a86d74275de 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs
@@ -4,7 +4,7 @@
 #[derive(PartialEq, Eq)]
 struct NotParam;
 
-fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
+fn check<T: std::marker::ConstParamTy_ + ?Sized>() {}
 
 fn main() {
     check::<&NotParam>(); //~ error: `NotParam` can't be used as a const parameter type
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
index 158e76630f3..ca2aa3adcb7 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
@@ -4,17 +4,17 @@ error[E0277]: `NotParam` can't be used as a const parameter type
 LL |     check::<&NotParam>();
    |             ^^^^^^^^^ unsatisfied trait bound
    |
-help: the trait `UnsizedConstParamTy` is not implemented for `NotParam`
+help: the trait `ConstParamTy_` is not implemented for `NotParam`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:5:1
    |
 LL | struct NotParam;
    | ^^^^^^^^^^^^^^^
-   = note: required for `&NotParam` to implement `UnsizedConstParamTy`
+   = note: required for `&NotParam` to implement `ConstParamTy_`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
    |
-LL | fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check<T: std::marker::ConstParamTy_ + ?Sized>() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:11:13
@@ -22,17 +22,17 @@ error[E0277]: `NotParam` can't be used as a const parameter type
 LL |     check::<[NotParam]>();
    |             ^^^^^^^^^^ unsatisfied trait bound
    |
-help: the trait `UnsizedConstParamTy` is not implemented for `NotParam`
+help: the trait `ConstParamTy_` is not implemented for `NotParam`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:5:1
    |
 LL | struct NotParam;
    | ^^^^^^^^^^^^^^^
-   = note: required for `[NotParam]` to implement `UnsizedConstParamTy`
+   = note: required for `[NotParam]` to implement `ConstParamTy_`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
    |
-LL | fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check<T: std::marker::ConstParamTy_ + ?Sized>() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:12:13
@@ -40,17 +40,17 @@ error[E0277]: `NotParam` can't be used as a const parameter type
 LL |     check::<[NotParam; 17]>();
    |             ^^^^^^^^^^^^^^ unsatisfied trait bound
    |
-help: the trait `UnsizedConstParamTy` is not implemented for `NotParam`
+help: the trait `ConstParamTy_` is not implemented for `NotParam`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:5:1
    |
 LL | struct NotParam;
    | ^^^^^^^^^^^^^^^
-   = note: required for `[NotParam; 17]` to implement `UnsizedConstParamTy`
+   = note: required for `[NotParam; 17]` to implement `ConstParamTy_`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
    |
-LL | fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check<T: std::marker::ConstParamTy_ + ?Sized>() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
index 98a8eb6ee95..24bbc5a9a23 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
@@ -3,7 +3,7 @@
 #![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::UnsizedConstParamTy;
+use std::marker::{ConstParamTy, ConstParamTy_};
 
 #[derive(PartialEq, Eq)]
 struct S<T> {
@@ -11,15 +11,15 @@ struct S<T> {
     gen: T,
 }
 
-impl<T: UnsizedConstParamTy> UnsizedConstParamTy for S<T> {}
+impl<T: ConstParamTy_> ConstParamTy_ for S<T> {}
 
-#[derive(PartialEq, Eq, UnsizedConstParamTy)]
+#[derive(PartialEq, Eq, ConstParamTy)]
 struct D<T> {
     field: u8,
     gen: T,
 }
 
-fn check<T: UnsizedConstParamTy + ?Sized>() {}
+fn check<T: ConstParamTy_ + ?Sized>() {}
 
 fn main() {
     check::<u8>();
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
index 8b3d0546010..0614ea97b1a 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
@@ -7,10 +7,10 @@ struct NotParam;
 #[derive(PartialEq, Eq)]
 struct CantParam(NotParam);
 
-impl std::marker::UnsizedConstParamTy for CantParam {}
+impl std::marker::ConstParamTy_ for CantParam {}
 //~^ error: the trait `ConstParamTy_` cannot be implemented for this type
 
-#[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
 //~^ error: the trait `ConstParamTy_` cannot be implemented for this type
 struct CantParamDerive(NotParam);
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
index a4e5736d834..fd1836802c4 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
@@ -1,17 +1,17 @@
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/const_param_ty_impl_bad_field.rs:10:43
+  --> $DIR/const_param_ty_impl_bad_field.rs:10:37
    |
 LL | struct CantParam(NotParam);
    |                  -------- this field does not implement `ConstParamTy_`
 LL |
-LL | impl std::marker::UnsizedConstParamTy for CantParam {}
-   |                                           ^^^^^^^^^
+LL | impl std::marker::ConstParamTy_ for CantParam {}
+   |                                     ^^^^^^^^^
 
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
   --> $DIR/const_param_ty_impl_bad_field.rs:13:10
    |
-LL | #[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | struct CantParamDerive(NotParam);
    |                        -------- this field does not implement `ConstParamTy_`
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
index e743b78fd13..a1c8eccfb09 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
@@ -3,20 +3,20 @@
 
 #[derive(PartialEq, Eq)]
 struct ImplementsConstParamTy;
-impl std::marker::UnsizedConstParamTy for ImplementsConstParamTy {}
+impl std::marker::ConstParamTy_ for ImplementsConstParamTy {}
 
 struct CantParam(ImplementsConstParamTy);
 
-impl std::marker::UnsizedConstParamTy for CantParam {}
+impl std::marker::ConstParamTy_ for CantParam {}
 //~^ error: the type `CantParam` does not `#[derive(PartialEq)]`
 //~| ERROR the trait bound `CantParam: Eq` is not satisfied
 
-#[derive(std::marker::UnsizedConstParamTy)]
+#[derive(std::marker::ConstParamTy)]
 //~^ error: the type `CantParamDerive` does not `#[derive(PartialEq)]`
 //~| ERROR the trait bound `CantParamDerive: Eq` is not satisfied
 struct CantParamDerive(ImplementsConstParamTy);
 
-fn check<T: std::marker::UnsizedConstParamTy>() {}
+fn check<T: std::marker::ConstParamTy_>() {}
 
 fn main() {
     check::<ImplementsConstParamTy>();
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
index d3141381db8..c6b791ed967 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
@@ -1,10 +1,10 @@
 error[E0277]: the trait bound `CantParam: Eq` is not satisfied
-  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:43
+  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:37
    |
-LL | impl std::marker::UnsizedConstParamTy for CantParam {}
-   |                                           ^^^^^^^^^ the trait `Eq` is not implemented for `CantParam`
+LL | impl std::marker::ConstParamTy_ for CantParam {}
+   |                                     ^^^^^^^^^ the trait `Eq` is not implemented for `CantParam`
    |
-note: required by a bound in `UnsizedConstParamTy`
+note: required by a bound in `ConstParamTy_`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 help: consider annotating `CantParam` with `#[derive(Eq)]`
    |
@@ -13,26 +13,26 @@ LL | struct CantParam(ImplementsConstParamTy);
    |
 
 error[E0277]: the type `CantParam` does not `#[derive(PartialEq)]`
-  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:43
+  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:37
    |
-LL | impl std::marker::UnsizedConstParamTy for CantParam {}
-   |                                           ^^^^^^^^^ unsatisfied trait bound
+LL | impl std::marker::ConstParamTy_ for CantParam {}
+   |                                     ^^^^^^^^^ unsatisfied trait bound
    |
 help: the trait `StructuralPartialEq` is not implemented for `CantParam`
   --> $DIR/const_param_ty_impl_no_structural_eq.rs:8:1
    |
 LL | struct CantParam(ImplementsConstParamTy);
    | ^^^^^^^^^^^^^^^^
-note: required by a bound in `UnsizedConstParamTy`
+note: required by a bound in `ConstParamTy_`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 
 error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied
   --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10
    |
-LL | #[derive(std::marker::UnsizedConstParamTy)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive`
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive`
    |
-note: required by a bound in `UnsizedConstParamTy`
+note: required by a bound in `ConstParamTy_`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 help: consider annotating `CantParamDerive` with `#[derive(Eq)]`
    |
@@ -43,15 +43,15 @@ LL | struct CantParamDerive(ImplementsConstParamTy);
 error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]`
   --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10
    |
-LL | #[derive(std::marker::UnsizedConstParamTy)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
    |
 help: the trait `StructuralPartialEq` is not implemented for `CantParamDerive`
   --> $DIR/const_param_ty_impl_no_structural_eq.rs:17:1
    |
 LL | struct CantParamDerive(ImplementsConstParamTy);
    | ^^^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `UnsizedConstParamTy`
+note: required by a bound in `ConstParamTy_`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
index 236b3bc162a..0c9b12805f7 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
@@ -12,10 +12,10 @@ impl PartialEq for Union {
 }
 impl Eq for Union {}
 
-impl std::marker::UnsizedConstParamTy for Union {}
+impl std::marker::ConstParamTy_ for Union {}
 //~^ ERROR the trait `ConstParamTy` may not be implemented for this type
 
-#[derive(std::marker::UnsizedConstParamTy)]
+#[derive(std::marker::ConstParamTy)]
 //~^ ERROR this trait cannot be derived for unions
 union UnionDerive {
     a: u8,
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
index 837c289c924..cc2147b49ae 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
@@ -1,14 +1,14 @@
 error: this trait cannot be derived for unions
   --> $DIR/const_param_ty_impl_union.rs:18:10
    |
-LL | #[derive(std::marker::UnsizedConstParamTy)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the trait `ConstParamTy` may not be implemented for this type
-  --> $DIR/const_param_ty_impl_union.rs:15:43
+  --> $DIR/const_param_ty_impl_union.rs:15:37
    |
-LL | impl std::marker::UnsizedConstParamTy for Union {}
-   |                                           ^^^^^ type is not a structure or enumeration
+LL | impl std::marker::ConstParamTy_ for Union {}
+   |                                     ^^^^^ type is not a structure or enumeration
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs
index 34ea143d254..d42ef90e1b1 100644
--- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs
+++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs
@@ -5,17 +5,14 @@ use std::marker::ConstParamTy;
 
 #[derive(ConstParamTy)]
 //~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty
-//~| ERROR the trait `ConstParamTy_` cannot be implemented for this ty
 struct Foo([*const u8; 1]);
 
 #[derive(ConstParamTy)]
 //~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty
-//~| ERROR the trait `ConstParamTy_` cannot be implemented for this ty
 struct Foo2([*mut u8; 1]);
 
 #[derive(ConstParamTy)]
 //~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty
-//~| ERROR the trait `ConstParamTy_` cannot be implemented for this ty
 struct Foo3([fn(); 1]);
 
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr
index 6b8d2394a86..442ec6b96ce 100644
--- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr
+++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr
@@ -3,91 +3,46 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
    |
 LL | #[derive(ConstParamTy)]
    |          ^^^^^^^^^^^^
-...
+LL |
 LL | struct Foo([*const u8; 1]);
    |            -------------- this field does not implement `ConstParamTy_`
    |
 note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: ConstParamTy_`
-  --> $DIR/nested_bad_const_param_ty.rs:9:12
+  --> $DIR/nested_bad_const_param_ty.rs:8:12
    |
 LL | struct Foo([*const u8; 1]);
    |            ^^^^^^^^^^^^^^
 
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/nested_bad_const_param_ty.rs:11:10
+  --> $DIR/nested_bad_const_param_ty.rs:10:10
    |
 LL | #[derive(ConstParamTy)]
    |          ^^^^^^^^^^^^
-...
+LL |
 LL | struct Foo2([*mut u8; 1]);
    |             ------------ this field does not implement `ConstParamTy_`
    |
 note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: ConstParamTy_`
-  --> $DIR/nested_bad_const_param_ty.rs:14:13
+  --> $DIR/nested_bad_const_param_ty.rs:12:13
    |
 LL | struct Foo2([*mut u8; 1]);
    |             ^^^^^^^^^^^^
 
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/nested_bad_const_param_ty.rs:16:10
+  --> $DIR/nested_bad_const_param_ty.rs:14:10
    |
 LL | #[derive(ConstParamTy)]
    |          ^^^^^^^^^^^^
-...
+LL |
 LL | struct Foo3([fn(); 1]);
    |             --------- this field does not implement `ConstParamTy_`
    |
 note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): ConstParamTy_`
-  --> $DIR/nested_bad_const_param_ty.rs:19:13
+  --> $DIR/nested_bad_const_param_ty.rs:16:13
    |
 LL | struct Foo3([fn(); 1]);
    |             ^^^^^^^^^
 
-error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/nested_bad_const_param_ty.rs:6:10
-   |
-LL | #[derive(ConstParamTy)]
-   |          ^^^^^^^^^^^^
-...
-LL | struct Foo([*const u8; 1]);
-   |            -------------- this field does not implement `ConstParamTy_`
-   |
-note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: UnsizedConstParamTy`
-  --> $DIR/nested_bad_const_param_ty.rs:9:12
-   |
-LL | struct Foo([*const u8; 1]);
-   |            ^^^^^^^^^^^^^^
-
-error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/nested_bad_const_param_ty.rs:11:10
-   |
-LL | #[derive(ConstParamTy)]
-   |          ^^^^^^^^^^^^
-...
-LL | struct Foo2([*mut u8; 1]);
-   |             ------------ this field does not implement `ConstParamTy_`
-   |
-note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: UnsizedConstParamTy`
-  --> $DIR/nested_bad_const_param_ty.rs:14:13
-   |
-LL | struct Foo2([*mut u8; 1]);
-   |             ^^^^^^^^^^^^
-
-error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/nested_bad_const_param_ty.rs:16:10
-   |
-LL | #[derive(ConstParamTy)]
-   |          ^^^^^^^^^^^^
-...
-LL | struct Foo3([fn(); 1]);
-   |             --------- this field does not implement `ConstParamTy_`
-   |
-note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): UnsizedConstParamTy`
-  --> $DIR/nested_bad_const_param_ty.rs:19:13
-   |
-LL | struct Foo3([fn(); 1]);
-   |             ^^^^^^^^^
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr
index b13f76eabad..72dfda50ea5 100644
--- a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr
+++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr
@@ -9,11 +9,13 @@ help: you might be missing a const parameter
 LL | impl<const bar: /* Type */> Wrapper<{ bar() }> {
    |     +++++++++++++++++++++++
 
-error[E0741]: using function pointers as const generic parameters is forbidden
+error: using function pointers as const generic parameters is forbidden
   --> $DIR/non_valtreeable_const_arg-2.rs:8:25
    |
 LL | struct Wrapper<const F: fn()>;
    |                         ^^^^
+   |
+   = note: the only supported types are integers, `bool`, and `char`
 
 error[E0599]: the function or associated item `call` exists for struct `Wrapper<function>`, but its trait bounds were not satisfied
   --> $DIR/non_valtreeable_const_arg-2.rs:17:26
@@ -35,5 +37,5 @@ note: the trait `Fn` must be implemented
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0425, E0599, E0741.
+Some errors have detailed explanations: E0425, E0599.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs
index a1ee1c4cdd5..937acf2e6bb 100644
--- a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs
@@ -1,11 +1,11 @@
 #![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::UnsizedConstParamTy;
+use std::marker::ConstParamTy_;
 
 struct Foo;
 
-impl UnsizedConstParamTy for &'static Foo {}
+impl ConstParamTy_ for &'static Foo {}
 //~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
 
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr
index 5ca8e6c7516..b977cf5d44e 100644
--- a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr
@@ -1,8 +1,8 @@
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/reference_pointee_is_const_param-1.rs:8:30
+  --> $DIR/reference_pointee_is_const_param-1.rs:8:24
    |
-LL | impl UnsizedConstParamTy for &'static Foo {}
-   |                              ^^^^^^^^^^^^ this field does not implement `ConstParamTy_`
+LL | impl ConstParamTy_ for &'static Foo {}
+   |                        ^^^^^^^^^^^^ this field does not implement `ConstParamTy_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs
index ac1b522f469..605fed26c9c 100644
--- a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs
@@ -3,12 +3,12 @@
 
 // Regression test for #119299
 
-use std::marker::UnsizedConstParamTy;
+use std::marker::ConstParamTy_;
 
 #[derive(Eq, PartialEq)]
 struct ConstStrU(*const u8, usize);
 
-impl UnsizedConstParamTy for &'static ConstStrU {}
+impl ConstParamTy_ for &'static ConstStrU {}
 //~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
 
 impl ConstStrU {
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr
index 5e5f6cc642d..0fe92f253a0 100644
--- a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr
@@ -1,8 +1,8 @@
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/reference_pointee_is_const_param-2.rs:11:30
+  --> $DIR/reference_pointee_is_const_param-2.rs:11:24
    |
-LL | impl UnsizedConstParamTy for &'static ConstStrU {}
-   |                              ^^^^^^^^^^^^^^^^^^ this field does not implement `ConstParamTy_`
+LL | impl ConstParamTy_ for &'static ConstStrU {}
+   |                        ^^^^^^^^^^^^^^^^^^ this field does not implement `ConstParamTy_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs
index b0934508399..0fe86adb291 100644
--- a/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs
+++ b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs
@@ -1,11 +1,11 @@
 #![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::UnsizedConstParamTy;
+use std::marker::ConstParamTy_;
 
 trait Trait {}
 
-impl UnsizedConstParamTy for dyn Trait {}
+impl ConstParamTy_ for dyn Trait {}
 //~^ ERROR: the trait `ConstParamTy` may not be implemented for this type
 
 fn foo<const N: dyn Trait>() {}
diff --git a/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr
index 9933ba6e335..67c6314e297 100644
--- a/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr
+++ b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr
@@ -1,8 +1,8 @@
 error: the trait `ConstParamTy` may not be implemented for this type
-  --> $DIR/trait_objects_as_a_const_generic.rs:8:30
+  --> $DIR/trait_objects_as_a_const_generic.rs:8:24
    |
-LL | impl UnsizedConstParamTy for dyn Trait {}
-   |                              ^^^^^^^^^ type is not a structure or enumeration
+LL | impl ConstParamTy_ for dyn Trait {}
+   |                        ^^^^^^^^^ type is not a structure or enumeration
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs
index f6e5bd6e355..5db031cb900 100644
--- a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs
+++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs
@@ -14,7 +14,10 @@ struct A([u8]);
 struct B(&'static [u8]);
 
 #[derive(ConstParamTy, Eq, PartialEq)]
-//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
 struct C(unsized_const_param::Foo);
 
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
+struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
+
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr
index 3089b30bd76..a5ae5c726da 100644
--- a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr
+++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr
@@ -6,6 +6,12 @@ LL | #[derive(ConstParamTy, Eq, PartialEq)]
 LL |
 LL | struct A([u8]);
    |          ---- this field does not implement `ConstParamTy_`
+   |
+note: the `ConstParamTy_` impl for `[u8]` requires that `unstable feature: `unsized_const_params``
+  --> $DIR/unsized_field-1.rs:10:10
+   |
+LL | struct A([u8]);
+   |          ^^^^
 
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
   --> $DIR/unsized_field-1.rs:12:10
@@ -15,15 +21,27 @@ LL | #[derive(ConstParamTy, Eq, PartialEq)]
 LL |
 LL | struct B(&'static [u8]);
    |          ------------- this field does not implement `ConstParamTy_`
+   |
+note: the `ConstParamTy_` impl for `&'static [u8]` requires that `unstable feature: `unsized_const_params``
+  --> $DIR/unsized_field-1.rs:14:10
+   |
+LL | struct B(&'static [u8]);
+   |          ^^^^^^^^^^^^^
 
 error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/unsized_field-1.rs:16:10
+  --> $DIR/unsized_field-1.rs:19:10
    |
-LL | #[derive(ConstParamTy, Eq, PartialEq)]
-   |          ^^^^^^^^^^^^
+LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
-LL | struct C(unsized_const_param::Foo);
-   |          ------------------------ this field does not implement `ConstParamTy_`
+LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
+   |          ---------------------------------------------------------- this field does not implement `ConstParamTy_`
+   |
+note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requires that `unstable feature: `unsized_const_params``
+  --> $DIR/unsized_field-1.rs:21:10
+   |
+LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-2.rs b/tests/ui/const-generics/adt_const_params/unsized_field-2.rs
deleted file mode 100644
index e4a3a481b4e..00000000000
--- a/tests/ui/const-generics/adt_const_params/unsized_field-2.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ aux-build:unsized_const_param.rs
-#![feature(adt_const_params, unsized_const_params)]
-//~^ WARN: the feature `unsized_const_params` is incomplete
-
-extern crate unsized_const_param;
-
-#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
-//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
-struct A(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
-
-#[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
-struct B(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
-
-fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr
deleted file mode 100644
index cef70ca0463..00000000000
--- a/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unsized_field-2.rs:2:30
-   |
-LL | #![feature(adt_const_params, unsized_const_params)]
-   |                              ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/unsized_field-2.rs:7:10
-   |
-LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | struct A(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
-   |          ---------------------------------------------------------- this field does not implement `ConstParamTy_`
-   |
-note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requires that `&'static [u8]: ConstParamTy_`
-  --> $DIR/unsized_field-2.rs:9:10
-   |
-LL | struct A(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs
index 311f507d3c7..500e8e22b0e 100644
--- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs
+++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs
@@ -7,7 +7,6 @@ use std::marker::ConstParamTy;
 
 #[derive(Debug, PartialEq, Eq, ConstParamTy)]
 //~^ ERROR the trait `ConstParamTy_`
-//~| ERROR the trait `ConstParamTy_`
 struct Foo {
     nested: &'static Bar<dyn std::fmt::Debug>,
     //~^ ERROR the size for values
diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
index 992a27c1c0e..d4aeb91999c 100644
--- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
+++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
@@ -1,17 +1,17 @@
 error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:13
    |
 LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
 note: required by an implicit `Sized` bound in `Bar`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:12
    |
 LL | struct Bar<T>(T);
    |            ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
 help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:12
    |
 LL | struct Bar<T>(T);
    |            ^  - ...if indirection were used here: `Box<T>`
@@ -26,34 +26,25 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
 ...
 LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |     ----------------------------------------- this field does not implement `ConstParamTy_`
-
-error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32
    |
-LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
-   |                                ^^^^^^^^^^^^
-...
-LL |     nested: &'static Bar<dyn std::fmt::Debug>,
-   |     ----------------------------------------- this field does not implement `ConstParamTy_`
-   |
-note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Eq`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): ConstParamTy_`
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:13
    |
 LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Sized`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Eq`
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:13
    |
 LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): UnsizedConstParamTy`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Sized`
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:13
    |
 LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:5
    |
 LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
    |          ----- in this derive macro expansion
@@ -64,7 +55,7 @@ LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
    = help: the trait `Debug` is implemented for `Bar<T>`
 note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:10
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10
    |
 LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
    |          ^^^^^
@@ -75,7 +66,7 @@ LL | struct Bar<T>(T);
    = note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug`
 
 error[E0369]: binary operation `==` cannot be applied to type `&Bar<dyn Debug>`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:5
    |
 LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
    |                 --------- in this derive macro expansion
@@ -84,7 +75,7 @@ LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `dyn Debug: Eq` is not satisfied
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:5
    |
 LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
    |                            -- in this derive macro expansion
@@ -94,7 +85,7 @@ LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |
    = help: the trait `Eq` is implemented for `Bar<T>`
 note: required for `Bar<dyn Debug>` to implement `Eq`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:28
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28
    |
 LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
    |                            ^^ unsatisfied trait bound introduced in this `derive` macro
@@ -104,7 +95,7 @@ note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:11:5
    |
 LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
    |                            -- in this derive macro expansion
@@ -114,12 +105,12 @@ LL |     nested: &'static Bar<dyn std::fmt::Debug>,
    |
    = help: the trait `Sized` is not implemented for `dyn Debug`
 note: required by an implicit `Sized` bound in `Bar`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:12
    |
 LL | struct Bar<T>(T);
    |            ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
 help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:12
    |
 LL | struct Bar<T>(T);
    |            ^  - ...if indirection were used here: `Box<T>`
@@ -127,26 +118,26 @@ LL | struct Bar<T>(T);
    |            this could be changed to `T: ?Sized`...
 
 error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:26:33
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:25:33
    |
 LL |     let x: Test<{ Foo { nested: &Bar(4) } }> = Test;
    |                                 ^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
 note: required by an implicit `Sized` bound in `Bar`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:12
    |
 LL | struct Bar<T>(T);
    |            ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
 help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
-  --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+  --> $DIR/unsizing-wfcheck-issue-126272.rs:20:12
    |
 LL | struct Bar<T>(T);
    |            ^  - ...if indirection were used here: `Box<T>`
    |            |
    |            this could be changed to `T: ?Sized`...
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0204, E0277, E0369.
 For more information about an error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/const-param-with-additional-obligations.rs b/tests/ui/const-generics/const-param-with-additional-obligations.rs
index 98097e86c7d..5110f95d5bf 100644
--- a/tests/ui/const-generics/const-param-with-additional-obligations.rs
+++ b/tests/ui/const-generics/const-param-with-additional-obligations.rs
@@ -1,14 +1,14 @@
 #![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::UnsizedConstParamTy;
+use std::marker::ConstParamTy_;
 
 #[derive(Eq, PartialEq)]
 struct Foo<T>(T);
 
 trait Other {}
 
-impl<T> UnsizedConstParamTy for Foo<T> where T: Other + UnsizedConstParamTy {}
+impl<T> ConstParamTy_ for Foo<T> where T: Other + ConstParamTy_ {}
 
 fn foo<const N: Foo<u8>>() {}
 //~^ ERROR `Foo<u8>` must implement `ConstParamTy` to be used as the type of a const generic parameter
diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs b/tests/ui/const-generics/generic_arg_infer/paren_infer.rs
index 9d7df8016cb..869683b7056 100644
--- a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs
+++ b/tests/ui/const-generics/generic_arg_infer/paren_infer.rs
@@ -1,4 +1,5 @@
 //@ check-pass
+//@ reference: items.generics.const.inferred
 
 struct Foo<const N: usize>;
 
diff --git a/tests/ui/const-generics/generic_const_parameter_types/no_const_param_ty_bound.stderr b/tests/ui/const-generics/generic_const_parameter_types/no_const_param_ty_bound.stderr
index 4ea323f4a5c..1eacc28b262 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/no_const_param_ty_bound.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/no_const_param_ty_bound.stderr
@@ -4,7 +4,7 @@ error[E0741]: `[T; N]` can't be used as a const parameter type
 LL | struct UsesType<T, const N: usize, const M: [T; N]>(PhantomData<T>);
    |                                             ^^^^^^
    |
-   = note: `T` must implement `UnsizedConstParamTy`, but it does not
+   = note: `T` must implement `ConstParamTy_`, but it does not
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/issue-66451.rs b/tests/ui/const-generics/issue-66451.rs
index 0b8693e0e67..9ce7658586a 100644
--- a/tests/ui/const-generics/issue-66451.rs
+++ b/tests/ui/const-generics/issue-66451.rs
@@ -1,15 +1,15 @@
 #![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::UnsizedConstParamTy;
+use std::marker::ConstParamTy;
 
-#[derive(Debug, PartialEq, Eq, UnsizedConstParamTy)]
+#[derive(Debug, PartialEq, Eq, ConstParamTy)]
 struct Foo {
     value: i32,
     nested: &'static Bar<i32>,
 }
 
-#[derive(Debug, PartialEq, Eq, UnsizedConstParamTy)]
+#[derive(Debug, PartialEq, Eq, ConstParamTy)]
 struct Bar<T>(T);
 
 struct Test<const F: Foo>;
diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
index 8ea96428deb..1301ca92f01 100644
--- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
+++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
@@ -4,7 +4,7 @@ error[E0741]: `&'static (dyn A + 'static)` can't be used as a const parameter ty
 LL | fn test<const T: &'static dyn A>() {
    |                  ^^^^^^^^^^^^^^
    |
-   = note: `(dyn A + 'static)` must implement `UnsizedConstParamTy`, but it does not
+   = note: `(dyn A + 'static)` must implement `ConstParamTy_`, but it does not
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr b/tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr
index bcb2bd255da..d970b12df6a 100644
--- a/tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr
+++ b/tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr
@@ -1,14 +1,22 @@
-error[E0741]: `&'static str` can't be used as a const parameter type
-  --> $DIR/slice-const-param-mismatch.rs:8:29
+error[E0658]: use of unstable library feature `unsized_const_params`
+  --> $DIR/slice-const-param-mismatch.rs:8:20
    |
 LL | struct ConstString<const T: &'static str>;
-   |                             ^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unsized_const_params)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required for `&'static str` to implement `ConstParamTy_`
 
-error[E0741]: `&'static [u8]` can't be used as a const parameter type
-  --> $DIR/slice-const-param-mismatch.rs:11:28
+error[E0658]: use of unstable library feature `unsized_const_params`
+  --> $DIR/slice-const-param-mismatch.rs:11:19
    |
 LL | struct ConstBytes<const T: &'static [u8]>;
-   |                            ^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unsized_const_params)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required for `&'static [u8]` to implement `ConstParamTy_`
 
 error[E0308]: mismatched types
   --> $DIR/slice-const-param-mismatch.rs:17:35
@@ -45,5 +53,5 @@ LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0308, E0741.
+Some errors have detailed explanations: E0308, E0658.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/slice-const-param.rs b/tests/ui/const-generics/slice-const-param.rs
index 1c5088b5283..8b5e934149e 100644
--- a/tests/ui/const-generics/slice-const-param.rs
+++ b/tests/ui/const-generics/slice-const-param.rs
@@ -12,7 +12,7 @@ pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
 }
 
 // Also check the codepaths for custom DST
-#[derive(std::marker::UnsizedConstParamTy, PartialEq, Eq)]
+#[derive(std::marker::ConstParamTy, PartialEq, Eq)]
 struct MyStr(str);
 
 fn function_with_my_str<const S: &'static MyStr>() -> &'static MyStr {
diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr
index 7a936ced030..c2351c707d7 100644
--- a/tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr
+++ b/tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr
@@ -1,9 +1,13 @@
-error[E0741]: `&'static ()` can't be used as a const parameter type
-  --> $DIR/transmute-const-param-static-reference.rs:9:23
+error[E0658]: use of unstable library feature `unsized_const_params`
+  --> $DIR/transmute-const-param-static-reference.rs:9:14
    |
 LL | struct Const<const P: &'static ()>;
-   |                       ^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unsized_const_params)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required for `&'static ()` to implement `ConstParamTy_`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0741`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.rs b/tests/ui/const-generics/transmute-const-param-static-reference.rs
index 0b47fd31eaf..bf164bdadb0 100644
--- a/tests/ui/const-generics/transmute-const-param-static-reference.rs
+++ b/tests/ui/const-generics/transmute-const-param-static-reference.rs
@@ -8,7 +8,7 @@
 
 struct Const<const P: &'static ()>;
 //[min]~^ ERROR `&'static ()` is forbidden as the type of a const generic parameter
-//[adt_const_params]~^^ ERROR `&'static ()` can't be used as a const parameter type
+//[adt_const_params]~^^ ERROR use of unstable library feature `unsized_const_params`
 
 fn main() {
     const A: &'static () = unsafe { std::mem::transmute(10 as *const ()) };
diff --git a/tests/ui/const-generics/unsized_const_params/symbol_mangling_v0_str.rs b/tests/ui/const-generics/unsized_const_params/symbol_mangling_v0_str.rs
index 359126f1251..429c401af1f 100644
--- a/tests/ui/const-generics/unsized_const_params/symbol_mangling_v0_str.rs
+++ b/tests/ui/const-generics/unsized_const_params/symbol_mangling_v0_str.rs
@@ -1,13 +1,13 @@
 //@ check-pass
 //@ compile-flags: -Csymbol-mangling-version=v0
 #![allow(incomplete_features)]
-#![feature(unsized_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 // Regression test for #116303
 
 #[derive(PartialEq, Eq)]
 struct MyStr(str);
-impl std::marker::UnsizedConstParamTy for MyStr {}
+impl std::marker::ConstParamTy_ for MyStr {}
 
 fn function_with_my_str<const S: &'static MyStr>() -> &'static MyStr {
     S
diff --git a/tests/ui/consts/const_refs_to_static_fail.stderr b/tests/ui/consts/const_refs_to_static_fail.stderr
index c567b3e0ce1..2bb6d2b8fef 100644
--- a/tests/ui/consts/const_refs_to_static_fail.stderr
+++ b/tests/ui/consts/const_refs_to_static_fail.stderr
@@ -16,7 +16,7 @@ error: constant BAD_PATTERN cannot be used as pattern
 LL |         BAD_PATTERN => {},
    |         ^^^^^^^^^^^
    |
-   = note: constants that reference mutable or external memory cannot be used as pattern
+   = note: constants that reference mutable or external memory cannot be used as patterns
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
index f9088c318a6..226a9de285d 100644
--- a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
+++ b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
@@ -15,7 +15,7 @@ error: constant extern_::C cannot be used as pattern
 LL |         C => {}
    |         ^
    |
-   = note: constants that reference mutable or external memory cannot be used as pattern
+   = note: constants that reference mutable or external memory cannot be used as patterns
 
 error: constant mutable::C cannot be used as pattern
   --> $DIR/const_refs_to_static_fail_invalid.rs:42:9
@@ -23,7 +23,7 @@ error: constant mutable::C cannot be used as pattern
 LL |         C => {}
    |         ^
    |
-   = note: constants that reference mutable or external memory cannot be used as pattern
+   = note: constants that reference mutable or external memory cannot be used as patterns
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr
index 6b70a211a72..5b8797c5116 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr
@@ -22,7 +22,7 @@ error: constant REF_INTERIOR_MUT cannot be used as pattern
 LL |         REF_INTERIOR_MUT => {},
    |         ^^^^^^^^^^^^^^^^
    |
-   = note: constants that reference mutable or external memory cannot be used as pattern
+   = note: constants that reference mutable or external memory cannot be used as patterns
 
 warning: skipping const checks
    |
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
index d753506cc94..c2b730375f2 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
@@ -10,7 +10,7 @@ error: constant SLICE_MUT cannot be used as pattern
 LL |         SLICE_MUT => true,
    |         ^^^^^^^^^
    |
-   = note: constants that reference mutable or external memory cannot be used as pattern
+   = note: constants that reference mutable or external memory cannot be used as patterns
 
 error: constant U8_MUT cannot be used as pattern
   --> $DIR/const_refers_to_static_cross_crate.rs:44:9
@@ -18,7 +18,7 @@ error: constant U8_MUT cannot be used as pattern
 LL |         U8_MUT => true,
    |         ^^^^^^
    |
-   = note: constants that reference mutable or external memory cannot be used as pattern
+   = note: constants that reference mutable or external memory cannot be used as patterns
 
 error: constant U8_MUT2 cannot be used as pattern
   --> $DIR/const_refers_to_static_cross_crate.rs:53:9
@@ -26,7 +26,7 @@ error: constant U8_MUT2 cannot be used as pattern
 LL |         U8_MUT2 => true,
    |         ^^^^^^^
    |
-   = note: constants that reference mutable or external memory cannot be used as pattern
+   = note: constants that reference mutable or external memory cannot be used as patterns
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/dist/cranelift-x86_64-unknown-linux-gnu-dist.rs b/tests/ui/dist/cranelift-x86_64-unknown-linux-gnu-dist.rs
index 198f8d1bc10..6d12ab1e4cf 100644
--- a/tests/ui/dist/cranelift-x86_64-unknown-linux-gnu-dist.rs
+++ b/tests/ui/dist/cranelift-x86_64-unknown-linux-gnu-dist.rs
@@ -2,6 +2,7 @@
 // dist artifacts.
 
 //@ only-dist
+//@ only-nightly (cranelift is not stable yet)
 //@ only-x86_64-unknown-linux-gnu
 //@ compile-flags: -Z codegen-backend=cranelift
 //@ run-pass
diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.rs b/tests/ui/feature-gates/feature-gate-adt_const_params.rs
index 8a3bcf25963..7efa529c557 100644
--- a/tests/ui/feature-gates/feature-gate-adt_const_params.rs
+++ b/tests/ui/feature-gates/feature-gate-adt_const_params.rs
@@ -1,2 +1,6 @@
-struct Foo<const NAME: &'static str>; //~ ERROR `&'static str` is forbidden
+struct Bar(u8);
+
+struct Foo<const N: Bar>;
+//~^ ERROR: `Bar` is forbidden as the type of a const generic parameter
+
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr
index 18d514f8cb5..7ea91a8f4c2 100644
--- a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr
+++ b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr
@@ -1,18 +1,14 @@
-error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/feature-gate-adt_const_params.rs:1:24
+error: `Bar` is forbidden as the type of a const generic parameter
+  --> $DIR/feature-gate-adt_const_params.rs:3:21
    |
-LL | struct Foo<const NAME: &'static str>;
-   |                        ^^^^^^^^^^^^
+LL | struct Foo<const N: Bar>;
+   |                     ^^^
    |
    = note: the only supported types are integers, `bool`, and `char`
 help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
    |
 LL + #![feature(adt_const_params)]
    |
-help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
-   |
-LL + #![feature(unsized_const_params)]
-   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.rs b/tests/ui/layout/thaw-transmute-invalid-enum.rs
index a7c2e1a86de..20fc8d46359 100644
--- a/tests/ui/layout/thaw-transmute-invalid-enum.rs
+++ b/tests/ui/layout/thaw-transmute-invalid-enum.rs
@@ -9,6 +9,7 @@ mod assert {
     where
         Dst: TransmuteFrom<Src>,
         //~^ ERROR: use of unstable library feature `transmutability`
+        //~^^ ERROR: use of unstable library feature `transmutability`
     {
     }
 }
diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.stderr b/tests/ui/layout/thaw-transmute-invalid-enum.stderr
index d12fc4694e0..2b89159c263 100644
--- a/tests/ui/layout/thaw-transmute-invalid-enum.stderr
+++ b/tests/ui/layout/thaw-transmute-invalid-enum.stderr
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `Subset` in this scope
-  --> $DIR/thaw-transmute-invalid-enum.rs:34:41
+  --> $DIR/thaw-transmute-invalid-enum.rs:35:41
    |
 LL |     assert::is_transmutable::<Superset, Subset>();
    |                                         ^^^^^^ not found in this scope
@@ -10,7 +10,7 @@ LL | fn test<Subset>() {
    |        ++++++++
 
 error[E0517]: attribute should be applied to a struct or union
-  --> $DIR/thaw-transmute-invalid-enum.rs:21:11
+  --> $DIR/thaw-transmute-invalid-enum.rs:22:11
    |
 LL |   #[repr(C, packed(2))]
    |             ^^^^^^^^^
@@ -50,8 +50,19 @@ LL |         Dst: TransmuteFrom<Src>,
    = help: add `#![feature(transmutability)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
+error[E0658]: use of unstable library feature `transmutability`
+  --> $DIR/thaw-transmute-invalid-enum.rs:10:14
+   |
+LL |         Dst: TransmuteFrom<Src>,
+   |              ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(transmutability)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+note: required by a bound in `TransmuteFrom`
+  --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
+
 error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
-  --> $DIR/thaw-transmute-invalid-enum.rs:29:9
+  --> $DIR/thaw-transmute-invalid-enum.rs:30:9
    |
 LL |         a: Ox00,
    |         ^^^^^^^
@@ -62,7 +73,7 @@ help: wrap the field type in `ManuallyDrop<...>`
 LL |         a: std::mem::ManuallyDrop<Ox00>,
    |            +++++++++++++++++++++++    +
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0412, E0517, E0658, E0740.
 For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/lifetimes/issue-105507.fixed b/tests/ui/lifetimes/issue-105507.fixed
index 46d4f14a245..a3c4e5784b8 100644
--- a/tests/ui/lifetimes/issue-105507.fixed
+++ b/tests/ui/lifetimes/issue-105507.fixed
@@ -31,7 +31,7 @@ impl<T> ProjectedMyTrait for T
 
 fn require_trait<T: MyTrait>(_: T) {}
 
-fn foo<T : MyTrait + 'static + 'static, U : MyTrait + 'static + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
+fn foo<T : MyTrait + 'static, U : MyTrait + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
     //~^ HELP consider restricting the type parameter to the `'static` lifetime
     //~| HELP consider restricting the type parameter to the `'static` lifetime
     require_trait(wrap);
diff --git a/tests/ui/lint/unused_parens_follow_ident.fixed b/tests/ui/lint/unused_parens_follow_ident.fixed
new file mode 100644
index 00000000000..e61b287e5a6
--- /dev/null
+++ b/tests/ui/lint/unused_parens_follow_ident.fixed
@@ -0,0 +1,17 @@
+//@ run-rustfix
+
+#![deny(unused_parens)]
+
+macro_rules! wrap {
+    ($name:ident $arg:expr) => {
+        $name($arg);
+    };
+}
+
+fn main() {
+    wrap!(unary routine()); //~ ERROR unnecessary parentheses around function argument
+    wrap!(unary routine()); //~ ERROR unnecessary parentheses around function argument
+}
+
+fn unary(_: ()) {}
+fn routine() {}
diff --git a/tests/ui/lint/unused_parens_follow_ident.rs b/tests/ui/lint/unused_parens_follow_ident.rs
new file mode 100644
index 00000000000..32a163345b2
--- /dev/null
+++ b/tests/ui/lint/unused_parens_follow_ident.rs
@@ -0,0 +1,17 @@
+//@ run-rustfix
+
+#![deny(unused_parens)]
+
+macro_rules! wrap {
+    ($name:ident $arg:expr) => {
+        $name($arg);
+    };
+}
+
+fn main() {
+    wrap!(unary(routine())); //~ ERROR unnecessary parentheses around function argument
+    wrap!(unary (routine())); //~ ERROR unnecessary parentheses around function argument
+}
+
+fn unary(_: ()) {}
+fn routine() {}
diff --git a/tests/ui/lint/unused_parens_follow_ident.stderr b/tests/ui/lint/unused_parens_follow_ident.stderr
new file mode 100644
index 00000000000..ce7bb26778c
--- /dev/null
+++ b/tests/ui/lint/unused_parens_follow_ident.stderr
@@ -0,0 +1,31 @@
+error: unnecessary parentheses around function argument
+  --> $DIR/unused_parens_follow_ident.rs:12:16
+   |
+LL |     wrap!(unary(routine()));
+   |                ^         ^
+   |
+note: the lint level is defined here
+  --> $DIR/unused_parens_follow_ident.rs:3:9
+   |
+LL | #![deny(unused_parens)]
+   |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     wrap!(unary(routine()));
+LL +     wrap!(unary routine());
+   |
+
+error: unnecessary parentheses around function argument
+  --> $DIR/unused_parens_follow_ident.rs:13:17
+   |
+LL |     wrap!(unary (routine()));
+   |                 ^         ^
+   |
+help: remove these parentheses
+   |
+LL -     wrap!(unary (routine()));
+LL +     wrap!(unary routine());
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/expr-as-stmt.fixed b/tests/ui/parser/expr-as-stmt.fixed
index bfae55047ed..b3a491200ed 100644
--- a/tests/ui/parser/expr-as-stmt.fixed
+++ b/tests/ui/parser/expr-as-stmt.fixed
@@ -66,7 +66,7 @@ fn asteroids() -> impl FnOnce() -> bool {
 
 // https://github.com/rust-lang/rust/issues/105179
 fn r#match() -> i32 {
-    ((match () { () => 1 })) + match () { () => 1 } //~ ERROR expected expression, found `+`
+    (match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
     //~^ ERROR mismatched types
 }
 
@@ -82,7 +82,7 @@ fn matches() -> bool {
     (match () { _ => true }) && match () { _ => true }; //~ ERROR mismatched types
     //~^ ERROR expected `;`, found keyword `match`
     (match () { _ => true }) && true; //~ ERROR mismatched types
-    ((match () { _ => true })) && true //~ ERROR mismatched types
+    (match () { _ => true }) && true //~ ERROR mismatched types
     //~^ ERROR mismatched types
 }
 fn main() {}
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
index 99433f73320..8a2be310e0d 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
@@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone> {
 }
 
 #[derive(Debug, Copy, Clone)]
-pub struct AABB<K: Debug + std::marker::Copy + std::marker::Copy + std::marker::Copy + std::marker::Copy> {
+pub struct AABB<K: Debug + std::marker::Copy> {
     pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
     //~^ ERROR the trait bound `K: Copy` is not satisfied
     //~| ERROR the trait bound `K: Copy` is not satisfied
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
index 6da3e351ffb..74df1d7c7cf 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
@@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone>{
 }
 
 #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type
-pub struct AABB<K: Copy + Debug + std::fmt::Debug + std::fmt::Debug + std::fmt::Debug>{
+pub struct AABB<K: Copy + Debug + std::fmt::Debug>{
     pub loc: Vector2<K>, //~ ERROR `K` doesn't implement `Debug`
     //~^ ERROR `K` doesn't implement `Debug`
     pub size: Vector2<K> //~ ERROR `K` doesn't implement `Debug`
diff --git a/tests/ui/suggestions/trait-impl-bound-suggestions.fixed b/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
index 9d3168f5acd..49793b4b6f4 100644
--- a/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
+++ b/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
@@ -10,7 +10,7 @@ struct ConstrainedStruct<X: Copy> {
 }
 
 #[allow(dead_code)]
-trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy, X: std::marker::Copy {
+trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy {
     fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
         //~^ ERROR the trait bound `X: Copy` is not satisfied
         ConstrainedStruct { x }
@@ -20,7 +20,7 @@ trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::
 
 // Regression test for #120838
 #[allow(dead_code)]
-trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy, X: std::marker::Copy {
+trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy {
     fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
         //~^ ERROR the trait bound `X: Copy` is not satisfied
         ConstrainedStruct { x }
diff --git a/tests/ui/symbol-names/const-generics-structural-demangling.rs b/tests/ui/symbol-names/const-generics-structural-demangling.rs
index 06e3ce51fa6..0b4af61f991 100644
--- a/tests/ui/symbol-names/const-generics-structural-demangling.rs
+++ b/tests/ui/symbol-names/const-generics-structural-demangling.rs
@@ -6,7 +6,7 @@
 #![feature(adt_const_params, unsized_const_params, decl_macro, rustc_attrs)]
 #![allow(incomplete_features)]
 
-use std::marker::UnsizedConstParamTy;
+use std::marker::ConstParamTy;
 
 pub struct RefByte<const RB: &'static u8>;
 
@@ -42,7 +42,7 @@ pub struct TupleByteBool<const TBB: (u8, bool)>;
 //~| ERROR demangling-alt(<c::TupleByteBool<{(1, false)}>>)
 impl TupleByteBool<{ (1, false) }> {}
 
-#[derive(PartialEq, Eq, UnsizedConstParamTy)]
+#[derive(PartialEq, Eq, ConstParamTy)]
 pub enum MyOption<T> {
     Some(T),
     None,
@@ -66,7 +66,7 @@ impl OptionUsize<{ MyOption::None }> {}
 //~| ERROR demangling-alt(<c::OptionUsize<{c::MyOption::<usize>::Some(0)}>>)
 impl OptionUsize<{ MyOption::Some(0) }> {}
 
-#[derive(PartialEq, Eq, UnsizedConstParamTy)]
+#[derive(PartialEq, Eq, ConstParamTy)]
 pub struct Foo {
     s: &'static str,
     ch: char,
@@ -83,7 +83,7 @@ impl Foo_<{ Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] } }> {}
 // NOTE(eddyb) this tests specifically the use of disambiguators in field names,
 // using macros 2.0 hygiene to create a `struct` with conflicting field names.
 macro duplicate_field_name_test($x:ident) {
-    #[derive(PartialEq, Eq, UnsizedConstParamTy)]
+    #[derive(PartialEq, Eq, ConstParamTy)]
     pub struct Bar {
         $x: u8,
         x: u16,