about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--RELEASES.md126
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs31
-rw-r--r--compiler/rustc_ast_passes/messages.ftl4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs7
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/crate_level.rs40
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs18
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/prelude.rs2
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs5
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/interface.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/target_checking.rs15
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl11
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs39
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs22
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/util.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs1
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs16
-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_expand/messages.ftl29
-rw-r--r--compiler/rustc_expand/src/config.rs3
-rw-r--r--compiler/rustc_expand/src/errors.rs78
-rw-r--r--compiler/rustc_expand/src/expand.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs45
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs26
-rw-r--r--compiler/rustc_hir/src/intravisit.rs11
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs29
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2402
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs10
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs17
-rw-r--r--compiler/rustc_interface/messages.ftl3
-rw-r--r--compiler/rustc_interface/src/errors.rs17
-rw-r--r--compiler/rustc_interface/src/util.rs8
-rw-r--r--compiler/rustc_lint/messages.ftl73
-rw-r--r--compiler/rustc_lint/src/builtin.rs20
-rw-r--r--compiler/rustc_lint/src/early/diagnostics.rs84
-rw-r--r--compiler/rustc_lint/src/lints.rs166
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs35
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs51
-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_metadata/src/rmeta/decoder.rs13
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs38
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/parameterized.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs7
-rw-r--r--compiler/rustc_middle/messages.ftl2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs8
-rw-r--r--compiler/rustc_middle/src/query/erase.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs63
-rw-r--r--compiler/rustc_middle/src/ty/context.rs26
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs43
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs14
-rw-r--r--compiler/rustc_passes/messages.ftl2
-rw-r--r--compiler/rustc_passes/src/dead.rs44
-rw-r--r--compiler/rustc_passes/src/stability.rs7
-rw-r--r--compiler/rustc_public/src/ty.rs12
-rw-r--r--compiler/rustc_public/src/unstable/convert/stable/ty.rs20
-rw-r--r--compiler/rustc_resolve/messages.ftl24
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs6
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/errors.rs55
-rw-r--r--compiler/rustc_resolve/src/ident.rs3
-rw-r--r--compiler/rustc_resolve/src/imports.rs6
-rw-r--r--compiler/rustc_resolve/src/late.rs4
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs3
-rw-r--r--compiler/rustc_span/src/hygiene.rs30
-rw-r--r--compiler/rustc_span/src/lib.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs7
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs7
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs38
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs2
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs35
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs2
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs7
-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/ffi/va_list.rs29
-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/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/keyword_docs.rs102
-rw-r--r--library/std/src/lib.rs5
-rw-r--r--library/std/src/sync/nonpoison/condvar.rs9
-rw-r--r--library/std/src/sync/poison/condvar.rs9
-rw-r--r--library/std/src/sys/fs/unix.rs120
-rw-r--r--library/std/src/sys/pal/hermit/time.rs32
-rw-r--r--library/std/src/sys/pal/sgx/time.rs15
-rw-r--r--library/std/src/sys/pal/solid/time.rs9
-rw-r--r--library/std/src/sys/pal/uefi/time.rs27
-rw-r--r--library/std/src/sys/pal/unix/time.rs30
-rw-r--r--library/std/src/sys/pal/unsupported/time.rs15
-rw-r--r--library/std/src/sys/pal/wasip1/time.rs25
-rw-r--r--library/std/src/sys/pal/wasip2/time.rs25
-rw-r--r--library/std/src/sys/pal/windows/time.rs30
-rw-r--r--library/std/src/sys/pal/xous/time.rs15
-rw-r--r--library/std/src/time.rs30
-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/SUMMARY.md5
-rw-r--r--src/doc/rustc/src/check-cfg.md2
-rw-r--r--src/doc/rustc/src/platform-support.md10
-rw-r--r--src/doc/rustc/src/platform-support/aarch64-unknown-none.md78
-rw-r--r--src/doc/rustc/src/platform-support/arm-none-eabi.md6
-rw-r--r--src/doc/rustc/src/platform-support/armebv7r-none-eabi.md55
-rw-r--r--src/doc/rustc/src/platform-support/armv4t-none-eabi.md3
-rw-r--r--src/doc/rustc/src/platform-support/armv5te-none-eabi.md3
-rw-r--r--src/doc/rustc/src/platform-support/armv7a-none-eabi.md70
-rw-r--r--src/doc/rustc/src/platform-support/armv7r-none-eabi.md28
-rw-r--r--src/doc/rustc/src/platform-support/armv8r-none-eabihf.md21
-rw-r--r--src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md5
-rw-r--r--src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md5
-rw-r--r--src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md5
-rw-r--r--src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md5
-rw-r--r--src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md5
-rw-r--r--src/doc/rustc/src/target-tier-policy.md2
-rw-r--r--src/librustdoc/clean/mod.rs35
-rw-r--r--src/librustdoc/clean/types.rs33
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/min_ident_chars.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_trait_methods.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs32
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs4
-rw-r--r--src/tools/compiletest/src/directives.rs9
-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--src/tools/tidy/src/fluent_lowercase.rs64
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--src/version2
-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/cffi/c-variadic-inline.rs47
-rw-r--r--tests/codegen-llvm/rust-abi-arch-specific-adjustment.rs8
-rw-r--r--tests/ui/c-variadic/naked.rs40
-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_exprs/post-analysis-user-facing-param-env.rs1
-rw-r--r--tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr19
-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/explicit-tail-calls/c-variadic.rs14
-rw-r--r--tests/ui/explicit-tail-calls/c-variadic.stderr8
-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/linkage-attr/raw-dylib/windows/dlltool-failed.rs2
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr2
-rw-r--r--tests/ui/macros/issue-61053-duplicate-binder.stderr4
-rw-r--r--tests/ui/symbol-names/const-generics-structural-demangling.rs8
254 files changed, 3642 insertions, 2942 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/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_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index bb559bd8921..53351f91c46 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -5,7 +5,9 @@ use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{DefKind, PerNS, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
-use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, Target, find_attr};
+use rustc_hir::{
+    self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr,
+};
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
@@ -1117,20 +1119,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
         };
 
+        let span = self.lower_span(i.span);
         let item = hir::ImplItem {
             owner_id: hir_id.expect_owner(),
             ident: self.lower_ident(ident),
             generics,
+            impl_kind: if is_in_trait_impl {
+                ImplItemImplKind::Trait {
+                    defaultness,
+                    trait_item_def_id: self
+                        .resolver
+                        .get_partial_res(i.id)
+                        .and_then(|r| r.expect_full_res().opt_def_id())
+                        .ok_or_else(|| {
+                            self.dcx().span_delayed_bug(
+                                span,
+                                "could not resolve trait item being implemented",
+                            )
+                        }),
+                }
+            } else {
+                ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }
+            },
             kind,
-            vis_span: self.lower_span(i.vis.span),
-            span: self.lower_span(i.span),
-            defaultness,
+            span,
             has_delayed_lints: !self.delayed_lints.is_empty(),
-            trait_item_def_id: self
-                .resolver
-                .get_partial_res(i.id)
-                .map(|r| r.expect_full_res().opt_def_id())
-                .unwrap_or(None),
         };
         self.arena.alloc(item)
     }
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 8dcf3e3aa38..e5405a7ad91 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -216,6 +216,10 @@ ast_passes_match_arm_with_no_body =
     .suggestion = add a body after the pattern
 
 ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe
+    .suggestion = needs `unsafe` before the extern keyword
+
+ast_passes_missing_unsafe_on_extern_lint = extern blocks should be unsafe
+    .suggestion = needs `unsafe` before the extern keyword
 
 ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
     .help = consider using the `#[path]` attribute to specify filesystem path
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index a6ef89b553d..dc221c2fb1a 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1131,7 +1131,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                             MISSING_UNSAFE_ON_EXTERN,
                             item.id,
                             item.span,
-                            BuiltinLintDiag::MissingUnsafeOnExtern {
+                            errors::MissingUnsafeOnExternLint {
                                 suggestion: item.span.shrink_to_lo(),
                             },
                         );
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index ae805042c54..e09ca5b81c8 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -523,6 +523,13 @@ pub(crate) struct MissingUnsafeOnExtern {
     pub span: Span,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(ast_passes_missing_unsafe_on_extern_lint)]
+pub(crate) struct MissingUnsafeOnExternLint {
+    #[suggestion(code = "unsafe ", applicability = "machine-applicable")]
+    pub suggestion: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(ast_passes_fieldless_union)]
 pub(crate) struct FieldlessUnion {
diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
index 0b2c05482bf..4611de44459 100644
--- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
@@ -43,11 +43,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
-    const TYPE: AttributeType = AttributeType::CrateLevel;
-
-    // because it's a crate-level attribute, we already warn about it.
-    // Putting target limitations here would give duplicate warnings
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         let ArgParser::NameValue(n) = args else {
@@ -76,11 +72,7 @@ impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
-    const TYPE: AttributeType = AttributeType::CrateLevel;
-
-    // because it's a crate-level attribute, we already warn about it.
-    // Putting target limitations here would give duplicate warnings
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         let ArgParser::NameValue(nv) = args else {
@@ -103,11 +95,7 @@ impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
-    const TYPE: AttributeType = AttributeType::CrateLevel;
-
-    // because it's a crate-level attribute, we already warn about it.
-    // Putting target limitations here would give duplicate warnings
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         let ArgParser::NameValue(nv) = args else {
@@ -130,11 +118,7 @@ impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
-    const TYPE: AttributeType = AttributeType::CrateLevel;
-
-    // because it's a crate-level attribute, we already warn about it.
-    // Putting target limitations here would give duplicate warnings
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         let ArgParser::NameValue(nv) = args else {
@@ -157,11 +141,7 @@ impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
-    const TYPE: AttributeType = AttributeType::CrateLevel;
-
-    // because it's a crate-level attribute, we already warn about it.
-    // Putting target limitations here would give duplicate warnings
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         let ArgParser::NameValue(nv) = args else {
@@ -182,11 +162,8 @@ pub(crate) struct NoCoreParser;
 impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
     const PATH: &[Symbol] = &[sym::no_core];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
-    // because it's a crate-level attribute, we already warn about it.
-    // Putting target limitations here would give duplicate warnings
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
-    const TYPE: AttributeType = AttributeType::CrateLevel;
 }
 
 pub(crate) struct NoStdParser;
@@ -194,9 +171,6 @@ pub(crate) struct NoStdParser;
 impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
     const PATH: &[Symbol] = &[sym::no_std];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
-    // because it's a crate-level attribute, we already warn about it.
-    // Putting target limitations here would give duplicate warnings
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
-    const TYPE: AttributeType = AttributeType::CrateLevel;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 043bc925eac..4ed13d239b9 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -12,15 +12,11 @@
 //! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
 //! contents of attributes, if an attribute appear multiple times in a list
 //!
-//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
-//! at the crate root, consider setting the `TYPE` in the parser trait to
-//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
-//!
 //! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
 
 use std::marker::PhantomData;
 
-use rustc_feature::{AttributeTemplate, AttributeType, template};
+use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol};
 use thin_vec::ThinVec;
@@ -89,11 +85,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
     ///
     /// If an attribute has this symbol, the `accept` function will be called on it.
     const ATTRIBUTES: AcceptMapping<Self, S>;
-
     const ALLOWED_TARGETS: AllowedTargets;
 
-    const TYPE: AttributeType = AttributeType::Normal;
-
     /// The parser has gotten a chance to accept the attributes on an item,
     /// here it can produce an attribute.
     ///
@@ -135,8 +128,6 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
-    const TYPE: AttributeType = AttributeType::Normal;
-
     /// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
 }
@@ -183,8 +174,6 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
     )];
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
 
-    const TYPE: AttributeType = T::TYPE;
-
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         Some(self.1?.0)
     }
@@ -269,7 +258,6 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
     const PATH: &[Symbol];
     const ON_DUPLICATE: OnDuplicate<S>;
     const ALLOWED_TARGETS: AllowedTargets;
-    const TYPE: AttributeType = AttributeType::Normal;
 
     /// Create the [`AttributeKind`] given attribute's [`Span`].
     const CREATE: fn(Span) -> AttributeKind;
@@ -289,7 +277,6 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
     const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
     const TEMPLATE: AttributeTemplate = template!(Word);
-    const TYPE: AttributeType = T::TYPE;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         if let Err(span) = args.no_args() {
@@ -323,8 +310,6 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
-    const TYPE: AttributeType = AttributeType::Normal;
-
     /// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
     fn extend<'c>(
         cx: &'c mut AcceptContext<'_, '_, S>,
@@ -360,7 +345,6 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
             group.items.extend(T::extend(cx, args))
         })];
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
-    const TYPE: AttributeType = T::TYPE;
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         if let Some(first_span) = self.first_span {
diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
index 8f040ffb9d4..980366b5c37 100644
--- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
@@ -1,6 +1,6 @@
 // data structures
 #[doc(hidden)]
-pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template};
+pub(super) use rustc_feature::{AttributeTemplate, template};
 #[doc(hidden)]
 pub(super) use rustc_hir::attrs::AttributeKind;
 #[doc(hidden)]
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index fbd9a480fbb..c756bce96e2 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -1,7 +1,5 @@
 use std::mem;
 
-use rustc_feature::AttributeType;
-
 use super::prelude::*;
 use crate::attributes::{
     AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
@@ -155,8 +153,7 @@ pub(crate) struct CoherenceIsCoreParser;
 impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
     const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
-    const TYPE: AttributeType = AttributeType::CrateLevel;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
 }
 
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index b3ab1d3edd6..d7998048be5 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -6,7 +6,7 @@ use std::sync::LazyLock;
 use private::Sealed;
 use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
 use rustc_errors::{Diag, Diagnostic, Level};
-use rustc_feature::{AttributeTemplate, AttributeType};
+use rustc_feature::AttributeTemplate;
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
 use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
@@ -83,7 +83,6 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
     pub(super) template: AttributeTemplate,
     pub(super) accept_fn: AcceptFn<S>,
     pub(super) allowed_targets: AllowedTargets,
-    pub(super) attribute_type: AttributeType,
 }
 
 type AcceptFn<S> =
@@ -133,7 +132,6 @@ macro_rules! attribute_parsers {
                                 })
                             }),
                             allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
-                            attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
                         });
                     }
 
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs
index 0fe3c209421..8f2de4af14e 100644
--- a/compiler/rustc_attr_parsing/src/interface.rs
+++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -272,7 +272,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
 
                             (accept.accept_fn)(&mut cx, args);
                             if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
-                                Self::check_type(accept.attribute_type, target, &mut cx);
                                 Self::check_target(&accept.allowed_targets, target, &mut cx);
                             }
                         }
diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs
index edc496b460c..c52253699b5 100644
--- a/compiler/rustc_attr_parsing/src/target_checking.rs
+++ b/compiler/rustc_attr_parsing/src/target_checking.rs
@@ -2,7 +2,7 @@ use std::borrow::Cow;
 
 use rustc_ast::AttrStyle;
 use rustc_errors::DiagArgValue;
-use rustc_feature::{AttributeType, Features};
+use rustc_feature::Features;
 use rustc_hir::lints::AttributeLintKind;
 use rustc_hir::{MethodKind, Target};
 
@@ -14,6 +14,11 @@ use crate::session_diagnostics::InvalidTarget;
 pub(crate) enum AllowedTargets {
     AllowList(&'static [Policy]),
     AllowListWarnRest(&'static [Policy]),
+    /// Special, and not the same as `AllowList(&[Allow(Target::Crate)])`.
+    /// For crate-level attributes we emit a specific set of lints to warn
+    /// people about accidentally not using them on the crate.
+    /// Only use this for attributes that are *exclusively* valid at the crate level.
+    CrateLevel,
 }
 
 pub(crate) enum AllowedResult {
@@ -43,6 +48,7 @@ impl AllowedTargets {
                     AllowedResult::Warn
                 }
             }
+            AllowedTargets::CrateLevel => AllowedResult::Allowed,
         }
     }
 
@@ -50,6 +56,7 @@ impl AllowedTargets {
         match self {
             AllowedTargets::AllowList(list) => list,
             AllowedTargets::AllowListWarnRest(list) => list,
+            AllowedTargets::CrateLevel => ALL_TARGETS,
         }
         .iter()
         .filter_map(|target| match target {
@@ -74,6 +81,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
         target: Target,
         cx: &mut AcceptContext<'_, 'sess, S>,
     ) {
+        Self::check_type(matches!(allowed_targets, AllowedTargets::CrateLevel), target, cx);
+
         match allowed_targets.is_allowed(target) {
             AllowedResult::Allowed => {}
             AllowedResult::Warn => {
@@ -109,7 +118,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
     }
 
     pub(crate) fn check_type(
-        attribute_type: AttributeType,
+        crate_level: bool,
         target: Target,
         cx: &mut AcceptContext<'_, 'sess, S>,
     ) {
@@ -119,7 +128,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
             return;
         }
 
-        if attribute_type != AttributeType::CrateLevel {
+        if !crate_level {
             return;
         }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index ea264c8064a..6d69040c711 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -716,7 +716,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             return (false, false, None);
         };
 
-        let implemented_trait_item = self.infcx.tcx.associated_item(my_def).trait_item_def_id;
+        let implemented_trait_item = self.infcx.tcx.trait_item_of(my_def);
 
         (
             true,
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 358c0d3db46..7c1a5f44e16 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -64,6 +64,11 @@ builtin_macros_autodiff_ty_activity = {$act} can not be used for this type
 builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}`
 
 builtin_macros_autodiff_width = autodiff width must fit u32, but is {$width}
+
+builtin_macros_avoid_att_syntax = avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+
+builtin_macros_avoid_intel_syntax = avoid using `.intel_syntax`, Intel syntax is the default
+
 builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
     .label = not applicable here
     .label2 = not a `struct`, `enum` or `union`
@@ -138,6 +143,8 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
 builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
     .suggestion = remove the value
 
+builtin_macros_duplicate_macro_attribute = duplicated attribute
+
 builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
     .cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
     .custom = use `std::env::var({$var_expr})` to read the variable at run time
@@ -231,6 +238,8 @@ builtin_macros_derive_from_wrong_field_count = `#[derive(From)]` used on a struc
 
 builtin_macros_derive_from_usage_note = `#[derive(From)]` can only be used on structs with exactly one field
 
+builtin_macros_incomplete_include = include macro expected single expression in source
+
 builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
     .note = only one `#[default]` attribute is needed
     .label = `#[default]` used here
@@ -294,3 +303,5 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal
     .label = not a trait
     .str_lit = try using `#[derive({$sym})]`
     .other = for example, write `#[derive(Debug)]` for `Debug`
+
+builtin_macros_unnameable_test_items = cannot test inner items
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 86b8e1ff8db..ae62b5ea2a0 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -1,4 +1,3 @@
-use lint::BuiltinLintDiag;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{AsmMacro, token};
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@@ -352,7 +351,7 @@ fn expand_preparsed_asm(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".intel_syntax"),
                     ecx.current_expansion.lint_node_id,
-                    BuiltinLintDiag::AvoidUsingIntelSyntax,
+                    errors::AvoidIntelSyntax,
                 );
             }
             if template_str.contains(".att_syntax") {
@@ -360,7 +359,7 @@ fn expand_preparsed_asm(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".att_syntax"),
                     ecx.current_expansion.lint_node_id,
-                    BuiltinLintDiag::AvoidUsingAttSyntax,
+                    errors::AvoidAttSyntax,
                 );
             }
         }
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/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 54e8f750337..0993fdc5be4 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -3,9 +3,29 @@ use rustc_errors::{
     Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans,
     Subdiagnostic,
 };
-use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Ident, Span, Symbol};
 
+#[derive(LintDiagnostic)]
+#[diag(builtin_macros_avoid_intel_syntax)]
+pub(crate) struct AvoidIntelSyntax;
+
+#[derive(LintDiagnostic)]
+#[diag(builtin_macros_avoid_att_syntax)]
+pub(crate) struct AvoidAttSyntax;
+
+#[derive(LintDiagnostic)]
+#[diag(builtin_macros_incomplete_include)]
+pub(crate) struct IncompleteInclude;
+
+#[derive(LintDiagnostic)]
+#[diag(builtin_macros_unnameable_test_items)]
+pub(crate) struct UnnameableTestItems;
+
+#[derive(LintDiagnostic)]
+#[diag(builtin_macros_duplicate_macro_attribute)]
+pub(crate) struct DuplicateMacroAttribute;
+
 #[derive(Diagnostic)]
 #[diag(builtin_macros_requires_cfg_pattern)]
 pub(crate) struct RequiresCfgPattern {
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_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index 11b868f81a9..16adaab15c5 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -12,7 +12,6 @@ use rustc_expand::base::{
     DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path,
 };
 use rustc_expand::module::DirOwnership;
-use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::lexer::StripTokens;
 use rustc_parse::parser::ForceCollect;
 use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
@@ -159,7 +158,7 @@ pub(crate) fn expand_include<'cx>(
                     INCOMPLETE_INCLUDE,
                     p.token.span,
                     self.node_id,
-                    BuiltinLintDiag::IncompleteInclude,
+                    errors::IncompleteInclude,
                 );
             }
             Some(expr)
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index a9d91f77560..51089e5a1d3 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -11,7 +11,6 @@ use rustc_errors::DiagCtxtHandle;
 use rustc_expand::base::{ExtCtxt, ResolverExpand};
 use rustc_expand::expand::{AstFragment, ExpansionConfig};
 use rustc_feature::Features;
-use rustc_lint_defs::BuiltinLintDiag;
 use rustc_session::Session;
 use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
 use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
@@ -165,7 +164,7 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
                 UNNAMEABLE_TEST_ITEMS,
                 attr.span,
                 i.id,
-                BuiltinLintDiag::UnnameableTestItems,
+                errors::UnnameableTestItems,
             );
         }
     }
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index 3a4585d5be9..e26f31dce67 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -5,7 +5,6 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
 use rustc_expand::expand::AstFragment;
 use rustc_feature::AttributeTemplate;
-use rustc_lint_defs::BuiltinLintDiag;
 use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
 use rustc_parse::{exp, parser};
 use rustc_session::errors::report_lit_error;
@@ -49,7 +48,7 @@ pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable,
                 DUPLICATE_MACRO_ATTRIBUTES,
                 attr.span,
                 ecx.current_expansion.lint_node_id,
-                BuiltinLintDiag::DuplicateMacroAttribute,
+                errors::DuplicateMacroAttribute,
             );
         }
     }
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/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index dd688b8b345..1dd65d38a2b 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -31,7 +31,7 @@ codegen_ssa_cpu_required = target requires explicitly specifying a cpu with `-C
 codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
 
 codegen_ssa_dlltool_fail_import_library =
-    Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
+    dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
     {$stdout}
     {$stderr}
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 008340e614d..dc500c363f4 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -562,15 +562,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
     codegen_fn_attrs
 }
 
-/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype.
-fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
-    let impl_item = tcx.opt_associated_item(def_id)?;
-    match impl_item.container {
-        ty::AssocItemContainer::Impl => impl_item.trait_item_def_id,
-        _ => None,
-    }
-}
-
 fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
     // Backtrack to the crate root.
     let mut disabled = match tcx.opt_local_parent(did) {
@@ -600,14 +591,15 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
 /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
 /// applied to the method prototype.
 fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false };
-    tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
+    tcx.trait_item_of(def_id).is_some_and(|id| {
+        tcx.codegen_fn_attrs(id).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
+    })
 }
 
 /// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
 /// attribute on the method prototype (if any).
 fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
-    tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment
+    tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment
 }
 
 /// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)]
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_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 61ba716d082..47c00bff5c9 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -3,6 +3,8 @@ expand_attributes_on_expressions_experimental =
     .help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//`
     .help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`
 
+expand_cfg_attr_no_attributes = `#[cfg_attr]` does not expand to any attributes
+
 expand_collapse_debuginfo_illegal =
     illegal value for attribute #[collapse_debuginfo(no|external|yes)]
 
@@ -78,6 +80,10 @@ expand_macro_body_stability =
     .label = invalid body stability attribute
     .label2 = body stability attribute affects this macro
 
+expand_macro_call_unused_doc_comment = unused doc comment
+    .label = rustdoc does not generate documentation for macro invocations
+    .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+
 expand_macro_const_stability =
     macros cannot have const stability attributes
     .label = invalid const stability attribute
@@ -89,6 +95,13 @@ expand_malformed_feature_attribute =
     malformed `feature` attribute input
     .expected = expected just one word
 
+expand_metavar_still_repeating = variable `{$ident}` is still repeating at this depth
+    .label = expected repetition
+
+expand_metavariable_wrong_operator = meta-variable repeats with different Kleene operator
+    .binder_label = expected repetition
+    .occurrence_label = conflicting repetition
+
 expand_meta_var_dif_seq_matchers = {$msg}
 
 expand_missing_fragment_specifier = missing fragment specifier
@@ -147,6 +160,9 @@ expand_mve_unrecognized_var =
 expand_non_inline_modules_in_proc_macro_input_are_unstable =
     non-inline modules in proc macro input are unstable
 
+expand_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+    .suggestion = use pat_param to preserve semantics
+
 expand_proc_macro_back_compat = using an old version of `{$crate_name}`
     .note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
 
@@ -176,11 +192,18 @@ expand_resolve_relative_path =
 
 expand_trace_macro = trace_macro
 
+expand_trailing_semi_macro = trailing semicolon in macro used in expression position
+    .note1 = macro invocations at the end of a block are treated as expressions
+    .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
+
+expand_unknown_macro_variable = unknown macro variable `{$name}`
+
+expand_unused_builtin_attribute = unused attribute `{$attr_name}`
+    .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`
+    .suggestion = remove the attribute
+
 expand_unsupported_key_value =
     key-value macro attributes are not supported
 
-expand_var_still_repeating =
-    variable `{$ident}` is still repeating at this depth
-
 expand_wrong_fragment_kind =
     non-{$kind} macro in {$kind} position: {$name}
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 15419ab7423..2925e337071 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -21,7 +21,6 @@ use rustc_feature::{
     ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, EnabledLibFeature, Features,
     REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
 };
-use rustc_lint_defs::BuiltinLintDiag;
 use rustc_session::Session;
 use rustc_session::parse::feature_err;
 use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
@@ -315,7 +314,7 @@ impl<'a> StripUnconfigured<'a> {
                 rustc_lint_defs::builtin::UNUSED_ATTRIBUTES,
                 cfg_attr.span,
                 ast::CRATE_NODE_ID,
-                BuiltinLintDiag::CfgAttrNoAttributes,
+                crate::errors::CfgAttrNoAttributes,
             );
         }
 
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 6eb5cd65846..c37c2d88d9c 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -3,9 +3,13 @@ use std::borrow::Cow;
 use rustc_ast::ast;
 use rustc_errors::codes::*;
 use rustc_hir::limit::Limit;
-use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol};
 
+#[derive(LintDiagnostic)]
+#[diag(expand_cfg_attr_no_attributes)]
+pub(crate) struct CfgAttrNoAttributes;
+
 #[derive(Diagnostic)]
 #[diag(expand_expr_repeat_no_syntax_vars)]
 pub(crate) struct NoSyntaxVarsExprRepeat {
@@ -28,13 +32,30 @@ pub(crate) struct CountRepetitionMisplaced {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_var_still_repeating)]
-pub(crate) struct VarStillRepeating {
+#[diag(expand_metavar_still_repeating)]
+pub(crate) struct MacroVarStillRepeating {
     #[primary_span]
     pub span: Span,
     pub ident: MacroRulesNormalizedIdent,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(expand_metavar_still_repeating)]
+pub(crate) struct MetaVarStillRepeatingLint {
+    #[label]
+    pub label: Span,
+    pub ident: MacroRulesNormalizedIdent,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(expand_metavariable_wrong_operator)]
+pub(crate) struct MetaVariableWrongOperator {
+    #[label(expand_binder_label)]
+    pub binder: Span,
+    #[label(expand_occurrence_label)]
+    pub occurrence: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(expand_meta_var_dif_seq_matchers)]
 pub(crate) struct MetaVarsDifSeqMatchers {
@@ -43,6 +64,12 @@ pub(crate) struct MetaVarsDifSeqMatchers {
     pub msg: String,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(expand_unknown_macro_variable)]
+pub(crate) struct UnknownMacroVariable {
+    pub name: MacroRulesNormalizedIdent,
+}
+
 #[derive(Diagnostic)]
 #[diag(expand_resolve_relative_path)]
 pub(crate) struct ResolveRelativePath {
@@ -345,6 +372,15 @@ pub(crate) struct DuplicateMatcherBinding {
     pub prev: Span,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(expand_duplicate_matcher_binding)]
+pub(crate) struct DuplicateMatcherBindingLint {
+    #[label]
+    pub span: Span,
+    #[label(expand_label2)]
+    pub prev: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(expand_missing_fragment_specifier)]
 #[note]
@@ -501,3 +537,39 @@ pub(crate) struct MacroArgsBadDelimSugg {
     #[suggestion_part(code = ")")]
     pub close: Span,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(expand_macro_call_unused_doc_comment)]
+#[help]
+pub(crate) struct MacroCallUnusedDocComment {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(expand_or_patterns_back_compat)]
+pub(crate) struct OrPatternsBackCompat {
+    #[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
+    pub span: Span,
+    pub suggestion: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(expand_trailing_semi_macro)]
+pub(crate) struct TrailingMacro {
+    #[note(expand_note1)]
+    #[note(expand_note2)]
+    pub is_trailing: bool,
+    pub name: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(expand_unused_builtin_attribute)]
+pub(crate) struct UnusedBuiltinAttribute {
+    #[note]
+    pub invoc_span: Span,
+    pub attr_name: Symbol,
+    pub macro_name: String,
+    #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
+    pub attr_span: Span,
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 38e057d2776..4c0e0bbfe26 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -25,7 +25,6 @@ use rustc_parse::parser::{
     token_descr,
 };
 use rustc_session::Session;
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
 use rustc_session::parse::feature_err;
 use rustc_span::hygiene::SyntaxContext;
@@ -2183,7 +2182,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                     UNUSED_DOC_COMMENTS,
                     current_span,
                     self.cx.current_expansion.lint_node_id,
-                    BuiltinLintDiag::UnusedDocComment(attr.span),
+                    crate::errors::MacroCallUnusedDocComment { span: attr.span },
                 );
             } else if rustc_attr_parsing::is_builtin_attr(attr)
                 && !AttributeParser::<Early>::is_parsed_attribute(&attr.path())
@@ -2196,7 +2195,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         UNUSED_ATTRIBUTES,
                         attr.span,
                         self.cx.current_expansion.lint_node_id,
-                        BuiltinLintDiag::UnusedBuiltinAttribute {
+                        crate::errors::UnusedBuiltinAttribute {
                             attr_name,
                             macro_name: pprust::path_to_string(&call.path),
                             invoc_span: call.path.span,
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index faeae1f494e..ebd6e887f7d 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -108,8 +108,7 @@
 use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::{DUMMY_NODE_ID, NodeId};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::MultiSpan;
-use rustc_lint_defs::BuiltinLintDiag;
+use rustc_errors::DecorateDiagCompat;
 use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
 use rustc_session::parse::ParseSess;
 use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw};
@@ -245,9 +244,12 @@ fn check_binders(
             // There are 3 possibilities:
             if let Some(prev_info) = binders.get(&name) {
                 // 1. The meta-variable is already bound in the current LHS: This is an error.
-                let mut span = MultiSpan::from_span(span);
-                span.push_span_label(prev_info.span, "previous declaration");
-                buffer_lint(psess, span, node_id, BuiltinLintDiag::DuplicateMatcherBinding);
+                buffer_lint(
+                    psess,
+                    span,
+                    node_id,
+                    errors::DuplicateMatcherBindingLint { span, prev: prev_info.span },
+                );
             } else if get_binder_info(macros, binders, name).is_none() {
                 // 2. The meta-variable is free: This is a binder.
                 binders.insert(name, BinderInfo { span, ops: ops.into() });
@@ -579,7 +581,7 @@ fn check_ops_is_prefix(
             return;
         }
     }
-    buffer_lint(psess, span.into(), node_id, BuiltinLintDiag::UnknownMacroVariable(name));
+    buffer_lint(psess, span, node_id, errors::UnknownMacroVariable { name });
 }
 
 /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@@ -604,29 +606,42 @@ fn ops_is_prefix(
     psess: &ParseSess,
     node_id: NodeId,
     span: Span,
-    name: MacroRulesNormalizedIdent,
+    ident: MacroRulesNormalizedIdent,
     binder_ops: &[KleeneToken],
     occurrence_ops: &[KleeneToken],
 ) {
     for (i, binder) in binder_ops.iter().enumerate() {
         if i >= occurrence_ops.len() {
-            let mut span = MultiSpan::from_span(span);
-            span.push_span_label(binder.span, "expected repetition");
-            buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableStillRepeating(name));
+            buffer_lint(
+                psess,
+                span,
+                node_id,
+                errors::MetaVarStillRepeatingLint { label: binder.span, ident },
+            );
             return;
         }
         let occurrence = &occurrence_ops[i];
         if occurrence.op != binder.op {
-            let mut span = MultiSpan::from_span(span);
-            span.push_span_label(binder.span, "expected repetition");
-            span.push_span_label(occurrence.span, "conflicting repetition");
-            buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableWrongOperator);
+            buffer_lint(
+                psess,
+                span,
+                node_id,
+                errors::MetaVariableWrongOperator {
+                    binder: binder.span,
+                    occurrence: occurrence.span,
+                },
+            );
             return;
         }
     }
 }
 
-fn buffer_lint(psess: &ParseSess, span: MultiSpan, node_id: NodeId, diag: BuiltinLintDiag) {
+fn buffer_lint(
+    psess: &ParseSess,
+    span: Span,
+    node_id: NodeId,
+    diag: impl Into<DecorateDiagCompat>,
+) {
     // Macros loaded from other crates have dummy node ids.
     if node_id != DUMMY_NODE_ID {
         psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, diag);
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 8b43f852b26..946265eba8b 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -17,7 +17,6 @@ use rustc_hir as hir;
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::MacroKinds;
 use rustc_hir::find_attr;
-use rustc_lint_defs::BuiltinLintDiag;
 use rustc_lint_defs::builtin::{
     RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
 };
@@ -90,7 +89,7 @@ impl<'a> ParserAnyMacro<'a> {
                     SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
                     parser.token.span,
                     lint_node_id,
-                    BuiltinLintDiag::TrailingMacro(is_trailing_mac, macro_ident),
+                    errors::TrailingMacro { is_trailing: is_trailing_mac, name: macro_ident },
                 );
             }
             parser.bump();
@@ -1425,7 +1424,7 @@ fn check_matcher_core<'tt>(
                             RUST_2021_INCOMPATIBLE_OR_PATTERNS,
                             span,
                             ast::CRATE_NODE_ID,
-                            BuiltinLintDiag::OrPatternsBackCompat(span, suggestion),
+                            errors::OrPatternsBackCompat { span, suggestion },
                         );
                     }
                     match is_in_follow(next_token, kind) {
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index ed8aa71d59d..6a3f1f62c91 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -17,8 +17,8 @@ use rustc_span::{
 use smallvec::{SmallVec, smallvec};
 
 use crate::errors::{
-    CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar,
-    NoSyntaxVarsExprRepeat, VarStillRepeating,
+    CountRepetitionMisplaced, MacroVarStillRepeating, MetaVarsDifSeqMatchers, MustRepeatOnce,
+    MveUnrecognizedVar, NoSyntaxVarsExprRepeat,
 };
 use crate::mbe::macro_parser::NamedMatch;
 use crate::mbe::macro_parser::NamedMatch::*;
@@ -483,7 +483,7 @@ fn transcribe_metavar<'tx>(
         }
         MatchedSeq(..) => {
             // We were unable to descend far enough. This is an error.
-            return Err(dcx.create_err(VarStillRepeating { span: sp, ident }));
+            return Err(dcx.create_err(MacroVarStillRepeating { span: sp, ident }));
         }
     };
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 75551fe4c19..493236718a8 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3220,12 +3220,21 @@ pub struct ImplItem<'hir> {
     pub owner_id: OwnerId,
     pub generics: &'hir Generics<'hir>,
     pub kind: ImplItemKind<'hir>,
-    pub defaultness: Defaultness,
+    pub impl_kind: ImplItemImplKind,
     pub span: Span,
-    pub vis_span: Span,
     pub has_delayed_lints: bool,
-    /// When we are in a trait impl, link to the trait-item's id.
-    pub trait_item_def_id: Option<DefId>,
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub enum ImplItemImplKind {
+    Inherent {
+        vis_span: Span,
+    },
+    Trait {
+        defaultness: Defaultness,
+        /// Item in the trait that this item implements
+        trait_item_def_id: Result<DefId, ErrorGuaranteed>,
+    },
 }
 
 impl<'hir> ImplItem<'hir> {
@@ -3239,6 +3248,13 @@ impl<'hir> ImplItem<'hir> {
         ImplItemId { owner_id: self.owner_id }
     }
 
+    pub fn vis_span(&self) -> Option<Span> {
+        match self.impl_kind {
+            ImplItemImplKind::Trait { .. } => None,
+            ImplItemImplKind::Inherent { vis_span, .. } => Some(vis_span),
+        }
+    }
+
     expect_methods_self_kind! {
         expect_const, (&'hir Ty<'hir>, BodyId), ImplItemKind::Const(ty, body), (ty, *body);
         expect_fn,    (&FnSig<'hir>, BodyId),   ImplItemKind::Fn(ty, body),    (ty, *body);
@@ -4985,7 +5001,7 @@ mod size_asserts {
     static_assert_size!(GenericBound<'_>, 64);
     static_assert_size!(Generics<'_>, 56);
     static_assert_size!(Impl<'_>, 40);
-    static_assert_size!(ImplItem<'_>, 96);
+    static_assert_size!(ImplItem<'_>, 88);
     static_assert_size!(ImplItemKind<'_>, 40);
     static_assert_size!(Item<'_>, 88);
     static_assert_size!(ItemKind<'_>, 64);
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 25a7ae239f3..eb682f32111 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -1257,18 +1257,21 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
         owner_id: _,
         ident,
         ref generics,
+        ref impl_kind,
         ref kind,
-        ref defaultness,
         span: _,
-        vis_span: _,
         has_delayed_lints: _,
-        trait_item_def_id: _,
     } = *impl_item;
 
     try_visit!(visitor.visit_ident(ident));
     try_visit!(visitor.visit_generics(generics));
-    try_visit!(visitor.visit_defaultness(defaultness));
     try_visit!(visitor.visit_id(impl_item.hir_id()));
+    match impl_kind {
+        ImplItemImplKind::Inherent { vis_span: _ } => {}
+        ImplItemImplKind::Trait { defaultness, trait_item_def_id: _ } => {
+            try_visit!(visitor.visit_defaultness(defaultness));
+        }
+    }
     match *kind {
         ImplItemKind::Const(ref ty, body) => {
             try_visit!(visitor.visit_ty_unambig(ty));
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/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 08b344638dd..886ebddc75c 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1009,8 +1009,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
             res = res.and(check_associated_item(tcx, def_id));
             let assoc_item = tcx.associated_item(def_id);
             match assoc_item.container {
-                ty::AssocItemContainer::Impl => {}
-                ty::AssocItemContainer::Trait => {
+                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
+                ty::AssocContainer::Trait => {
                     res = res.and(check_trait_item(tcx, def_id));
                 }
             }
@@ -1026,8 +1026,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
             res = res.and(check_associated_item(tcx, def_id));
             let assoc_item = tcx.associated_item(def_id);
             match assoc_item.container {
-                ty::AssocItemContainer::Impl => {}
-                ty::AssocItemContainer::Trait => {
+                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
+                ty::AssocContainer::Trait => {
                     res = res.and(check_trait_item(tcx, def_id));
                 }
             }
@@ -1043,8 +1043,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
 
             let assoc_item = tcx.associated_item(def_id);
             let has_type = match assoc_item.container {
-                ty::AssocItemContainer::Impl => true,
-                ty::AssocItemContainer::Trait => {
+                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
+                ty::AssocContainer::Trait => {
                     tcx.ensure_ok().explicit_item_bounds(def_id);
                     tcx.ensure_ok().explicit_item_self_bounds(def_id);
                     if tcx.is_conditionally_const(def_id) {
@@ -1177,12 +1177,9 @@ fn check_impl_items_against_trait<'tcx>(
 
     for &impl_item in impl_item_refs {
         let ty_impl_item = tcx.associated_item(impl_item);
-        let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
-            tcx.associated_item(trait_item_id)
-        } else {
-            // Checked in `associated_item`.
-            tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
-            continue;
+        let ty_trait_item = match ty_impl_item.expect_trait_impl() {
+            Ok(trait_item_id) => tcx.associated_item(trait_item_id),
+            Err(ErrorGuaranteed { .. }) => continue,
         };
 
         let res = tcx.ensure_ok().compare_impl_item(impl_item.expect_local());
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index e4827256193..946c4936bb6 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -37,7 +37,7 @@ pub(super) fn compare_impl_item(
     impl_item_def_id: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
     let impl_item = tcx.associated_item(impl_item_def_id);
-    let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap());
+    let trait_item = tcx.associated_item(impl_item.expect_trait_impl()?);
     let impl_trait_ref =
         tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
     debug!(?impl_trait_ref);
@@ -298,14 +298,9 @@ fn compare_method_predicate_entailment<'tcx>(
     // compatible with that of the trait method. We do this by
     // checking that `impl_fty <: trait_fty`.
     //
-    // FIXME. Unfortunately, this doesn't quite work right now because
-    // associated type normalization is not integrated into subtype
-    // checks. For the comparison to be valid, we need to
-    // normalize the associated types in the impl/trait methods
-    // first. However, because function types bind regions, just
-    // calling `FnCtxt::normalize` would have no effect on
-    // any associated types appearing in the fn arguments or return
-    // type.
+    // FIXME: We manually instantiate the trait method here as we need
+    // to manually compute its implied bounds. Otherwise this could just
+    // be `ocx.sub(impl_sig, trait_sig)`.
 
     let mut wf_tys = FxIndexSet::default();
 
@@ -446,7 +441,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     impl_m_def_id: LocalDefId,
 ) -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed> {
     let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());
-    let trait_m = tcx.associated_item(impl_m.trait_item_def_id.unwrap());
+    let trait_m = tcx.associated_item(impl_m.expect_trait_impl()?);
     let impl_trait_ref =
         tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity();
     // First, check a few of the same things as `compare_impl_method`,
@@ -1449,8 +1444,10 @@ fn compare_self_type<'tcx>(
 
     let self_string = |method: ty::AssocItem| {
         let untransformed_self_ty = match method.container {
-            ty::AssocItemContainer::Impl => impl_trait_ref.self_ty(),
-            ty::AssocItemContainer::Trait => tcx.types.self_param,
+            ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
+                impl_trait_ref.self_ty()
+            }
+            ty::AssocContainer::Trait => tcx.types.self_param,
         };
         let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
         let (infcx, param_env) = tcx
@@ -2458,8 +2455,12 @@ fn param_env_with_gat_bounds<'tcx>(
 
     for impl_ty in impl_tys_to_install {
         let trait_ty = match impl_ty.container {
-            ty::AssocItemContainer::Trait => impl_ty,
-            ty::AssocItemContainer::Impl => tcx.associated_item(impl_ty.trait_item_def_id.unwrap()),
+            ty::AssocContainer::InherentImpl => bug!(),
+            ty::AssocContainer::Trait => impl_ty,
+            ty::AssocContainer::TraitImpl(Err(_)) => continue,
+            ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) => {
+                tcx.associated_item(trait_item_def_id)
+            }
         };
 
         let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 22a9446fd4c..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.
@@ -944,12 +933,11 @@ pub(crate) fn check_associated_item(
 
         // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
         // other `Foo` impls are incoherent.
-        tcx.ensure_ok()
-            .coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?;
+        tcx.ensure_ok().coherent_trait(tcx.parent(item.trait_item_or_self()?))?;
 
         let self_ty = match item.container {
-            ty::AssocItemContainer::Trait => tcx.types.self_param,
-            ty::AssocItemContainer::Impl => {
+            ty::AssocContainer::Trait => tcx.types.self_param,
+            ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
                 tcx.type_of(item.container_id(tcx)).instantiate_identity()
             }
         };
@@ -978,7 +966,7 @@ pub(crate) fn check_associated_item(
                 check_method_receiver(wfcx, hir_sig, item, self_ty)
             }
             ty::AssocKind::Type { .. } => {
-                if let ty::AssocItemContainer::Trait = item.container {
+                if let ty::AssocContainer::Trait = item.container {
                     check_associated_type_bounds(wfcx, item, span)
                 }
                 if item.defaultness(tcx).has_value() {
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_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 126ffabd448..dd3590f9ac5 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -111,9 +111,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         }
 
         Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
-            let assoc_item = tcx.associated_item(def_id);
-            let trait_assoc_predicates =
-                tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
+            let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
+            let trait_assoc_predicates = tcx.explicit_predicates_of(trait_item_def_id);
 
             let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
             let impl_def_id = tcx.parent(fn_def_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 62125c99d80..8cbf17162e3 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -125,8 +125,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
         Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => {
             match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
                 Ok(map) => {
-                    let assoc_item = tcx.associated_item(def_id);
-                    return map[&assoc_item.trait_item_def_id.unwrap()];
+                    let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
+                    return map[&trait_item_def_id];
                 }
                 Err(_) => {
                     return ty::EarlyBinder::bind(Ty::new_error_with_message(
@@ -198,7 +198,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                 }
             }
             ImplItemKind::Type(ty) => {
-                if tcx.impl_trait_ref(tcx.hir_get_parent_item(hir_id)).is_none() {
+                if let ImplItemImplKind::Inherent { .. } = item.impl_kind {
                     check_feature_inherent_assoc_ty(tcx, item.span);
                 }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 0b3d50ff219..7370124e800 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1021,7 +1021,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let container_id = assoc_item.container_id(tcx);
                 debug!(?def_id, ?container, ?container_id);
                 match container {
-                    ty::AssocItemContainer::Trait => {
+                    ty::AssocContainer::Trait => {
                         if let Err(e) = callee::check_legal_trait_for_method_call(
                             tcx,
                             path_span,
@@ -1033,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.set_tainted_by_errors(e);
                         }
                     }
-                    ty::AssocItemContainer::Impl => {
+                    ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
                         if segments.len() == 1 {
                             // `<T>::assoc` will end up here, and so
                             // can `T::assoc`. If this came from an
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 94b635c41b4..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,
             );
         }
@@ -2354,7 +1380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // We want it to always point to the trait item.
             // If we're pointing at an inherent function, we don't need to do anything,
             // so we fetch the parent and verify if it's a trait item.
-            && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
+            && let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
             && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
             // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
             && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
@@ -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_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index d7ddbcc8b53..1998a1884b7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1882,7 +1882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if segment.ident.name == sym::clone
             && results.type_dependent_def_id(expr.hir_id).is_some_and(|did| {
                     let assoc_item = self.tcx.associated_item(did);
-                    assoc_item.container == ty::AssocItemContainer::Trait
+                    assoc_item.container == ty::AssocContainer::Trait
                         && assoc_item.container_id(self.tcx) == clone_trait_did
                 })
             // If that clone call hasn't already dereferenced the self type (i.e. don't give this
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 129de32fd4a..7f5397a7926 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -278,8 +278,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
     {
         if let Some(item) = tcx.opt_associated_item(def_id.into())
             && let ty::AssocKind::Const { .. } = item.kind
-            && let ty::AssocItemContainer::Impl = item.container
-            && let Some(trait_item_def_id) = item.trait_item_def_id
+            && let ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container
         {
             let impl_def_id = item.container_id(tcx);
             let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 52a8eff984b..4185f7f6996 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -18,8 +18,8 @@ use rustc_middle::middle::stability;
 use rustc_middle::ty::elaborate::supertrait_def_ids;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
 use rustc_middle::ty::{
-    self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind,
-    ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, Upcast,
+    self, AssocContainer, AssocItem, GenericArgs, GenericArgsRef, GenericParamDefKind, ParamEnvAnd,
+    Ty, TyCtxt, TypeVisitableExt, Upcast,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
@@ -528,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ProbeScope::Single(def_id) => {
                     let item = self.tcx.associated_item(def_id);
                     // FIXME(fn_delegation): Delegation to inherent methods is not yet supported.
-                    assert_eq!(item.container, AssocItemContainer::Trait);
+                    assert_eq!(item.container, AssocContainer::Trait);
 
                     let trait_def_id = self.tcx.parent(def_id);
                     let trait_span = self.tcx.def_span(trait_def_id);
@@ -1659,7 +1659,7 @@ impl<'tcx> Pick<'tcx> {
     /// Do not use for type checking.
     pub(crate) fn differs_from(&self, other: &Self) -> bool {
         let Self {
-            item: AssocItem { def_id, kind: _, container: _, trait_item_def_id: _ },
+            item: AssocItem { def_id, kind: _, container: _ },
             kind: _,
             import_ids: _,
             autoderefs: _,
@@ -1702,7 +1702,7 @@ impl<'tcx> Pick<'tcx> {
                         tcx.def_path_str(self.item.def_id),
                     ));
                 }
-                (ty::AssocKind::Const { name }, ty::AssocItemContainer::Trait) => {
+                (ty::AssocKind::Const { name }, ty::AssocContainer::Trait) => {
                     let def_id = self.item.container_id(tcx);
                     lint.span_suggestion(
                         span,
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_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index d83b18cbc2d..6f6666f8c76 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -30,6 +30,9 @@ interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
 interface_input_file_would_be_overwritten =
     the input file "{$path}" would be overwritten by the generated executable
 
+interface_invalid_crate_type_value = invalid `crate_type` value
+    .suggestion = did you mean
+
 interface_mixed_bin_crate =
     cannot mix `bin` crate type with others
 
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index d1082eaf617..727e09c7562 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -1,7 +1,7 @@
 use std::io;
 use std::path::Path;
 
-use rustc_macros::Diagnostic;
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
@@ -108,3 +108,18 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
     pub feature: &'a str,
     pub enabled: &'a str,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(interface_invalid_crate_type_value)]
+pub(crate) struct UnknownCrateTypes {
+    #[subdiagnostic]
+    pub sugg: Option<UnknownCrateTypesSub>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(interface_suggestion, code = r#""{snippet}""#, applicability = "maybe-incorrect")]
+pub(crate) struct UnknownCrateTypesSub {
+    #[primary_span]
+    pub span: Span,
+    pub snippet: Symbol,
+}
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 04006f3e446..061c764e619 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -13,9 +13,8 @@ use rustc_errors::LintBuffer;
 use rustc_metadata::{DylibError, load_symbol_from_dylib};
 use rustc_middle::ty::CurrentGcx;
 use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple};
-use rustc_session::lint::{self, BuiltinLintDiag};
 use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
-use rustc_session::{EarlyDiagCtxt, Session, filesearch};
+use rustc_session::{EarlyDiagCtxt, Session, filesearch, lint};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMapInputs;
@@ -468,7 +467,10 @@ pub(crate) fn check_attr_crate_type(
                         lint::builtin::UNKNOWN_CRATE_TYPES,
                         ast::CRATE_NODE_ID,
                         span,
-                        BuiltinLintDiag::UnknownCrateTypes { span, candidate },
+                        errors::UnknownCrateTypes {
+                            sugg: candidate
+                                .map(|cand| errors::UnknownCrateTypesSub { span, snippet: cand }),
+                        },
                     );
                 }
             } else {
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 417e5a97069..5b98c9fafaa 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -40,12 +40,6 @@ lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` order
 lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
     .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
 
-lint_avoid_att_syntax =
-    avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-
-lint_avoid_intel_syntax =
-    avoid using `.intel_syntax`, Intel syntax is the default
-
 lint_bad_attribute_argument = bad attribute argument
 
 lint_bad_opt_access = {$msg}
@@ -187,12 +181,6 @@ lint_builtin_unused_doc_comment = unused doc comment
 lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
     .suggestion = use `loop`
 
-lint_byte_slice_in_packed_struct_with_derive = {$ty} slice in a packed struct that derives a built-in trait
-    .help = consider implementing the trait by hand, or remove the `packed` attribute
-
-lint_cfg_attr_no_attributes =
-    `#[cfg_attr]` does not expand to any attributes
-
 lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
 
 lint_closure_returning_async_block = closure returning async block can be made into an async closure
@@ -249,11 +237,6 @@ lint_dropping_copy_types = calls to `std::mem::drop` with a value that implement
 lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
     .label = argument has type `{$arg_ty}`
 
-lint_duplicate_macro_attribute =
-    duplicated attribute
-
-lint_duplicate_matcher_binding = duplicate matcher binding
-
 lint_enum_intrinsics_mem_discriminant =
     the return value of `mem::discriminant` is unspecified when called with a non-enum type
     .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum
@@ -409,9 +392,6 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
 lint_improper_ctypes_union_layout_reason = this union has unspecified layout
 lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
 
-lint_incomplete_include =
-    include macro expected single expression in source
-
 lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly
     .label = use a different label that doesn't start with `0` or `1`
     .help = start numbering with `2` instead
@@ -427,9 +407,6 @@ lint_invalid_asm_label_named = avoid using named labels in inline assembly
     .note = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 lint_invalid_asm_label_no_span = the label may be declared in the expansion of a macro
 
-lint_invalid_crate_type_value = invalid `crate_type` value
-    .suggestion = did you mean
-
 # FIXME: we should ordinalize $valid_up_to when we add support for doing so
 lint_invalid_from_utf8_checked = calls to `{$method}` with an invalid literal always return an error
     .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
@@ -470,15 +447,9 @@ lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a point
     .suggestion_with_exposed_provenance = use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance
     .suggestion_without_provenance_mut = if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
 
-lint_legacy_derive_helpers = derive helper attribute is used before it is introduced
-    .label = the attribute is introduced here
-
 lint_lintpass_by_hand = implementing `LintPass` by hand
     .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
-lint_macro_expanded_macro_exports_accessed_by_absolute_paths = macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
-    .note = the macro is defined here
-
 lint_macro_expr_fragment_specifier_2024_migration =
     the `expr` fragment specifier will accept more expressions in the 2024 edition
     .suggestion = to keep the existing behavior, use the `expr_2021` fragment specifier
@@ -486,10 +457,6 @@ lint_macro_is_private = macro `{$ident}` is private
 
 lint_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used
 
-lint_macro_use_deprecated =
-    applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
-    .help = remove it and import macros at use sites with a `use` item instead
-
 lint_malformed_attribute = malformed lint attribute input
 
 lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
@@ -499,10 +466,6 @@ lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
     .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
     .suggestion = you might have meant to use `Iterator::for_each`
 
-lint_metavariable_still_repeating = variable `{$name}` is still repeating at this depth
-
-lint_metavariable_wrong_operator = meta-variable repeats with different Kleene operator
-
 lint_mismatched_lifetime_syntaxes_eliding_while_named =
     eliding a lifetime that's named elsewhere is confusing
 
@@ -548,9 +511,6 @@ lint_mismatched_lifetime_syntaxes_suggestion_mixed =
 lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths =
     use `'_` for type paths
 
-lint_missing_unsafe_on_extern = extern blocks should be unsafe
-    .suggestion = needs `unsafe` before the extern keyword
-
 lint_mixed_script_confusables =
     the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
     .includes_note = the usage includes {$includes}
@@ -674,9 +634,6 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
 
 lint_opaque_hidden_inferred_bound_sugg = add this bound
 
-lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-    .suggestion = use pat_param to preserve semantics
-
 lint_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location}
     .label = not found from {$location}
     .help = import `macro_rules` with `use` to make it callable above its definition
@@ -719,9 +676,6 @@ lint_pattern_in_foreign = patterns aren't allowed in foreign function declaratio
 lint_private_extern_crate_reexport = extern crate `{$ident}` is private and cannot be re-exported
     .suggestion = consider making the `extern crate` item publicly accessible
 
-lint_proc_macro_derive_resolution_fallback = cannot find {$ns_descr} `{$ident}` in this scope
-    .label = names from parent modules are not accessible without an explicit import
-
 lint_query_instability = using `{$query}` can result in unstable query results
     .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
 
@@ -762,9 +716,6 @@ lint_redundant_semicolons_suggestion = remove {$multiple_semicolons ->
         *[false] this semicolon
     }
 
-lint_reexport_private_dependency =
-    {$kind} `{$name}` from private dependency '{$krate}' is re-exported
-
 lint_remove_mut_from_pattern = remove `mut` from the parameter
 
 lint_removed_lint = lint `{$name}` has been removed: {$reason}
@@ -826,10 +777,6 @@ lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal
 lint_too_large_char_cast = value exceeds maximum `char` value
     .note = maximum valid `char` value is `0x10FFFF`
 
-lint_trailing_semi_macro = trailing semicolon in macro used in expression position
-    .note1 = macro invocations at the end of a block are treated as expressions
-    .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
-
 lint_ty_qualified = usage of qualified `ty::{$ty}`
     .suggestion = try importing it and using it unqualified
 
@@ -935,13 +882,9 @@ lint_unknown_lint =
         *[false] did you mean: `{$replace}`
     }
 
-lint_unknown_macro_variable = unknown macro variable `{$name}`
-
 lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
     .help = add `#![register_tool({$tool_name})]` to the crate root
 
-lint_unnameable_test_items = cannot test inner items
-
 lint_unnecessary_qualification = unnecessary qualification
     .suggestion = remove the unnecessary path segments
 
@@ -964,10 +907,6 @@ lint_untranslatable_diag = diagnostics should be created using translatable mess
 lint_unused_allocation = unnecessary allocation, use `&` instead
 lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
 
-lint_unused_builtin_attribute = unused attribute `{$attr_name}`
-    .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`
-    .suggestion = remove the attribute
-
 lint_unused_closure =
     unused {$pre}{$count ->
         [one] closure
@@ -993,14 +932,6 @@ lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
 lint_unused_delim = unnecessary {$delim} around {$item}
     .suggestion = remove these {$delim}
 
-lint_unused_doc_comment = unused doc comment
-    .label = rustdoc does not generate documentation for macro invocations
-    .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion
-
-lint_unused_extern_crate = unused extern crate
-    .label = unused
-    .suggestion = remove the unused `extern crate`
-
 lint_unused_import_braces = braces around {$node} is unnecessary
 
 lint_unused_imports = {$num_snippets ->
@@ -1014,15 +945,11 @@ lint_unused_imports = {$num_snippets ->
         }
     .help = if this is a test module, consider adding a `#[cfg(test)]` to the containing module
 
-lint_unused_label = unused label
-
 lint_unused_lifetime = lifetime parameter `{$ident}` never used
     .suggestion = elide the unused lifetime
 
 lint_unused_macro_definition = unused macro definition: `{$name}`
 
-lint_unused_macro_use = unused `#[macro_use]` import
-
 lint_unused_op = unused {$op} that must be used
     .label = the {$op} produces a value
     .suggestion = use `let _ = ...` to ignore the resulting value
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index c3c0a34df71..75a0f89321b 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -29,12 +29,12 @@ use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
 use rustc_hir::intravisit::FnKind as HirFnKind;
-use rustc_hir::{Body, FnDecl, PatKind, PredicateOrigin, find_attr};
+use rustc_hir::{Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
 use rustc_middle::bug;
 use rustc_middle::lint::LevelAndSource;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
+use rustc_middle::ty::{self, AssocContainer, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
 use rustc_session::lint::FutureIncompatibilityReason;
 // hardwired lints from rustc_lint_defs
 pub use rustc_session::lint::builtin::*;
@@ -61,7 +61,6 @@ use crate::lints::{
     BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
     BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
 };
-use crate::nonstandard_style::{MethodLateContext, method_context};
 use crate::{
     EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
     fluent_generated as fluent,
@@ -469,14 +468,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
-        let context = method_context(cx, impl_item.owner_id.def_id);
+        let container = cx.tcx.associated_item(impl_item.owner_id.def_id).container;
 
-        match context {
+        match container {
             // If the method is an impl for a trait, don't doc.
-            MethodLateContext::TraitImpl => return,
-            MethodLateContext::TraitAutoImpl => {}
+            AssocContainer::TraitImpl(_) => return,
+            AssocContainer::Trait => {}
             // If the method is an impl for an item with docs_hidden, don't doc.
-            MethodLateContext::PlainImpl => {
+            AssocContainer::InherentImpl => {
                 let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id());
                 let impl_ty = cx.tcx.type_of(parent).instantiate_identity();
                 let outerdef = match impl_ty.kind() {
@@ -1321,9 +1320,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
-        // Only lint inherent impl items.
-        if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() {
-            self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false);
+        if let ImplItemImplKind::Inherent { vis_span } = impl_item.impl_kind {
+            self.perform_lint(cx, "item", impl_item.owner_id.def_id, vis_span, false);
         }
     }
 }
diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs
index 7300490b838..9029ee04471 100644
--- a/compiler/rustc_lint/src/early/diagnostics.rs
+++ b/compiler/rustc_lint/src/early/diagnostics.rs
@@ -64,17 +64,6 @@ pub fn decorate_builtin_lint(
             }
             .decorate_lint(diag);
         }
-        BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
-            span: macro_span,
-            ns_descr,
-            ident,
-        } => lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns_descr, ident }
-            .decorate_lint(diag),
-        BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
-            lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def }
-                .decorate_lint(diag)
-        }
-
         BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
             lints::ElidedLifetimesInPaths {
                 subdiag: elided_lifetime_in_path_suggestion(
@@ -87,10 +76,6 @@ pub fn decorate_builtin_lint(
             }
             .decorate_lint(diag);
         }
-        BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
-            let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate });
-            lints::UnknownCrateTypes { sugg }.decorate_lint(diag);
-        }
         BuiltinLintDiag::UnusedImports {
             remove_whole_use,
             num_to_remove,
@@ -146,9 +131,6 @@ pub fn decorate_builtin_lint(
             stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }
                 .decorate_lint(diag);
         }
-        BuiltinLintDiag::UnusedDocComment(attr_span) => {
-            lints::UnusedDocComment { span: attr_span }.decorate_lint(diag);
-        }
         BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => {
             let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span };
             if is_foreign {
@@ -158,12 +140,6 @@ pub fn decorate_builtin_lint(
             }
             .decorate_lint(diag);
         }
-        BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
-            lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag);
-        }
-        BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => {
-            lints::OrPatternsBackCompat { span: suggestion_span, suggestion }.decorate_lint(diag);
-        }
         BuiltinLintDiag::ReservedPrefix(label_span, prefix) => {
             lints::ReservedPrefix {
                 label: label_span,
@@ -183,18 +159,6 @@ pub fn decorate_builtin_lint(
                 lints::ReservedMultihash { suggestion }.decorate_lint(diag);
             }
         }
-        BuiltinLintDiag::UnusedBuiltinAttribute {
-            attr_name,
-            macro_name,
-            invoc_span,
-            attr_span,
-        } => {
-            lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name, attr_span }
-                .decorate_lint(diag);
-        }
-        BuiltinLintDiag::TrailingMacro(is_trailing, name) => {
-            lints::TrailingMacro { is_trailing, name }.decorate_lint(diag);
-        }
         BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => {
             lints::BreakWithLabelAndLoop {
                 sub: lints::BreakWithLabelAndLoopSub {
@@ -221,9 +185,6 @@ pub fn decorate_builtin_lint(
             };
             lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
         }
-        BuiltinLintDiag::MissingUnsafeOnExtern { suggestion } => {
-            lints::MissingUnsafeOnExtern { suggestion }.decorate_lint(diag);
-        }
         BuiltinLintDiag::SingleUseLifetime {
             param_span,
             use_span: Some((use_span, elide)),
@@ -253,7 +214,6 @@ pub fn decorate_builtin_lint(
                 .decorate_lint(diag);
         }
         BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => {
-            debug!(?deletion_span);
             lints::UnusedLifetime { deletion_span, ident }.decorate_lint(diag);
         }
         BuiltinLintDiag::NamedArgumentUsedPositionally {
@@ -291,12 +251,6 @@ pub fn decorate_builtin_lint(
             }
             .decorate_lint(diag);
         }
-        BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => {
-            lints::ByteSliceInPackedStructWithDerive { ty }.decorate_lint(diag);
-        }
-        BuiltinLintDiag::UnusedExternCrate { span, removal_span } => {
-            lints::UnusedExternCrate { span, removal_span }.decorate_lint(diag);
-        }
         BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
             let suggestion_span = vis_span.between(ident_span);
             let code = if vis_span.is_empty() { "use " } else { " use " };
@@ -335,9 +289,6 @@ pub fn decorate_builtin_lint(
             }
             .decorate_lint(diag);
         }
-        BuiltinLintDiag::ReexportPrivateDependency { name, kind, krate } => {
-            lints::ReexportPrivateDependency { name, kind, krate }.decorate_lint(diag);
-        }
         BuiltinLintDiag::UnusedQualifications { removal_span } => {
             lints::UnusedQualifications { removal_span }.decorate_lint(diag);
         }
@@ -377,15 +328,10 @@ pub fn decorate_builtin_lint(
             });
             lints::UnknownDiagnosticAttribute { typo }.decorate_lint(diag);
         }
-        BuiltinLintDiag::MacroUseDeprecated => {
-            lints::MacroUseDeprecated.decorate_lint(diag);
-        }
-        BuiltinLintDiag::UnusedMacroUse => lints::UnusedMacroUse.decorate_lint(diag),
         BuiltinLintDiag::PrivateExternCrateReexport { source: ident, extern_crate_span } => {
             lints::PrivateExternCrateReexport { ident, sugg: extern_crate_span.shrink_to_lo() }
                 .decorate_lint(diag);
         }
-        BuiltinLintDiag::UnusedLabel => lints::UnusedLabel.decorate_lint(diag),
         BuiltinLintDiag::MacroIsPrivate(ident) => {
             lints::MacroIsPrivate { ident }.decorate_lint(diag);
         }
@@ -398,36 +344,6 @@ pub fn decorate_builtin_lint(
         BuiltinLintDiag::UnstableFeature(msg) => {
             lints::UnstableFeature { msg }.decorate_lint(diag);
         }
-        BuiltinLintDiag::AvoidUsingIntelSyntax => {
-            lints::AvoidIntelSyntax.decorate_lint(diag);
-        }
-        BuiltinLintDiag::AvoidUsingAttSyntax => {
-            lints::AvoidAttSyntax.decorate_lint(diag);
-        }
-        BuiltinLintDiag::IncompleteInclude => {
-            lints::IncompleteInclude.decorate_lint(diag);
-        }
-        BuiltinLintDiag::UnnameableTestItems => {
-            lints::UnnameableTestItems.decorate_lint(diag);
-        }
-        BuiltinLintDiag::DuplicateMacroAttribute => {
-            lints::DuplicateMacroAttribute.decorate_lint(diag);
-        }
-        BuiltinLintDiag::CfgAttrNoAttributes => {
-            lints::CfgAttrNoAttributes.decorate_lint(diag);
-        }
-        BuiltinLintDiag::MetaVariableStillRepeating(name) => {
-            lints::MetaVariableStillRepeating { name }.decorate_lint(diag);
-        }
-        BuiltinLintDiag::MetaVariableWrongOperator => {
-            lints::MetaVariableWrongOperator.decorate_lint(diag);
-        }
-        BuiltinLintDiag::DuplicateMatcherBinding => {
-            lints::DuplicateMatcherBinding.decorate_lint(diag);
-        }
-        BuiltinLintDiag::UnknownMacroVariable(name) => {
-            lints::UnknownMacroVariable { name }.decorate_lint(diag);
-        }
         BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
             lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag)
         }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 56d65ed08f9..b7312484de5 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_session::lint::AmbiguityErrorDiag;
 use rustc_span::edition::Edition;
-use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym};
+use rustc_span::{Ident, Span, Symbol, sym};
 
 use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds};
 use crate::errors::{OverruledAttributeSub, RequestedLevel};
@@ -2536,15 +2536,6 @@ pub(crate) mod unexpected_cfg_value {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_macro_use_deprecated)]
-#[help]
-pub(crate) struct MacroUseDeprecated;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_unused_macro_use)]
-pub(crate) struct UnusedMacroUse;
-
-#[derive(LintDiagnostic)]
 #[diag(lint_private_extern_crate_reexport, code = E0365)]
 pub(crate) struct PrivateExternCrateReexport {
     pub ident: Ident,
@@ -2553,10 +2544,6 @@ pub(crate) struct PrivateExternCrateReexport {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_unused_label)]
-pub(crate) struct UnusedLabel;
-
-#[derive(LintDiagnostic)]
 #[diag(lint_macro_is_private)]
 pub(crate) struct MacroIsPrivate {
     pub ident: Ident,
@@ -2586,50 +2573,6 @@ impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_avoid_intel_syntax)]
-pub(crate) struct AvoidIntelSyntax;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_avoid_att_syntax)]
-pub(crate) struct AvoidAttSyntax;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_incomplete_include)]
-pub(crate) struct IncompleteInclude;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_unnameable_test_items)]
-pub(crate) struct UnnameableTestItems;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_duplicate_macro_attribute)]
-pub(crate) struct DuplicateMacroAttribute;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_cfg_attr_no_attributes)]
-pub(crate) struct CfgAttrNoAttributes;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_metavariable_still_repeating)]
-pub(crate) struct MetaVariableStillRepeating {
-    pub name: MacroRulesNormalizedIdent,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(lint_metavariable_wrong_operator)]
-pub(crate) struct MetaVariableWrongOperator;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_duplicate_matcher_binding)]
-pub(crate) struct DuplicateMatcherBinding;
-
-#[derive(LintDiagnostic)]
-#[diag(lint_unknown_macro_variable)]
-pub(crate) struct UnknownMacroVariable {
-    pub name: MacroRulesNormalizedIdent,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_unused_crate_dependency)]
 #[help]
 pub(crate) struct UnusedCrateDependency {
@@ -2715,22 +2658,6 @@ pub(crate) struct AbsPathWithModuleSugg {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_proc_macro_derive_resolution_fallback)]
-pub(crate) struct ProcMacroDeriveResolutionFallback {
-    #[label]
-    pub span: Span,
-    pub ns_descr: &'static str,
-    pub ident: Ident,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)]
-pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
-    #[note]
-    pub definition: Span,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_hidden_lifetime_parameters)]
 pub(crate) struct ElidedLifetimesInPaths {
     #[subdiagnostic]
@@ -2738,21 +2665,6 @@ pub(crate) struct ElidedLifetimesInPaths {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_invalid_crate_type_value)]
-pub(crate) struct UnknownCrateTypes {
-    #[subdiagnostic]
-    pub sugg: Option<UnknownCrateTypesSub>,
-}
-
-#[derive(Subdiagnostic)]
-#[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")]
-pub(crate) struct UnknownCrateTypesSub {
-    #[primary_span]
-    pub span: Span,
-    pub candidate: Symbol,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_unused_imports)]
 pub(crate) struct UnusedImports {
     #[subdiagnostic]
@@ -2810,14 +2722,6 @@ pub(crate) enum RedundantImportSub {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_unused_doc_comment)]
-#[help]
-pub(crate) struct UnusedDocComment {
-    #[label]
-    pub span: Span,
-}
-
-#[derive(LintDiagnostic)]
 pub(crate) enum PatternsInFnsWithoutBody {
     #[diag(lint_pattern_in_foreign)]
     Foreign {
@@ -2841,21 +2745,6 @@ pub(crate) struct PatternsInFnsWithoutBodySub {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_legacy_derive_helpers)]
-pub(crate) struct LegacyDeriveHelpers {
-    #[label]
-    pub span: Span,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(lint_or_patterns_back_compat)]
-pub(crate) struct OrPatternsBackCompat {
-    #[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
-    pub span: Span,
-    pub suggestion: String,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_reserved_prefix)]
 pub(crate) struct ReservedPrefix {
     #[label]
@@ -2876,27 +2765,6 @@ pub(crate) struct RawPrefix {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_unused_builtin_attribute)]
-pub(crate) struct UnusedBuiltinAttribute {
-    #[note]
-    pub invoc_span: Span,
-    pub attr_name: Symbol,
-    pub macro_name: String,
-    #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
-    pub attr_span: Span,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(lint_trailing_semi_macro)]
-pub(crate) struct TrailingMacro {
-    #[note(lint_note1)]
-    #[note(lint_note2)]
-    pub is_trailing: bool,
-
-    pub name: Ident,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_break_with_label_and_loop)]
 pub(crate) struct BreakWithLabelAndLoop {
     #[subdiagnostic]
@@ -2939,13 +2807,6 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_missing_unsafe_on_extern)]
-pub(crate) struct MissingUnsafeOnExtern {
-    #[suggestion(code = "unsafe ", applicability = "machine-applicable")]
-    pub suggestion: Span,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_single_use_lifetime)]
 pub(crate) struct SingleUseLifetime {
     #[label(lint_label_param)]
@@ -2993,23 +2854,6 @@ pub(crate) struct NamedArgumentUsedPositionally {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_byte_slice_in_packed_struct_with_derive)]
-#[help]
-pub(crate) struct ByteSliceInPackedStructWithDerive {
-    // FIXME: make this translatable
-    pub ty: String,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(lint_unused_extern_crate)]
-pub(crate) struct UnusedExternCrate {
-    #[label]
-    pub span: Span,
-    #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
-    pub removal_span: Span,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_extern_crate_not_idiomatic)]
 pub(crate) struct ExternCrateNotIdiomatic {
     #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
@@ -3057,14 +2901,6 @@ pub(crate) struct HiddenGlobReexports {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_reexport_private_dependency)]
-pub(crate) struct ReexportPrivateDependency {
-    pub name: String,
-    pub kind: String,
-    pub krate: Symbol,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_unnecessary_qualification)]
 pub(crate) struct UnusedQualifications {
     #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 65075cfecfa..7f643a551bb 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{FnKind, Visitor};
 use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
 use rustc_middle::hir::nested_filter::All;
-use rustc_middle::ty;
+use rustc_middle::ty::AssocContainer;
 use rustc_session::config::CrateType;
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::def_id::LocalDefId;
@@ -20,29 +20,6 @@ use crate::lints::{
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 
-#[derive(PartialEq)]
-pub(crate) enum MethodLateContext {
-    TraitAutoImpl,
-    TraitImpl,
-    PlainImpl,
-}
-
-pub(crate) fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext {
-    let item = cx.tcx.associated_item(id);
-    match item.container {
-        ty::AssocItemContainer::Trait => MethodLateContext::TraitAutoImpl,
-        ty::AssocItemContainer::Impl => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
-            Some(_) => MethodLateContext::TraitImpl,
-            None => MethodLateContext::PlainImpl,
-        },
-    }
-}
-
-fn assoc_item_in_trait_impl(cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) -> bool {
-    let item = cx.tcx.associated_item(ii.owner_id);
-    item.trait_item_def_id.is_some()
-}
-
 declare_lint! {
     /// The `non_camel_case_types` lint detects types, variants, traits and
     /// type parameters that don't have camel case names.
@@ -389,8 +366,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
         id: LocalDefId,
     ) {
         match &fk {
-            FnKind::Method(ident, sig, ..) => match method_context(cx, id) {
-                MethodLateContext::PlainImpl => {
+            FnKind::Method(ident, sig, ..) => match cx.tcx.associated_item(id).container {
+                AssocContainer::InherentImpl => {
                     if sig.header.abi != ExternAbi::Rust
                         && find_attr!(cx.tcx.get_all_attrs(id), AttributeKind::NoMangle(..))
                     {
@@ -398,10 +375,10 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
                     }
                     self.check_snake_case(cx, "method", ident);
                 }
-                MethodLateContext::TraitAutoImpl => {
+                AssocContainer::Trait => {
                     self.check_snake_case(cx, "trait method", ident);
                 }
-                _ => (),
+                AssocContainer::TraitImpl(_) => {}
             },
             FnKind::ItemFn(ident, _, header) => {
                 // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
@@ -602,7 +579,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
         if let hir::ImplItemKind::Const(..) = ii.kind
-            && !assoc_item_in_trait_impl(cx, ii)
+            && let hir::ImplItemImplKind::Inherent { .. } = ii.impl_kind
         {
             NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ii.ident);
         }
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 2e84233e5a5..40a818a3c9d 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -11,7 +11,7 @@ use rustc_hir_id::{HashStableContext, HirId, ItemLocalId};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::def_id::DefPathHash;
 pub use rustc_span::edition::Edition;
-use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym};
+use rustc_span::{Ident, Span, Symbol, sym};
 use serde::{Deserialize, Serialize};
 
 pub use self::Level::*;
@@ -620,17 +620,7 @@ pub enum DeprecatedSinceKind {
 #[derive(Debug)]
 pub enum BuiltinLintDiag {
     AbsPathWithModule(Span),
-    ProcMacroDeriveResolutionFallback {
-        span: Span,
-        ns_descr: &'static str,
-        ident: Ident,
-    },
-    MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
     ElidedLifetimesInPaths(usize, Span, bool, Span),
-    UnknownCrateTypes {
-        span: Span,
-        candidate: Option<Symbol>,
-    },
     UnusedImports {
         remove_whole_use: bool,
         num_to_remove: usize,
@@ -646,20 +636,11 @@ pub enum BuiltinLintDiag {
         path: String,
         since_kind: DeprecatedSinceKind,
     },
-    UnusedDocComment(Span),
-    UnusedBuiltinAttribute {
-        attr_name: Symbol,
-        macro_name: String,
-        invoc_span: Span,
-        attr_span: Span,
-    },
     PatternsInFnsWithoutBody {
         span: Span,
         ident: Ident,
         is_foreign: bool,
     },
-    LegacyDeriveHelpers(Span),
-    OrPatternsBackCompat(Span, String),
     ReservedPrefix(Span, String),
     /// `'r#` in edition < 2021.
     RawPrefix(Span),
@@ -668,15 +649,11 @@ pub enum BuiltinLintDiag {
         is_string: bool,
         suggestion: Span,
     },
-    TrailingMacro(bool, Ident),
     BreakWithLabelAndLoop(Span),
     UnicodeTextFlow(Span, String),
     UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
     UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
     DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
-    MissingUnsafeOnExtern {
-        suggestion: Span,
-    },
     SingleUseLifetime {
         /// Span of the parameter which declares this lifetime.
         param_span: Span,
@@ -701,14 +678,6 @@ pub enum BuiltinLintDiag {
         /// Indicates if the named argument is used as a width/precision for formatting
         is_formatting_arg: bool,
     },
-    ByteSliceInPackedStructWithDerive {
-        // FIXME: enum of byte/string
-        ty: String,
-    },
-    UnusedExternCrate {
-        span: Span,
-        removal_span: Span,
-    },
     ExternCrateNotIdiomatic {
         vis_span: Span,
         ident_span: Span,
@@ -736,11 +705,6 @@ pub enum BuiltinLintDiag {
         /// The local binding that shadows the glob reexport.
         private_item_span: Span,
     },
-    ReexportPrivateDependency {
-        name: String,
-        kind: String,
-        krate: Symbol,
-    },
     UnusedQualifications {
         /// The span of the unnecessarily-qualified path to remove.
         removal_span: Span,
@@ -763,27 +727,14 @@ pub enum BuiltinLintDiag {
         span: Span,
         typo_name: Option<Symbol>,
     },
-    MacroUseDeprecated,
-    UnusedMacroUse,
     PrivateExternCrateReexport {
         source: Ident,
         extern_crate_span: Span,
     },
-    UnusedLabel,
     MacroIsPrivate(Ident),
     UnusedMacroDefinition(Symbol),
     MacroRuleNeverUsed(usize, Symbol),
     UnstableFeature(DiagMessage),
-    AvoidUsingIntelSyntax,
-    AvoidUsingAttSyntax,
-    IncompleteInclude,
-    UnnameableTestItems,
-    DuplicateMacroAttribute,
-    CfgAttrNoAttributes,
-    MetaVariableStillRepeating(MacroRulesNormalizedIdent),
-    MetaVariableWrongOperator,
-    DuplicateMatcherBinding,
-    UnknownMacroVariable(MacroRulesNormalizedIdent),
     UnusedCrateDependency {
         extern_crate: Symbol,
         local_crate: Symbol,
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_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 110b26c62ef..0c8d1f32e99 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1194,10 +1194,6 @@ impl<'a> CrateMetadataRef<'a> {
         self.root.tables.default_fields.get(self, id).map(|d| d.decode(self))
     }
 
-    fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> {
-        self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self))
-    }
-
     fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
         self.root
             .tables
@@ -1359,14 +1355,9 @@ impl<'a> CrateMetadataRef<'a> {
             }
             _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
         };
-        let container = self.root.tables.assoc_container.get(self, id).unwrap();
+        let container = self.root.tables.assoc_container.get(self, id).unwrap().decode(self);
 
-        ty::AssocItem {
-            kind,
-            def_id: self.local_def_id(id),
-            trait_item_def_id: self.get_trait_item_def_id(id),
-            container,
-        }
+        ty::AssocItem { kind, def_id: self.local_def_id(id), container }
     }
 
     fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index a7e7e9985f4..db66938457f 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -22,7 +22,7 @@ use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::mir::interpret;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::specialization_graph;
-use rustc_middle::ty::AssocItemContainer;
+use rustc_middle::ty::AssocContainer;
 use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::fast_reject::{self, TreatParams};
 use rustc_middle::{bug, span_bug};
@@ -1254,8 +1254,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         DefKind::AssocTy => {
             let assoc_item = tcx.associated_item(def_id);
             match assoc_item.container {
-                ty::AssocItemContainer::Impl => true,
-                ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(),
+                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
+                ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
             }
         }
         DefKind::TyParam => {
@@ -1725,24 +1725,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let tcx = self.tcx;
         let item = tcx.associated_item(def_id);
 
-        self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx));
-        self.tables.assoc_container.set_some(def_id.index, item.container);
-
-        match item.container {
-            AssocItemContainer::Trait => {
-                if item.is_type() {
-                    self.encode_explicit_item_bounds(def_id);
-                    self.encode_explicit_item_self_bounds(def_id);
-                    if tcx.is_conditionally_const(def_id) {
-                        record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id]
-                            <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder());
-                    }
-                }
-            }
-            AssocItemContainer::Impl => {
-                if let Some(trait_item_def_id) = item.trait_item_def_id {
-                    self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into());
-                }
+        if matches!(item.container, AssocContainer::Trait | AssocContainer::TraitImpl(_)) {
+            self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx));
+        }
+
+        record!(self.tables.assoc_container[def_id] <- item.container);
+
+        if let AssocContainer::Trait = item.container
+            && item.is_type()
+        {
+            self.encode_explicit_item_bounds(def_id);
+            self.encode_explicit_item_self_bounds(def_id);
+            if tcx.is_conditionally_const(def_id) {
+                record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id]
+                    <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder());
             }
         }
         if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 1f7d142d330..720970bbaf9 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -447,7 +447,6 @@ define_tables! {
     coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
     eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>,
     trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
-    trait_item_def_id: Table<DefIndex, RawDefId>,
     expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
     default_fields: Table<DefIndex, LazyValue<DefId>>,
     params_in_repr: Table<DefIndex, LazyValue<DenseBitSet<u32>>>,
@@ -459,7 +458,7 @@ define_tables! {
     def_keys: Table<DefIndex, LazyValue<DefKey>>,
     proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
     variant_data: Table<DefIndex, LazyValue<VariantData>>,
-    assoc_container: Table<DefIndex, ty::AssocItemContainer>,
+    assoc_container: Table<DefIndex, LazyValue<ty::AssocContainer>>,
     macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,
     proc_macro: Table<DefIndex, MacroKind>,
     deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs
index 34180001f80..4b2dc2c814e 100644
--- a/compiler/rustc_metadata/src/rmeta/parameterized.rs
+++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs
@@ -102,7 +102,7 @@ trivially_parameterized_over_tcx! {
     rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
     rustc_middle::mir::ConstQualifs,
     rustc_middle::ty::AnonConstKind,
-    rustc_middle::ty::AssocItemContainer,
+    rustc_middle::ty::AssocContainer,
     rustc_middle::ty::AsyncDestructor,
     rustc_middle::ty::Asyncness,
     rustc_middle::ty::DeducedParamAttrs,
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 2cb07a28a8a..a882ee4f2b9 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -222,13 +222,6 @@ fixed_size_enum! {
 }
 
 fixed_size_enum! {
-    ty::AssocItemContainer {
-        ( Trait )
-        ( Impl  )
-    }
-}
-
-fixed_size_enum! {
     MacroKind {
         ( Attr   )
         ( Bang   )
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_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index bea2191c560..4c00b769237 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -318,7 +318,7 @@ trivial! {
     rustc_middle::traits::WellFormedLoc,
     rustc_middle::ty::adjustment::CoerceUnsizedInfo,
     rustc_middle::ty::AssocItem,
-    rustc_middle::ty::AssocItemContainer,
+    rustc_middle::ty::AssocContainer,
     rustc_middle::ty::Asyncness,
     rustc_middle::ty::AsyncDestructor,
     rustc_middle::ty::BoundVariableKind,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 2aa32dfa0d8..0e645a3aae4 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1881,6 +1881,7 @@ rustc_queries! {
     }
 
     /// Returns whether the impl or associated function has the `default` keyword.
+    /// Note: This will ICE on inherent impl items. Consider using `AssocItem::defaultness`.
     query defaultness(def_id: DefId) -> hir::Defaultness {
         desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) }
         separate_provide_extern
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index a902a8a61e5..768646c7630 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -5,15 +5,17 @@ use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_hir::find_attr;
 use rustc_macros::{Decodable, Encodable, HashStable};
-use rustc_span::{Ident, Symbol};
+use rustc_span::{ErrorGuaranteed, Ident, Symbol};
 
 use super::{TyCtxt, Visibility};
 use crate::ty;
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
-pub enum AssocItemContainer {
+pub enum AssocContainer {
     Trait,
-    Impl,
+    InherentImpl,
+    /// The `DefId` points to the trait item being implemented.
+    TraitImpl(Result<DefId, ErrorGuaranteed>),
 }
 
 /// Information about an associated item
@@ -21,11 +23,7 @@ pub enum AssocItemContainer {
 pub struct AssocItem {
     pub def_id: DefId,
     pub kind: AssocKind,
-    pub container: AssocItemContainer,
-
-    /// If this is an item in an impl of a trait then this is the `DefId` of
-    /// the associated item on the trait that this implements.
-    pub trait_item_def_id: Option<DefId>,
+    pub container: AssocContainer,
 }
 
 impl AssocItem {
@@ -55,7 +53,34 @@ impl AssocItem {
     ///
     /// [`type_of`]: crate::ty::TyCtxt::type_of
     pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
-        tcx.defaultness(self.def_id)
+        match self.container {
+            AssocContainer::InherentImpl => hir::Defaultness::Final,
+            AssocContainer::Trait | AssocContainer::TraitImpl(_) => tcx.defaultness(self.def_id),
+        }
+    }
+
+    pub fn expect_trait_impl(&self) -> Result<DefId, ErrorGuaranteed> {
+        let AssocContainer::TraitImpl(trait_item_id) = self.container else {
+            bug!("expected item to be in a trait impl: {:?}", self.def_id);
+        };
+        trait_item_id
+    }
+
+    /// If this is a trait impl item, returns the `DefId` of the trait item this implements.
+    /// Otherwise, returns `DefId` for self. Returns an Err in case the trait item was not
+    /// resolved successfully.
+    pub fn trait_item_or_self(&self) -> Result<DefId, ErrorGuaranteed> {
+        match self.container {
+            AssocContainer::TraitImpl(id) => id,
+            AssocContainer::Trait | AssocContainer::InherentImpl => Ok(self.def_id),
+        }
+    }
+
+    pub fn trait_item_def_id(&self) -> Option<DefId> {
+        match self.container {
+            AssocContainer::TraitImpl(Ok(id)) => Some(id),
+            _ => None,
+        }
     }
 
     #[inline]
@@ -71,16 +96,18 @@ impl AssocItem {
     #[inline]
     pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
         match self.container {
-            AssocItemContainer::Impl => None,
-            AssocItemContainer::Trait => Some(tcx.parent(self.def_id)),
+            AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => None,
+            AssocContainer::Trait => Some(tcx.parent(self.def_id)),
         }
     }
 
     #[inline]
     pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
         match self.container {
-            AssocItemContainer::Impl => Some(tcx.parent(self.def_id)),
-            AssocItemContainer::Trait => None,
+            AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => {
+                Some(tcx.parent(self.def_id))
+            }
+            AssocContainer::Trait => None,
         }
     }
 
@@ -156,11 +183,11 @@ impl AssocItem {
             return false;
         }
 
-        let def_id = match (self.container, self.trait_item_def_id) {
-            (AssocItemContainer::Trait, _) => self.def_id,
-            (AssocItemContainer::Impl, Some(trait_item_did)) => trait_item_did,
-            // Inherent impl but this attr is only applied to trait assoc items.
-            (AssocItemContainer::Impl, None) => return true,
+        let def_id = match self.container {
+            AssocContainer::Trait => self.def_id,
+            AssocContainer::TraitImpl(Ok(trait_item_did)) => trait_item_did,
+            AssocContainer::TraitImpl(Err(_)) => return false,
+            AssocContainer::InherentImpl => return true,
         };
         find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_))
     }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8ea767dccd3..79700d485c4 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2276,7 +2276,16 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) {
             Node::Item(..) | Node::TraitItem(..) => false,
-            Node::ImplItem(..) => self.is_bound_region_in_impl_item(suitable_region_binding_scope),
+            Node::ImplItem(impl_item) => match impl_item.impl_kind {
+                // For now, we do not try to target impls of traits. This is
+                // because this message is going to suggest that the user
+                // change the fn signature, but they may not be free to do so,
+                // since the signature must match the trait.
+                //
+                // FIXME(#42706) -- in some cases, we could do better here.
+                hir::ImplItemImplKind::Trait { .. } => true,
+                _ => false,
+            },
             _ => false,
         };
 
@@ -2330,21 +2339,6 @@ impl<'tcx> TyCtxt<'tcx> {
         None
     }
 
-    /// Checks if the bound region is in Impl Item.
-    pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
-        let container_id = self.parent(suitable_region_binding_scope.to_def_id());
-        if self.impl_trait_ref(container_id).is_some() {
-            // For now, we do not try to target impls of traits. This is
-            // because this message is going to suggest that the user
-            // change the fn signature, but they may not be free to do so,
-            // since the signature must match the trait.
-            //
-            // FIXME(#42706) -- in some cases, we could do better here.
-            return true;
-        }
-        false
-    }
-
     /// Determines whether identifiers in the assembly have strict naming rules.
     /// Currently, only NVPTX* targets need it.
     pub fn has_strict_asm_symbol_naming(self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index e76993e0542..34ead91b4f6 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -18,8 +18,8 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::print::{FmtPrinter, Print};
 use crate::ty::{
-    self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self, AssocContainer, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
+    TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 
 /// An `InstanceKind` along with the args that are needed to substitute the instance.
@@ -611,26 +611,23 @@ impl<'tcx> Instance<'tcx> {
                     debug!(" => fn pointer created for virtual call");
                     resolved.def = InstanceKind::ReifyShim(def_id, reason);
                 }
-                // Reify `Trait::method` implementations if KCFI is enabled
-                // FIXME(maurer) only reify it if it is a vtable-safe function
-                _ if tcx.sess.is_sanitizer_kcfi_enabled()
-                    && tcx
-                        .opt_associated_item(def_id)
-                        .and_then(|assoc| assoc.trait_item_def_id)
-                        .is_some() =>
-                {
-                    // If this function could also go in a vtable, we need to `ReifyShim` it with
-                    // KCFI because it can only attach one type per function.
-                    resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
-                }
-                // Reify `::call`-like method implementations if KCFI is enabled
-                _ if tcx.sess.is_sanitizer_kcfi_enabled()
-                    && tcx.is_closure_like(resolved.def_id()) =>
-                {
-                    // Reroute through a reify via the *unresolved* instance. The resolved one can't
-                    // be directly reified because it's closure-like. The reify can handle the
-                    // unresolved instance.
-                    resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
+                _ if tcx.sess.is_sanitizer_kcfi_enabled() => {
+                    // Reify `::call`-like method implementations
+                    if tcx.is_closure_like(resolved.def_id()) {
+                        // Reroute through a reify via the *unresolved* instance. The resolved one can't
+                        // be directly reified because it's closure-like. The reify can handle the
+                        // unresolved instance.
+                        resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
+                    // Reify `Trait::method` implementations
+                    // FIXME(maurer) only reify it if it is a vtable-safe function
+                    } else if let Some(assoc) = tcx.opt_associated_item(def_id)
+                        && let AssocContainer::Trait | AssocContainer::TraitImpl(Ok(_)) =
+                            assoc.container
+                    {
+                        // If this function could also go in a vtable, we need to `ReifyShim` it with
+                        // KCFI because it can only attach one type per function.
+                        resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
+                    }
                 }
                 _ => {}
             }
@@ -683,7 +680,7 @@ impl<'tcx> Instance<'tcx> {
                     && !matches!(
                         tcx.opt_associated_item(def),
                         Some(ty::AssocItem {
-                            container: ty::AssocItemContainer::Trait,
+                            container: ty::AssocContainer::Trait,
                             ..
                         })
                     );
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index da17ec1f9f3..d4c001f625e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1934,6 +1934,11 @@ impl<'tcx> TyCtxt<'tcx> {
         Some((parent, def_kind))
     }
 
+    /// Returns the trait item that is implemented by the given item `DefId`.
+    pub fn trait_item_of(self, def_id: impl IntoQueryParam<DefId>) -> Option<DefId> {
+        self.opt_associated_item(def_id.into_query_param())?.trait_item_def_id()
+    }
+
     /// If the given `DefId` is an associated item of a trait,
     /// returns the `DefId` of the trait; otherwise, returns `None`.
     pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> {
@@ -2149,17 +2154,12 @@ impl<'tcx> TyCtxt<'tcx> {
         let Some(item) = self.opt_associated_item(def_id) else {
             return false;
         };
-        if item.container != ty::AssocItemContainer::Impl {
-            return false;
-        }
 
-        let Some(trait_item_def_id) = item.trait_item_def_id else {
+        let AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container else {
             return false;
         };
 
-        return !self
-            .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
-            .is_empty();
+        !self.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id).is_empty()
     }
 }
 
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index ab7885905a6..75537caa894 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -75,7 +75,7 @@ passes_const_stable_not_stable =
     .label = attribute specified here
 
 passes_custom_mir_incompatible_dialect_and_phase =
-    The {$dialect} dialect is not compatible with the {$phase} phase
+    the {$dialect} dialect is not compatible with the {$phase} phase
     .dialect_span = this dialect...
     .phase_span = ... is not compatible with this phase
 
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index fc33405d455..3c2c9683a4d 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -373,31 +373,27 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
     /// Automatically generated items marked with `rustc_trivial_field_reads`
     /// will be ignored for the purposes of dead code analysis (see PR #85200
     /// for discussion).
-    fn should_ignore_item(&mut self, def_id: DefId) -> bool {
-        if let Some(impl_of) = self.tcx.trait_impl_of_assoc(def_id) {
-            if !self.tcx.is_automatically_derived(impl_of) {
-                return false;
-            }
-
-            if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
-                && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
+    fn should_ignore_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) -> bool {
+        if let hir::ImplItemImplKind::Trait { .. } = impl_item.impl_kind
+            && let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id())
+            && self.tcx.is_automatically_derived(impl_of)
+            && let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity()
+            && self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads)
+        {
+            if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind()
+                && let Some(adt_def_id) = adt_def.did().as_local()
             {
-                let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity();
-                if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind()
-                    && let Some(adt_def_id) = adt_def.did().as_local()
-                {
-                    self.ignored_derived_traits.entry(adt_def_id).or_default().insert(trait_of);
-                }
-                return true;
+                self.ignored_derived_traits.entry(adt_def_id).or_default().insert(trait_ref.def_id);
             }
+            return true;
         }
 
         false
     }
 
     fn visit_node(&mut self, node: Node<'tcx>) {
-        if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node
-            && self.should_ignore_item(owner_id.to_def_id())
+        if let Node::ImplItem(impl_item) = node
+            && self.should_ignore_impl_item(impl_item)
         {
             return;
         }
@@ -439,7 +435,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             }
             Node::ImplItem(impl_item) => {
                 let item = self.tcx.local_parent(impl_item.owner_id.def_id);
-                if self.tcx.impl_trait_ref(item).is_none() {
+                if let hir::ImplItemImplKind::Inherent { .. } = impl_item.impl_kind {
                     //// If it's a type whose items are live, then it's live, too.
                     //// This is done to handle the case where, for example, the static
                     //// method of a private type is used, but the type itself is never
@@ -484,13 +480,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
     fn check_impl_or_impl_item_live(&mut self, local_def_id: LocalDefId) -> bool {
         let (impl_block_id, trait_def_id) = match self.tcx.def_kind(local_def_id) {
             // assoc impl items of traits are live if the corresponding trait items are live
-            DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => (
-                self.tcx.local_parent(local_def_id),
-                self.tcx
-                    .associated_item(local_def_id)
-                    .trait_item_def_id
-                    .and_then(|def_id| def_id.as_local()),
-            ),
+            DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => {
+                let trait_item_id =
+                    self.tcx.trait_item_of(local_def_id).and_then(|def_id| def_id.as_local());
+                (self.tcx.local_parent(local_def_id), trait_item_id)
+            }
             // impl items are live if the corresponding traits are live
             DefKind::Impl { of_trait: true } => (
                 local_def_id,
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 71650c6b9b9..2ee1bd0dfd1 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -21,8 +21,8 @@ use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::middle::stability::{AllowUnstable, Deprecated, DeprecationEntry, EvalResult};
 use rustc_middle::query::{LocalCrate, Providers};
-use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::{AssocContainer, TyCtxt};
 use rustc_session::lint;
 use rustc_session::lint::builtin::{DEPRECATED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL};
 use rustc_span::{Span, Symbol, sym};
@@ -486,8 +486,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
         self.check_compatible_stability(ii.owner_id.def_id);
-        let impl_def_id = self.tcx.hir_get_parent_item(ii.hir_id());
-        if self.tcx.impl_trait_ref(impl_def_id).is_none() {
+        if let hir::ImplItemImplKind::Inherent { .. } = ii.impl_kind {
             self.check_missing_stability(ii.owner_id.def_id);
             self.check_missing_const_stability(ii.owner_id.def_id);
         }
@@ -711,7 +710,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
                 for impl_item_ref in items {
                     let impl_item = self.tcx.associated_item(impl_item_ref.owner_id);
 
-                    if let Some(def_id) = impl_item.trait_item_def_id {
+                    if let AssocContainer::TraitImpl(Ok(def_id)) = impl_item.container {
                         // Pass `None` to skip deprecation warnings.
                         self.tcx.check_stability(
                             def_id,
diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs
index 1b5f0ed1429..bcc77ff849d 100644
--- a/compiler/rustc_public/src/ty.rs
+++ b/compiler/rustc_public/src/ty.rs
@@ -1612,11 +1612,7 @@ crate_def! {
 pub struct AssocItem {
     pub def_id: AssocDef,
     pub kind: AssocKind,
-    pub container: AssocItemContainer,
-
-    /// If this is an item in an impl of a trait then this is the `DefId` of
-    /// the associated item on the trait that this implements.
-    pub trait_item_def_id: Option<AssocDef>,
+    pub container: AssocContainer,
 }
 
 #[derive(Clone, PartialEq, Debug, Eq, Serialize)]
@@ -1636,9 +1632,11 @@ pub enum AssocKind {
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, Serialize)]
-pub enum AssocItemContainer {
+pub enum AssocContainer {
+    InherentImpl,
+    /// The `AssocDef` points to the trait item being implemented.
+    TraitImpl(AssocDef),
     Trait,
-    Impl,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs
index 207038db40d..5131611eb02 100644
--- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs
+++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs
@@ -1076,14 +1076,21 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind {
     }
 }
 
-impl<'tcx> Stable<'tcx> for ty::AssocItemContainer {
-    type T = crate::ty::AssocItemContainer;
+impl<'tcx> Stable<'tcx> for ty::AssocContainer {
+    type T = crate::ty::AssocContainer;
 
-    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
-        use crate::ty::AssocItemContainer;
+    fn stable(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        _: &CompilerCtxt<'_, BridgeTys>,
+    ) -> Self::T {
+        use crate::ty::AssocContainer;
         match self {
-            ty::AssocItemContainer::Trait => AssocItemContainer::Trait,
-            ty::AssocItemContainer::Impl => AssocItemContainer::Impl,
+            ty::AssocContainer::Trait => AssocContainer::Trait,
+            ty::AssocContainer::InherentImpl => AssocContainer::InherentImpl,
+            ty::AssocContainer::TraitImpl(trait_item_id) => {
+                AssocContainer::TraitImpl(tables.assoc_def(trait_item_id.unwrap()))
+            }
         }
     }
 }
@@ -1100,7 +1107,6 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem {
             def_id: tables.assoc_def(self.def_id),
             kind: self.kind.stable(tables, cx),
             container: self.container.stable(tables, cx),
-            trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)),
         }
     }
 }
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 0e566e20a12..cc8fbc18b73 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -231,6 +231,9 @@ resolve_item_was_cfg_out = the item is gated here
 resolve_label_with_similar_name_reachable =
     a label with a similar name is reachable
 
+resolve_legacy_derive_helpers = derive helper attribute is used before it is introduced
+    .label = the attribute is introduced here
+
 resolve_lending_iterator_report_error =
     associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
     .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type
@@ -260,6 +263,9 @@ resolve_macro_defined_later =
 resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments =
     macro-expanded `extern crate` items cannot shadow names passed with `--extern`
 
+resolve_macro_expanded_macro_exports_accessed_by_absolute_paths = macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
+    .note = the macro is defined here
+
 resolve_macro_expected_found =
     expected {$expected}, found {$found} `{$macro_path}`
     .label = not {$article} {$expected}
@@ -268,6 +274,10 @@ resolve_macro_extern_deprecated =
     `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
     .help = try an outer attribute: `#[macro_use]`
 
+resolve_macro_use_deprecated =
+    applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
+    .help = remove it and import macros at use sites with a `use` item instead
+
 resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
 
 resolve_macro_use_name_already_in_use =
@@ -339,6 +349,9 @@ resolve_param_in_ty_of_const_param =
 
 resolve_pattern_doesnt_bind_name = pattern doesn't bind `{$name}`
 
+resolve_proc_macro_derive_resolution_fallback = cannot find {$ns_descr} `{$ident}` in this scope
+    .label = names from parent modules are not accessible without an explicit import
+
 resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
     .help = you can define integration tests in a directory named `tests`
 
@@ -348,6 +361,9 @@ resolve_reexport_of_crate_public =
 resolve_reexport_of_private =
     re-export of private `{$ident}`
 
+resolve_reexport_private_dependency =
+    {$kind} `{$name}` from private dependency '{$krate}' is re-exported
+
 resolve_relative_2018 =
     relative paths are not supported in visibilities in 2018 edition or later
     .suggestion = try
@@ -465,6 +481,14 @@ resolve_unreachable_label_suggestion_use_similarly_named =
 resolve_unreachable_label_with_similar_name_exists =
     a label with a similar name exists but is unreachable
 
+resolve_unused_extern_crate = unused extern crate
+    .label = unused
+    .suggestion = remove the unused `extern crate`
+
+resolve_unused_label = unused label
+
+resolve_unused_macro_use = unused `#[macro_use]` import
+
 resolve_variable_bound_with_different_mode =
     variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
     .label = bound in different ways
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 50a1ad23a54..95f979a3fed 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -169,7 +169,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
                         UNUSED_EXTERN_CRATES,
                         extern_crate.id,
                         span,
-                        BuiltinLintDiag::UnusedExternCrate {
+                        crate::errors::UnusedExternCrate {
                             span: extern_crate.span,
                             removal_span: extern_crate.span_with_attributes,
                         },
@@ -406,7 +406,7 @@ impl Resolver<'_, '_> {
                                 MACRO_USE_EXTERN_CRATE,
                                 import.root_id,
                                 import.span,
-                                BuiltinLintDiag::MacroUseDeprecated,
+                                crate::errors::MacroUseDeprecated,
                             );
                         }
                     }
@@ -427,7 +427,7 @@ impl Resolver<'_, '_> {
                         UNUSED_IMPORTS,
                         import.root_id,
                         import.span,
-                        BuiltinLintDiag::UnusedMacroUse,
+                        crate::errors::UnusedMacroUse,
                     );
                 }
                 _ => {}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 689e713ef46..236ab1f09d3 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -138,7 +138,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
                 CRATE_NODE_ID,
                 span_use,
-                BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+                errors::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def },
             );
         }
 
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 72be94e58db..f0ea97ba8a0 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_errors::{
     Applicability, Diag, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, MultiSpan,
     Subdiagnostic,
 };
-use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Ident, Span, Symbol};
 
 use crate::late::PatternSource;
@@ -566,6 +566,22 @@ pub(crate) struct ProcMacroSameCrate {
     pub(crate) is_test: bool,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(resolve_proc_macro_derive_resolution_fallback)]
+pub(crate) struct ProcMacroDeriveResolutionFallback {
+    #[label]
+    pub span: Span,
+    pub ns_descr: &'static str,
+    pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(resolve_macro_expanded_macro_exports_accessed_by_absolute_paths)]
+pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
+    #[note]
+    pub definition: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(resolve_imported_crate)]
 pub(crate) struct CrateImported {
@@ -1276,3 +1292,40 @@ pub(crate) struct TraitImplMismatch {
     #[label(resolve_trait_impl_mismatch_label_item)]
     pub(crate) trait_item_span: Span,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(resolve_legacy_derive_helpers)]
+pub(crate) struct LegacyDeriveHelpers {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(resolve_unused_extern_crate)]
+pub(crate) struct UnusedExternCrate {
+    #[label]
+    pub span: Span,
+    #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
+    pub removal_span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(resolve_reexport_private_dependency)]
+pub(crate) struct ReexportPrivateDependency {
+    pub name: Symbol,
+    pub kind: &'static str,
+    pub krate: Symbol,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(resolve_unused_label)]
+pub(crate) struct UnusedLabel;
+
+#[derive(LintDiagnostic)]
+#[diag(resolve_unused_macro_use)]
+pub(crate) struct UnusedMacroUse;
+
+#[derive(LintDiagnostic)]
+#[diag(resolve_macro_use_deprecated)]
+#[help]
+pub(crate) struct MacroUseDeprecated;
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index bc06a227571..35051675fd8 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -4,7 +4,6 @@ use rustc_ast::{self as ast, NodeId};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_middle::bug;
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
 use rustc_session::parse::feature_err;
 use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
@@ -520,7 +519,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                                         PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
                                         lint_id,
                                         orig_ident.span,
-                                        BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
+                                        errors::ProcMacroDeriveResolutionFallback {
                                             span: orig_ident.span,
                                             ns_descr: ns.descr(),
                                             ident,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index d7fc028287f..33c2c7436d1 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -720,9 +720,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         EXPORTED_PRIVATE_DEPENDENCIES,
                         binding_id,
                         binding.span,
-                        BuiltinLintDiag::ReexportPrivateDependency {
-                            kind: binding.res().descr().to_string(),
-                            name: key.ident.name.to_string(),
+                        crate::errors::ReexportPrivateDependency {
+                            name: key.ident.name,
+                            kind: binding.res().descr(),
                             krate: self.tcx.crate_name(reexported_def_id.krate),
                         },
                     );
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 521fef2b9d4..4d4acc60ca8 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -29,7 +29,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::ty::{DelegationFnSig, Visibility};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
-use rustc_session::lint::{self, BuiltinLintDiag};
+use rustc_session::lint;
 use rustc_session::parse::feature_err;
 use rustc_span::source_map::{Spanned, respan};
 use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
@@ -5225,7 +5225,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 lint::builtin::UNUSED_LABELS,
                 *id,
                 *span,
-                BuiltinLintDiag::UnusedLabel,
+                errors::UnusedLabel,
             );
         }
     }
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 5fa87b4cd9b..d3e98ef839b 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -979,7 +979,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             LEGACY_DERIVE_HELPERS,
                             node_id,
                             ident.span,
-                            BuiltinLintDiag::LegacyDeriveHelpers(binding.span),
+                            errors::LegacyDeriveHelpers { span: binding.span },
                         );
                     }
                 }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index d81fa062e01..577a16a0d25 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -469,8 +469,7 @@ fn implemented_method<'tcx>(
     let ancestor = if let Some(impl_id) = tcx.impl_of_assoc(instance.def_id()) {
         // Implementation in an `impl` block
         trait_ref = tcx.impl_trait_ref(impl_id)?;
-        let impl_method = tcx.associated_item(instance.def_id());
-        method_id = impl_method.trait_item_def_id?;
+        method_id = tcx.trait_item_of(instance.def_id())?;
         trait_method = tcx.associated_item(method_id);
         trait_id = trait_ref.skip_binder().def_id;
         impl_id
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 19494ffc37e..633cbc3a4ae 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -46,6 +46,8 @@ use crate::symbol::{Symbol, kw, sym};
 use crate::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, with_session_globals};
 
 /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
+///
+/// See <https://rustc-dev-guide.rust-lang.org/macro-expansion.html> for more explanation.
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub struct SyntaxContext(u32);
 
@@ -61,7 +63,10 @@ pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
 
 #[derive(Clone, Copy, Debug)]
 struct SyntaxContextData {
+    /// The last macro expansion in the chain.
+    /// (Here we say the most deeply nested macro expansion is the "outermost" expansion.)
     outer_expn: ExpnId,
+    /// Transparency of the last macro expansion
     outer_transparency: Transparency,
     parent: SyntaxContext,
     /// This context, but with all transparent and semi-opaque expansions filtered away.
@@ -450,11 +455,13 @@ impl HygieneData {
         self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque
     }
 
+    /// See [`SyntaxContextData::outer_expn`]
     #[inline]
     fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
         self.syntax_context_data[ctxt.0 as usize].outer_expn
     }
 
+    /// The last macro expansion and its Transparency
     #[inline]
     fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
         let data = &self.syntax_context_data[ctxt.0 as usize];
@@ -900,6 +907,7 @@ impl SyntaxContext {
         HygieneData::with(|data| data.normalize_to_macro_rules(self))
     }
 
+    /// See [`SyntaxContextData::outer_expn`]
     #[inline]
     pub fn outer_expn(self) -> ExpnId {
         HygieneData::with(|data| data.outer_expn(self))
@@ -912,6 +920,7 @@ impl SyntaxContext {
         HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone())
     }
 
+    /// See [`HygieneData::outer_mark`]
     #[inline]
     fn outer_mark(self) -> (ExpnId, Transparency) {
         HygieneData::with(|data| data.outer_mark(self))
@@ -982,19 +991,20 @@ impl Span {
 #[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
 pub struct ExpnData {
     // --- The part unique to each expansion.
-    /// The kind of this expansion - macro or compiler desugaring.
     pub kind: ExpnKind,
-    /// The expansion that produced this expansion.
+    /// The expansion that contains the definition of the macro for this expansion.
     pub parent: ExpnId,
-    /// The location of the actual macro invocation or syntax sugar , e.g.
-    /// `let x = foo!();` or `if let Some(y) = x {}`
+    /// The span of the macro call which produced this expansion.
+    ///
+    /// This span will typically have a different `ExpnData` and `call_site`.
+    /// This recursively traces back through any macro calls which expanded into further
+    /// macro calls, until the "source call-site" is reached at the root SyntaxContext.
+    /// For example, if `food!()` expands to `fruit!()` which then expands to `grape`,
+    /// then the call-site of `grape` is `fruit!()` and the call-site of `fruit!()`
+    /// is `food!()`.
     ///
-    /// This may recursively refer to other macro invocations, e.g., if
-    /// `foo!()` invoked `bar!()` internally, and there was an
-    /// expression inside `bar!`; the call_site of the expression in
-    /// the expansion would point to the `bar!` invocation; that
-    /// call_site span would have its own ExpnData, with the call_site
-    /// pointing to the `foo!` invocation.
+    /// For a desugaring expansion, this is the span of the expression or node that was
+    /// desugared.
     pub call_site: Span,
     /// Used to force two `ExpnData`s to have different `Fingerprint`s.
     /// Due to macro expansion, it's possible to end up with two `ExpnId`s
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index ae6755f0764..e95b743b1ce 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -710,8 +710,8 @@ impl Span {
         if !ctxt.is_root() { ctxt.outer_expn_data().call_site.source_callsite() } else { self }
     }
 
-    /// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
-    /// if any.
+    /// Returns the call-site span of the last macro expansion which produced this `Span`.
+    /// (see [`ExpnData::call_site`]). Returns `None` if this is not an expansion.
     pub fn parent_callsite(self) -> Option<Span> {
         let ctxt = self.ctxt();
         (!ctxt.is_root()).then(|| ctxt.outer_expn_data().call_site)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index e042ce84955..f997842a607 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -857,11 +857,11 @@ fn foo(&self) -> Self::T { String::new() }
                     && self.infcx.can_eq(param_env, assoc_ty, found)
                 {
                     let msg = match assoc_item.container {
-                        ty::AssocItemContainer::Trait => {
+                        ty::AssocContainer::Trait => {
                             "associated type defaults can't be assumed inside the \
                                             trait defining them"
                         }
-                        ty::AssocItemContainer::Impl => {
+                        ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
                             "associated type is `default` and may be overridden"
                         }
                     };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index 7369134420c..518d4fe17e8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -571,13 +571,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // but right now it's not really very smart when it comes to implicit `Sized`
         // predicates and bounds on the trait itself.
 
-        let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx)
-        else {
-            return;
-        };
-        let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else {
+        let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(impl_item_def_id.to_def_id()) else {
             return;
         };
+        let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
         let trait_args = trait_ref
             .instantiate_identity()
             // Replace the explicit self type with `Self` for better suggestion rendering
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
index 8a67e4ccd45..f54ebd76cab 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
@@ -5,7 +5,7 @@
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{LangItem, lang_items};
-use rustc_middle::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv};
+use rustc_middle::ty::{AssocContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv};
 use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, sym};
 use tracing::debug;
 
@@ -76,8 +76,9 @@ pub fn call_kind<'tcx>(
     let parent = tcx.opt_associated_item(method_did).and_then(|assoc| {
         let container_id = assoc.container_id(tcx);
         match assoc.container {
-            AssocItemContainer::Impl => tcx.trait_id_of_impl(container_id),
-            AssocItemContainer::Trait => Some(container_id),
+            AssocContainer::InherentImpl => None,
+            AssocContainer::TraitImpl(_) => tcx.trait_id_of_impl(container_id),
+            AssocContainer::Trait => Some(container_id),
         }
     });
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index cb84d583e6e..f2f840581cf 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -421,7 +421,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 })
                 | hir::Node::ImplItem(hir::ImplItem {
                     generics,
-                    trait_item_def_id: None,
+                    impl_kind: hir::ImplItemImplKind::Inherent { .. },
                     kind: hir::ImplItemKind::Fn(..),
                     ..
                 }) if finder.can_suggest_bound(generics) => {
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/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 19eb85506b6..4d0465777dd 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -387,7 +387,7 @@ pub(crate) fn assoc_def(
     if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_def_id) {
         // Ensure that the impl is constrained, otherwise projection may give us
         // bad unconstrained infer vars.
-        if assoc_item.item.container == ty::AssocItemContainer::Impl
+        if let ty::AssocContainer::TraitImpl(_) = assoc_item.item.container
             && let Some(impl_def_id) = assoc_item.item.container_id(tcx).as_local()
         {
             tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?;
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index e9629e31482..84f52e7fc9d 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -2,7 +2,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatorState};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{self as hir, ItemKind};
+use rustc_hir::{self as hir, ImplItemImplKind, ItemKind};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
 use rustc_middle::{bug, span_bug};
@@ -63,7 +63,7 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
 fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> {
     tcx.associated_items(impl_id)
         .in_definition_order()
-        .filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
+        .filter_map(|item| item.trait_item_def_id().map(|trait_item| (trait_item, item.def_id)))
         .collect()
 }
 
@@ -97,12 +97,7 @@ fn associated_item_from_trait_item(
         }
     };
 
-    ty::AssocItem {
-        kind,
-        def_id: owner_id.to_def_id(),
-        trait_item_def_id: Some(owner_id.to_def_id()),
-        container: ty::AssocItemContainer::Trait,
-    }
+    ty::AssocItem { kind, def_id: owner_id.to_def_id(), container: ty::AssocContainer::Trait }
 }
 
 fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> ty::AssocItem {
@@ -118,12 +113,13 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>
         }
     };
 
-    ty::AssocItem {
-        kind,
-        def_id: owner_id.to_def_id(),
-        trait_item_def_id: impl_item.trait_item_def_id,
-        container: ty::AssocItemContainer::Impl,
-    }
+    let container = match impl_item.impl_kind {
+        ImplItemImplKind::Inherent { .. } => ty::AssocContainer::InherentImpl,
+        ImplItemImplKind::Trait { trait_item_def_id, .. } => {
+            ty::AssocContainer::TraitImpl(trait_item_def_id)
+        }
+    };
+    ty::AssocItem { kind, def_id: owner_id.to_def_id(), container }
 }
 struct RPITVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -190,7 +186,10 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
                     }
                     let did = item.owner_id.def_id.to_def_id();
                     let item = tcx.hir_impl_item(*item);
-                    let Some(trait_item_def_id) = item.trait_item_def_id else {
+                    let ImplItemImplKind::Trait {
+                        trait_item_def_id: Ok(trait_item_def_id), ..
+                    } = item.impl_kind
+                    else {
                         return Some((did, vec![]));
                     };
                     let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| {
@@ -256,8 +255,7 @@ fn associated_type_for_impl_trait_in_trait(
             }),
         },
         def_id,
-        trait_item_def_id: None,
-        container: ty::AssocItemContainer::Trait,
+        container: ty::AssocContainer::Trait,
     });
 
     // Copy visility of the containing function.
@@ -322,8 +320,7 @@ fn associated_type_for_impl_trait_in_impl(
             }),
         },
         def_id,
-        trait_item_def_id: Some(trait_assoc_def_id),
-        container: ty::AssocItemContainer::Impl,
+        container: ty::AssocContainer::TraitImpl(Ok(trait_assoc_def_id)),
     });
 
     // Copy visility of the containing function.
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index cdfb93c4e7d..543f6a3ccf7 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -107,7 +107,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
                 // the assumed wf types of the trait's RPITIT GAT.
                 ty::ImplTraitInTraitData::Impl { .. } => {
                     let impl_def_id = tcx.local_parent(def_id);
-                    let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap();
+                    let rpitit_def_id = tcx.trait_item_of(def_id).unwrap();
                     let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
                         tcx,
                         impl_def_id.to_def_id(),
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 4a7263d0ccd..eb3236d3006 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -245,7 +245,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
 
                         for &assoc in self.tcx.associated_items(parent).in_definition_order() {
                             trace!(?assoc);
-                            if assoc.trait_item_def_id != Some(alias_ty.def_id) {
+                            if assoc.expect_trait_impl() != Ok(alias_ty.def_id) {
                                 continue;
                             }
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index b22c326b9f2..a5987757dc3 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -88,7 +88,10 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
                 }),
             ..
         })
-        | hir::Node::ImplItem(hir::ImplItem { defaultness, .. })
+        | hir::Node::ImplItem(hir::ImplItem {
+            impl_kind: hir::ImplItemImplKind::Trait { defaultness, .. },
+            ..
+        })
         | hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness,
         node => {
             bug!("`defaultness` called on {:?}", node);
@@ -165,7 +168,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
 
     if tcx.def_kind(def_id) == DefKind::AssocFn
         && let assoc_item = tcx.associated_item(def_id)
-        && assoc_item.container == ty::AssocItemContainer::Trait
+        && assoc_item.container == ty::AssocContainer::Trait
         && assoc_item.defaultness(tcx).has_value()
     {
         let sig = tcx.fn_sig(def_id).instantiate_identity();
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/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
index 88ad1197777..643bd95df84 100644
--- a/library/core/src/ffi/va_list.rs
+++ b/library/core/src/ffi/va_list.rs
@@ -202,18 +202,23 @@ mod sealed {
     impl<T> Sealed for *const T {}
 }
 
-/// Trait which permits the allowed types to be used with [`VaListImpl::arg`].
+/// Types that are valid to read using [`VaListImpl::arg`].
 ///
 /// # Safety
 ///
-/// This trait must only be implemented for types that C passes as varargs without implicit promotion.
+/// The standard library implements this trait for primitive types that are
+/// expected to have a variable argument application-binary interface (ABI) on all
+/// platforms.
 ///
-/// In C varargs, integers smaller than [`c_int`] and floats smaller than [`c_double`]
-/// are implicitly promoted to [`c_int`] and [`c_double`] respectively. Implementing this trait for
-/// types that are subject to this promotion rule is invalid.
+/// When C passes variable arguments, integers smaller than [`c_int`] and floats smaller
+/// than [`c_double`] are implicitly promoted to [`c_int`] and [`c_double`] respectively.
+/// Implementing this trait for types that are subject to this promotion rule is invalid.
 ///
 /// [`c_int`]: core::ffi::c_int
 /// [`c_double`]: core::ffi::c_double
+// We may unseal this trait in the future, but currently our `va_arg` implementations don't support
+// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used
+// to accept unsupported types in the meantime.
 pub unsafe trait VaArgSafe: sealed::Sealed {}
 
 // i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
@@ -233,7 +238,19 @@ unsafe impl<T> VaArgSafe for *mut T {}
 unsafe impl<T> VaArgSafe for *const T {}
 
 impl<'f> VaListImpl<'f> {
-    /// Advance to the next arg.
+    /// Advance to and read the next variable argument.
+    ///
+    /// # Safety
+    ///
+    /// This function is only sound to call when the next variable argument:
+    ///
+    /// - has a type that is ABI-compatible with the type `T`
+    /// - has a value that is a properly initialized value of type `T`
+    ///
+    /// Calling this function with an incompatible type, an invalid value, or when there
+    /// are no more variable arguments, is unsound.
+    ///
+    /// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html
     #[inline]
     pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
         // SAFETY: the caller must uphold the safety contract for `va_arg`.
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/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/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 1c55824ab90..7ff4af8ede8 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -1257,6 +1257,108 @@ mod ref_keyword {}
 /// [`async`]: ../std/keyword.async.html
 mod return_keyword {}
 
+#[doc(keyword = "become")]
+//
+/// Perform a tail-call of a function.
+///
+/// <div class="warning">
+///
+/// `feature(explicit_tail_calls)` is currently incomplete and may not work properly.
+/// </div>
+///
+/// When tail calling a function, instead of its stack frame being added to the
+/// stack, the stack frame of the caller is directly replaced with the callee's.
+/// This means that as long as a loop in a call graph only uses tail calls, the
+/// stack growth will be bounded.
+///
+/// This is useful for writing functional-style code (since it prevents recursion
+/// from exhausting resources) or for code optimization (since a tail call
+/// *might* be cheaper than a normal call, tail calls can be used in a similar
+/// manner to computed goto).
+///
+/// Example of using `become` to implement functional-style `fold`:
+/// ```
+/// #![feature(explicit_tail_calls)]
+/// #![expect(incomplete_features)]
+///
+/// fn fold<T: Copy, S>(slice: &[T], init: S, f: impl Fn(S, T) -> S) -> S {
+///     match slice {
+///         // without `become`, on big inputs this could easily overflow the
+///         // stack. using a tail call guarantees that the stack will not grow unboundedly
+///         [first, rest @ ..] => become fold(rest, f(init, *first), f),
+///         [] => init,
+///     }
+/// }
+/// ```
+///
+/// Compilers can already perform "tail call optimization" -- they can replace normal
+/// calls with tail calls, although there are no guarantees that this will be done.
+/// However, to perform TCO, the call needs to be the last thing that happens
+/// in the functions and be returned from it. This requirement is often broken
+/// by drop code for locals, which is run after computing the return expression:
+///
+/// ```
+/// fn example() {
+///     let string = "meow".to_owned();
+///     println!("{string}");
+///     return help(); // this is *not* the last thing that happens in `example`...
+/// }
+///
+/// // ... because it is desugared to this:
+/// fn example_desugared() {
+///     let string = "meow".to_owned();
+///     println!("{string}");
+///     let tmp = help();
+///     drop(string);
+///     return tmp;
+/// }
+///
+/// fn help() {}
+/// ```
+///
+/// For this reason, `become` also changes the drop order, such that locals are
+/// dropped *before* evaluating the call.
+///
+/// In order to guarantee that the compiler can perform a tail call, `become`
+/// currently has these requirements:
+/// 1. callee and caller must have the same ABI, arguments, and return type
+/// 2. callee and caller must not have varargs
+/// 3. caller must not be marked with `#[track_caller]`
+///    - callee is allowed to be marked with `#[track_caller]` as otherwise
+///      adding `#[track_caller]` would be a breaking change. if callee is
+///      marked with `#[track_caller]` a tail call is not guaranteed.
+/// 4. callee and caller cannot be a closure
+///    (unless it's coerced to a function pointer)
+///
+/// It is possible to tail-call a function pointer:
+/// ```
+/// #![feature(explicit_tail_calls)]
+/// #![expect(incomplete_features)]
+///
+/// #[derive(Copy, Clone)]
+/// enum Inst { Inc, Dec }
+///
+/// fn dispatch(stream: &[Inst], state: u32) -> u32 {
+///     const TABLE: &[fn(&[Inst], u32) -> u32] = &[increment, decrement];
+///     match stream {
+///         [inst, rest @ ..] => become TABLE[*inst as usize](rest, state),
+///         [] => state,
+///     }
+/// }
+///
+/// fn increment(stream: &[Inst], state: u32) -> u32 {
+///     become dispatch(stream, state + 1)
+/// }
+///
+/// fn decrement(stream: &[Inst], state: u32) -> u32 {
+///     become dispatch(stream, state - 1)
+/// }
+///
+/// let program = &[Inst::Inc, Inst::Inc, Inst::Dec, Inst::Inc];
+/// assert_eq!(dispatch(program, 0), 2);
+/// ```
+mod become_keyword {}
+
 #[doc(keyword = "self")]
 //
 /// The receiver of a method, or the current module.
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5725816c600..33e3bf0c085 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -284,7 +284,6 @@
 #![feature(core_float_math)]
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
-#![feature(derive_const)]
 #![feature(doc_cfg)]
 #![feature(doc_cfg_hide)]
 #![feature(doc_masked)]
@@ -332,11 +331,7 @@
 #![feature(cfg_select)]
 #![feature(char_internals)]
 #![feature(clone_to_uninit)]
-#![feature(const_cmp)]
 #![feature(const_convert)]
-#![feature(const_ops)]
-#![feature(const_option_ops)]
-#![feature(const_try)]
 #![feature(core_intrinsics)]
 #![feature(core_io_borrowed_buf)]
 #![feature(drop_guard)]
diff --git a/library/std/src/sync/nonpoison/condvar.rs b/library/std/src/sync/nonpoison/condvar.rs
index 49afdd87818..994fc6816a0 100644
--- a/library/std/src/sync/nonpoison/condvar.rs
+++ b/library/std/src/sync/nonpoison/condvar.rs
@@ -198,11 +198,10 @@ impl Condvar {
     /// the system time. This function is susceptible to spurious wakeups.
     /// Condition variables normally have a boolean predicate associated with
     /// them, and the predicate must always be checked each time this function
-    /// returns to protect against spurious wakeups. Additionally, it is
-    /// typically desirable for the timeout to not exceed some duration in
-    /// spite of spurious wakes, thus the sleep-duration is decremented by the
-    /// amount slept. Alternatively, use the `wait_timeout_while` method
-    /// to wait with a timeout while a predicate is true.
+    /// returns to protect against spurious wakeups.  Furthermore, since the timeout
+    /// is given relative to the moment this function is called, it needs to be adjusted
+    /// when this function is called in a loop. The [`wait_timeout_while`] method
+    /// lets you wait with a timeout while a predicate is true, taking care of all these concerns.
     ///
     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
     /// known to have elapsed.
diff --git a/library/std/src/sync/poison/condvar.rs b/library/std/src/sync/poison/condvar.rs
index 5dc2b510f3a..de625a6cc5f 100644
--- a/library/std/src/sync/poison/condvar.rs
+++ b/library/std/src/sync/poison/condvar.rs
@@ -269,11 +269,10 @@ impl Condvar {
     /// the system time. This function is susceptible to spurious wakeups.
     /// Condition variables normally have a boolean predicate associated with
     /// them, and the predicate must always be checked each time this function
-    /// returns to protect against spurious wakeups. Additionally, it is
-    /// typically desirable for the timeout to not exceed some duration in
-    /// spite of spurious wakes, thus the sleep-duration is decremented by the
-    /// amount slept. Alternatively, use the `wait_timeout_while` method
-    /// to wait with a timeout while a predicate is true.
+    /// returns to protect against spurious wakeups. Furthermore, since the timeout
+    /// is given relative to the moment this function is called, it needs to be adjusted
+    /// when this function is called in a loop. The [`wait_timeout_while`] method
+    /// lets you wait with a timeout while a predicate is true, taking care of all these concerns.
     ///
     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
     /// known to have elapsed.
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/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs
index 89a427ab88b..f76a5f96c87 100644
--- a/library/std/src/sys/pal/hermit/time.rs
+++ b/library/std/src/sys/pal/hermit/time.rs
@@ -25,15 +25,8 @@ impl Timespec {
         Timespec { t: timespec { tv_sec, tv_nsec } }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
-        // FIXME: const PartialOrd
-        let mut cmp = self.t.tv_sec - other.t.tv_sec;
-        if cmp == 0 {
-            cmp = self.t.tv_nsec as i64 - other.t.tv_nsec as i64;
-        }
-
-        if cmp >= 0 {
+    fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
+        if self >= other {
             Ok(if self.t.tv_nsec >= other.t.tv_nsec {
                 Duration::new(
                     (self.t.tv_sec - other.t.tv_sec) as u64,
@@ -53,22 +46,20 @@ impl Timespec {
         }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
+    fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
         let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?;
 
         // Nano calculations can't overflow because nanos are <1B which fit
         // in a u32.
-        let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
-        if nsec >= NSEC_PER_SEC as u32 {
-            nsec -= NSEC_PER_SEC as u32;
+        let mut nsec = other.subsec_nanos() + u32::try_from(self.t.tv_nsec).unwrap();
+        if nsec >= NSEC_PER_SEC.try_into().unwrap() {
+            nsec -= u32::try_from(NSEC_PER_SEC).unwrap();
             secs = secs.checked_add(1)?;
         }
         Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
+    fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
         let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?;
 
         // Similar to above, nanos can't overflow.
@@ -222,18 +213,15 @@ impl SystemTime {
         SystemTime(time)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
         self.0.sub_timespec(&other.0)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_add_duration(other)?))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_sub_duration(other)?))
     }
 }
diff --git a/library/std/src/sys/pal/sgx/time.rs b/library/std/src/sys/pal/sgx/time.rs
index 603dae952ab..db4cf2804bf 100644
--- a/library/std/src/sys/pal/sgx/time.rs
+++ b/library/std/src/sys/pal/sgx/time.rs
@@ -32,22 +32,15 @@ impl SystemTime {
         SystemTime(usercalls::insecure_time())
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        // FIXME: ok_or_else with const closures
-        match self.0.checked_sub(other.0) {
-            Some(duration) => Ok(duration),
-            None => Err(other.0 - self.0),
-        }
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_add(*other)?))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_sub(*other)?))
     }
 }
diff --git a/library/std/src/sys/pal/solid/time.rs b/library/std/src/sys/pal/solid/time.rs
index e35e60df1a0..c39d715c6a6 100644
--- a/library/std/src/sys/pal/solid/time.rs
+++ b/library/std/src/sys/pal/solid/time.rs
@@ -39,8 +39,7 @@ impl SystemTime {
         Self(t)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
         if self.0 >= other.0 {
             Ok(Duration::from_secs((self.0 as u64).wrapping_sub(other.0 as u64)))
         } else {
@@ -48,13 +47,11 @@ impl SystemTime {
         }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_add_unsigned(other.as_secs())?))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_sub_unsigned(other.as_secs())?))
     }
 }
diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs
index 36ce3f7ef96..c6636626fd5 100644
--- a/library/std/src/sys/pal/uefi/time.rs
+++ b/library/std/src/sys/pal/uefi/time.rs
@@ -80,32 +80,19 @@ impl SystemTime {
             .unwrap_or_else(|| panic!("time not implemented on this platform"))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        // FIXME: ok_or_else with const closures
-        match self.0.checked_sub(other.0) {
-            Some(duration) => Ok(duration),
-            None => Err(other.0 - self.0),
-        }
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
-        let temp = self.0.checked_add(*other)?;
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+        let temp = Self(self.0.checked_add(*other)?);
 
         // Check if can be represented in UEFI
-        // FIXME: const PartialOrd
-        let mut cmp = temp.as_secs() - MAX_UEFI_TIME.0.as_secs();
-        if cmp == 0 {
-            cmp = temp.subsec_nanos() as u64 - MAX_UEFI_TIME.0.subsec_nanos() as u64;
-        }
-
-        if cmp <= 0 { Some(SystemTime(temp)) } else { None }
+        if temp <= MAX_UEFI_TIME { Some(temp) } else { None }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
-        Some(SystemTime(self.0.checked_sub(*other)?))
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+        self.0.checked_sub(*other).map(Self)
     }
 }
 
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index 328fe0bc960..bd7f74fea6a 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -38,18 +38,15 @@ impl SystemTime {
         SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
         self.t.sub_timespec(&other.t)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime { t: self.t.checked_add_duration(other)? })
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime { t: self.t.checked_sub_duration(other)? })
     }
 }
@@ -136,15 +133,8 @@ impl Timespec {
         Timespec::new(t.tv_sec as i64, t.tv_nsec as i64).unwrap()
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
-        // FIXME: const PartialOrd
-        let mut cmp = self.tv_sec - other.tv_sec;
-        if cmp == 0 {
-            cmp = self.tv_nsec.as_inner() as i64 - other.tv_nsec.as_inner() as i64;
-        }
-
-        if cmp >= 0 {
+    pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
+        if self >= other {
             // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
             // to optimize it into a branchless form (see also #75545):
             //
@@ -179,8 +169,7 @@ impl Timespec {
         }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
         let mut secs = self.tv_sec.checked_add_unsigned(other.as_secs())?;
 
         // Nano calculations can't overflow because nanos are <1B which fit
@@ -190,11 +179,10 @@ impl Timespec {
             nsec -= NSEC_PER_SEC as u32;
             secs = secs.checked_add(1)?;
         }
-        Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) })
+        Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) })
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
         let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?;
 
         // Similar to above, nanos can't overflow.
@@ -203,7 +191,7 @@ impl Timespec {
             nsec += NSEC_PER_SEC as i32;
             secs = secs.checked_sub(1)?;
         }
-        Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) })
+        Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) })
     }
 
     #[allow(dead_code)]
diff --git a/library/std/src/sys/pal/unsupported/time.rs b/library/std/src/sys/pal/unsupported/time.rs
index 0c387917044..6d67b538a96 100644
--- a/library/std/src/sys/pal/unsupported/time.rs
+++ b/library/std/src/sys/pal/unsupported/time.rs
@@ -31,22 +31,15 @@ impl SystemTime {
         panic!("time not implemented on this platform")
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        // FIXME: ok_or_else with const closures
-        match self.0.checked_sub(other.0) {
-            Some(duration) => Ok(duration),
-            None => Err(other.0 - self.0),
-        }
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_add(*other)?))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_sub(*other)?))
     }
 }
diff --git a/library/std/src/sys/pal/wasip1/time.rs b/library/std/src/sys/pal/wasip1/time.rs
index 892661b312b..0d8d0b59ac1 100644
--- a/library/std/src/sys/pal/wasip1/time.rs
+++ b/library/std/src/sys/pal/wasip1/time.rs
@@ -43,34 +43,23 @@ impl SystemTime {
         SystemTime(current_time(wasi::CLOCKID_REALTIME))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
+    pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
         SystemTime(Duration::from_nanos(ts))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
-        // FIXME: const TryInto
-        let ns = self.0.as_nanos();
-        if ns <= u64::MAX as u128 { Some(ns as u64) } else { None }
+    pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
+        self.0.as_nanos().try_into().ok()
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        // FIXME: ok_or_else with const closures
-        match self.0.checked_sub(other.0) {
-            Some(duration) => Ok(duration),
-            None => Err(other.0 - self.0),
-        }
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_add(*other)?))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_sub(*other)?))
     }
 }
diff --git a/library/std/src/sys/pal/wasip2/time.rs b/library/std/src/sys/pal/wasip2/time.rs
index 980070e7b85..43489183994 100644
--- a/library/std/src/sys/pal/wasip2/time.rs
+++ b/library/std/src/sys/pal/wasip2/time.rs
@@ -36,34 +36,23 @@ impl SystemTime {
         SystemTime(Duration::new(now.seconds, now.nanoseconds))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
+    pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
         SystemTime(Duration::from_nanos(ts))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
-        // FIXME: const TryInto
-        let ns = self.0.as_nanos();
-        if ns <= u64::MAX as u128 { Some(ns as u64) } else { None }
+    pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
+        self.0.as_nanos().try_into().ok()
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        // FIXME: ok_or_else with const closures
-        match self.0.checked_sub(other.0) {
-            Some(duration) => Ok(duration),
-            None => Err(other.0 - self.0),
-        }
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_add(*other)?))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_sub(*other)?))
     }
 }
diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs
index f8f9a9fd818..0d31b80e56a 100644
--- a/library/std/src/sys/pal/windows/time.rs
+++ b/library/std/src/sys/pal/windows/time.rs
@@ -72,8 +72,7 @@ impl SystemTime {
         }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    const fn from_intervals(intervals: i64) -> SystemTime {
+    fn from_intervals(intervals: i64) -> SystemTime {
         SystemTime {
             t: c::FILETIME {
                 dwLowDateTime: intervals as u32,
@@ -82,13 +81,11 @@ impl SystemTime {
         }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    const fn intervals(&self) -> i64 {
+    fn intervals(&self) -> i64 {
         (self.t.dwLowDateTime as i64) | ((self.t.dwHighDateTime as i64) << 32)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
         let me = self.intervals();
         let other = other.intervals();
         if me >= other {
@@ -98,14 +95,12 @@ impl SystemTime {
         }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?;
         Some(SystemTime::from_intervals(intervals))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?;
         Some(SystemTime::from_intervals(intervals))
     }
@@ -155,18 +150,15 @@ impl Hash for SystemTime {
     }
 }
 
-#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-const fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
-    // FIXME: const TryInto
-    let secs = dur
-        .as_secs()
+fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
+    dur.as_secs()
         .checked_mul(INTERVALS_PER_SEC)?
-        .checked_add(dur.subsec_nanos() as u64 / 100)?;
-    if secs <= i64::MAX as u64 { Some(secs.cast_signed()) } else { None }
+        .checked_add(dur.subsec_nanos() as u64 / 100)?
+        .try_into()
+        .ok()
 }
 
-#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-const fn intervals2dur(intervals: u64) -> Duration {
+fn intervals2dur(intervals: u64) -> Duration {
     Duration::new(intervals / INTERVALS_PER_SEC, ((intervals % INTERVALS_PER_SEC) * 100) as u32)
 }
 
diff --git a/library/std/src/sys/pal/xous/time.rs b/library/std/src/sys/pal/xous/time.rs
index d737416436e..ae8be81c0b7 100644
--- a/library/std/src/sys/pal/xous/time.rs
+++ b/library/std/src/sys/pal/xous/time.rs
@@ -43,22 +43,15 @@ impl SystemTime {
         SystemTime { 0: Duration::from_millis((upper as u64) << 32 | lower as u64) }
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        // FIXME: ok_or_else with const closures
-        match self.0.checked_sub(other.0) {
-            Some(duration) => Ok(duration),
-            None => Err(other.0 - self.0),
-        }
+    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_add(*other)?))
     }
 
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
         Some(SystemTime(self.0.checked_sub(*other)?))
     }
 }
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 84fbb4c2fe4..31187adb6fe 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -551,13 +551,8 @@ impl SystemTime {
     /// println!("{difference:?}");
     /// ```
     #[stable(feature = "time2", since = "1.8.0")]
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn duration_since(&self, earlier: SystemTime) -> Result<Duration, SystemTimeError> {
-        // FIXME: map_err in const
-        match self.0.sub_time(&earlier.0) {
-            Ok(time) => Ok(time),
-            Err(err) => Err(SystemTimeError(err)),
-        }
+    pub fn duration_since(&self, earlier: SystemTime) -> Result<Duration, SystemTimeError> {
+        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
     }
 
     /// Returns the difference from this system time to the
@@ -594,8 +589,7 @@ impl SystemTime {
     /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
     /// otherwise.
     #[stable(feature = "time_checked_add", since = "1.34.0")]
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
+    pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
         self.0.checked_add_duration(&duration).map(SystemTime)
     }
 
@@ -603,15 +597,13 @@ impl SystemTime {
     /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
     /// otherwise.
     #[stable(feature = "time_checked_add", since = "1.34.0")]
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
+    pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
         self.0.checked_sub_duration(&duration).map(SystemTime)
     }
 }
 
 #[stable(feature = "time2", since = "1.8.0")]
-#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Add<Duration> for SystemTime {
+impl Add<Duration> for SystemTime {
     type Output = SystemTime;
 
     /// # Panics
@@ -624,16 +616,14 @@ impl const Add<Duration> for SystemTime {
 }
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const AddAssign<Duration> for SystemTime {
+impl AddAssign<Duration> for SystemTime {
     fn add_assign(&mut self, other: Duration) {
         *self = *self + other;
     }
 }
 
 #[stable(feature = "time2", since = "1.8.0")]
-#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const Sub<Duration> for SystemTime {
+impl Sub<Duration> for SystemTime {
     type Output = SystemTime;
 
     fn sub(self, dur: Duration) -> SystemTime {
@@ -642,8 +632,7 @@ impl const Sub<Duration> for SystemTime {
 }
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
-impl const SubAssign<Duration> for SystemTime {
+impl SubAssign<Duration> for SystemTime {
     fn sub_assign(&mut self, other: Duration) {
         *self = *self - other;
     }
@@ -710,8 +699,7 @@ impl SystemTimeError {
     /// ```
     #[must_use]
     #[stable(feature = "time2", since = "1.8.0")]
-    #[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
-    pub const fn duration(&self) -> Duration {
+    pub fn duration(&self) -> Duration {
         self.0
     }
 }
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/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 8e378e53e51..e4bf33dd8a0 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -48,6 +48,7 @@
     - [\*-apple-visionos](platform-support/apple-visionos.md)
     - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
     - [aarch64-unknown-linux-musl](platform-support/aarch64-unknown-linux-musl.md)
+    - [aarch64-unknown-none*](platform-support/aarch64-unknown-none.md)
     - [aarch64_be-unknown-none-softfloat](platform-support/aarch64_be-unknown-none-softfloat.md)
     - [aarch64_be-unknown-linux-musl](platform-support/aarch64_be-unknown-linux-musl.md)
     - [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md)
@@ -55,7 +56,9 @@
     - [arm-none-eabi](platform-support/arm-none-eabi.md)
       - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)
       - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md)
-      - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md)
+      - [armv7a-none-eabi{,hf}](platform-support/armv7a-none-eabi.md)
+      - [armv7r-none-eabi{,hf}](platform-support/armv7r-none-eabi.md)
+      - [armebv7r-none-eabi{,hf}](platform-support/armebv7r-none-eabi.md)
       - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md)
       - [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md)
       - [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md)
diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md
index 00add2651ae..4caeaa106b4 100644
--- a/src/doc/rustc/src/check-cfg.md
+++ b/src/doc/rustc/src/check-cfg.md
@@ -134,7 +134,7 @@ As of `2025-01-02T`, the list of known names is as follows:
  - `unix`
  - `windows`
 
-> Starting with 1.85.0, the `test` cfg is consider to be a "userspace" config
+> Starting with 1.85.0, the `test` cfg is considered to be a "userspace" config
 > despite being also set by `rustc` and should be managed by the build system itself.
 
 Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 9ad9cb5b526..e5e46f72637 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -149,22 +149,22 @@ target | std | notes
 [`aarch64-apple-ios-sim`](platform-support/apple-ios.md) | ✓ | Apple iOS Simulator on ARM64
 [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
 [`aarch64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | ARM64 Fuchsia
-`aarch64-unknown-none` | * | Bare ARM64, hardfloat
-`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
+[`aarch64-unknown-none`](platform-support/aarch64-unknown-none.md) | * | Bare ARM64, hardfloat
+[`aarch64-unknown-none-softfloat`](platform-support/aarch64-unknown-none.md) | * | Bare ARM64, softfloat
 [`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | ? | ARM64 UEFI
 [`arm-linux-androideabi`](platform-support/android.md) | ✓ | Armv6 Android
 `arm-unknown-linux-musleabi` | ✓ | Armv6 Linux with musl 1.2.3
 `arm-unknown-linux-musleabihf` | ✓ | Armv6 Linux with musl 1.2.3, hardfloat
 [`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ✓ | Arm64EC Windows MSVC
-[`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian
-[`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian, hardfloat
+[`armebv7r-none-eabi`](platform-support/armebv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian
+[`armebv7r-none-eabihf`](platform-support/armebv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian, hardfloat
 [`armv5te-unknown-linux-gnueabi`](platform-support/armv5te-unknown-linux-gnueabi.md) | ✓ | Armv5TE Linux (kernel 4.4+, glibc 2.23)
 `armv5te-unknown-linux-musleabi` | ✓ | Armv5TE Linux with musl 1.2.3
 [`armv7-linux-androideabi`](platform-support/android.md) | ✓ | Armv7-A Android
 `armv7-unknown-linux-gnueabi` | ✓ | Armv7-A Linux (kernel 4.15+, glibc 2.27)
 `armv7-unknown-linux-musleabi` | ✓ | Armv7-A Linux with musl 1.2.3
 `armv7-unknown-linux-musleabihf` | ✓ | Armv7-A Linux with musl 1.2.3, hardfloat
-[`armv7a-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare Armv7-A
+[`armv7a-none-eabi`](platform-support/armv7a-none-eabi.md) | * | Bare Armv7-A
 [`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R
 [`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, hardfloat
 `i586-unknown-linux-gnu` | ✓ | 32-bit Linux (kernel 3.2+, glibc 2.17, original Pentium) [^x86_32-floats-x87]
diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-none.md b/src/doc/rustc/src/platform-support/aarch64-unknown-none.md
new file mode 100644
index 00000000000..7e18e8c157f
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/aarch64-unknown-none.md
@@ -0,0 +1,78 @@
+# `aarch64-unknown-none` and `aarch64-unknown-none-softfloat`
+
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
+
+Bare-metal targets for CPUs in the Armv8-A architecture family, running in AArch64 mode.
+
+For the AArch32 mode carried over from Armv7-A, see
+[`armv7a-none-eabi`](armv7a-none-eabi.md) instead.
+
+Processors in this family include the [Arm Cortex-A35, 53, 76, etc][aarch64-cpus].
+
+[aarch64-cpus]: https://en.wikipedia.org/wiki/Comparison_of_ARM_processors#ARMv8-A
+
+## Target maintainers
+
+[Rust Embedded Devices Working Group Arm Team]
+
+[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
+
+## Target CPU and Target Feature options
+
+All AArch64 processors include an FPU. The difference between the `-none` and
+`-none-softfloat` targets is whether the FPU is used for passing function arguments.
+You may prefer the `-softfloat` target when writing a kernel or interfacing with
+pre-compiled binaries that use the soft-float ABI.
+
+When using the hardfloat targets, the minimum floating-point features assumed
+are those of the `fp-armv8`, which excludes NEON SIMD support. If your
+processor supports a different set of floating-point features than the default
+expectations of `fp-armv8`, then these should also be enabled or disabled as
+needed with `-C target-feature=(+/-)`. It is also possible to tell Rust (or
+LLVM) that you have a specific model of Arm processor, using the
+[`-Ctarget-cpu`][target-cpu] option. Doing so may change the default set of
+target-features enabled.
+
+[target-cpu]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-cpu
+[target-feature]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-feature
+
+## Requirements
+
+These targets are cross-compiled and use static linking.
+
+By default, the `lld` linker included with Rust will be used; however, you may
+want to use the GNU linker instead. This can be obtained for Windows/Mac/Linux
+from the [Arm Developer Website][arm-gnu-toolchain], or possibly from your OS's
+package manager. To use it, add the following to your `.cargo/config.toml`:
+
+```toml
+[target.aarch64-unknown-none]
+linker = "aarch64-none-elf-ld"
+```
+
+The GNU linker can also be used by specifying `aarch64-none-elf-gcc` as the
+linker. This is needed when using GCC's link time optimization.
+
+These targets don't provide a linker script, so you'll need to bring your own
+according to the specific device you are using. Pass
+`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use
+`your_script.ld` during linking.
+
+[arm-gnu-toolchain]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain
+
+## Cross-compilation toolchains and C code
+
+This target supports C code compiled with the `aarch64-none-elf` target
+triple and a suitable `-march` or `-mcpu` flag.
+
+## Start-up and Low-Level Code
+
+The [Rust Embedded Devices Working Group Arm Team] maintain the
+[`aarch64-cpu`] crate, which may be useful for writing bare-metal code using
+this target.
+
+The *TrustedFirmware* group also maintain [Rust crates for this
+target](https://github.com/ArmFirmwareCrates).
+
+[`aarch64-cpu`]: https://docs.rs/aarch64-cpu
diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md
index 9732df4be7f..aaa80e42971 100644
--- a/src/doc/rustc/src/platform-support/arm-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md
@@ -12,10 +12,10 @@ their own document.
 ### Tier 2 Target List
 
 - Arm A-Profile Architectures
-  - `armv7a-none-eabi`
+  - [`armv7a-none-eabi`](armv7a-none-eabi.md)
 - Arm R-Profile Architectures
   - [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md)
-  - [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armv7r-none-eabi.md)
+  - [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armebv7r-none-eabi.md)
 - Arm M-Profile Architectures
   - [`thumbv6m-none-eabi`](thumbv6m-none-eabi.md)
   - [`thumbv7m-none-eabi`](thumbv7m-none-eabi.md)
@@ -28,7 +28,7 @@ their own document.
 ### Tier 3 Target List
 
 - Arm A-Profile Architectures
-  - `armv7a-none-eabihf`
+  - [`armv7a-none-eabihf`](armv7a-none-eabi.md)
 - Arm R-Profile Architectures
   - [`armv8r-none-eabihf`](armv8r-none-eabihf.md)
 - Arm M-Profile Architectures
diff --git a/src/doc/rustc/src/platform-support/armebv7r-none-eabi.md b/src/doc/rustc/src/platform-support/armebv7r-none-eabi.md
new file mode 100644
index 00000000000..3e90319c373
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/armebv7r-none-eabi.md
@@ -0,0 +1,55 @@
+# `armebv7r-none-eabi` and `armebv7r-none-eabihf`
+
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
+
+Bare-metal target for CPUs in the Armv7-R architecture family running in Big
+Endian mode. These processors support dual ARM/Thumb mode, with ARM mode as
+the default.
+
+**NOTE:** You should almost always prefer the [little-endian
+versions](armv7r-none-eabi.md) of these target. Big Endian Arm systems are
+highly unusual.
+
+Processors in this family include the [Arm Cortex-R4, 5, 7, and 8][cortex-r].
+
+See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
+`arm-none-eabi` targets.
+
+[cortex-r]: https://en.wikipedia.org/wiki/ARM_Cortex-R
+
+## Target maintainers
+
+[@chrisnc](https://github.com/chrisnc)
+
+## Requirements
+
+Note that some variants of the Cortex-R have both big-endian instructions and
+data. This configuration is known as BE-32, while data-only big-endianness is
+known as BE-8. To build programs for BE-32 processors, the GNU linker must be
+used with the `-mbe32` option. See [ARM Cortex-R Series Programmer's Guide:
+Endianness][endianness] for more details about different endian modes.
+
+When using the hardfloat targets, the minimum floating-point features assumed
+are those of the `vfpv3-d16`, which includes single- and double-precision, with
+16 double-precision registers. This floating-point unit appears in Cortex-R4F
+and Cortex-R5F processors. See [VFP in the Cortex-R processors][vfp]
+for more details on the possible FPU variants.
+
+If your processor supports a different set of floating-point features than the
+default expectations of `vfpv3-d16`, then these should also be enabled or
+disabled as needed with `-C target-feature=(+/-)`.
+
+[endianness]: https://developer.arm.com/documentation/den0042/a/Coding-for-Cortex-R-Processors/Endianness
+
+[vfp]: https://developer.arm.com/documentation/den0042/a/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/VFP-in-the-Cortex-R-processors
+
+## Start-up and Low-Level Code
+
+The [Rust Embedded Devices Working Group Arm Team] maintain the [`cortex-ar`]
+and [`cortex-r-rt`] crates, which may be useful for writing bare-metal code
+using this target. Those crates include several examples which run in QEMU and
+build using these targets.
+
+[`cortex-ar`]: https://docs.rs/cortex-ar
+[`cortex-r-rt`]: https://docs.rs/cortex-r-rt
diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
index 56f919e2a12..c6d88762fb1 100644
--- a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
@@ -1,6 +1,7 @@
 # armv4t-none-eabi / thumbv4t-none-eabi
 
-Tier 3
+* **Tier:  3**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 These two targets are part of the [`arm-none-eabi`](arm-none-eabi.md) target
 group, and all the information there applies.
diff --git a/src/doc/rustc/src/platform-support/armv5te-none-eabi.md b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md
index 22287972b7e..e9f34d4ede8 100644
--- a/src/doc/rustc/src/platform-support/armv5te-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md
@@ -1,6 +1,7 @@
 # `armv5te-none-eabi`
 
-**Tier: 3**
+* **Tier: 3**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for any cpu in the Armv5TE architecture family, supporting
 ARM/Thumb code interworking (aka `A32`/`T32`), with `A32` code as the default code
diff --git a/src/doc/rustc/src/platform-support/armv7a-none-eabi.md b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md
new file mode 100644
index 00000000000..3dadda86a5f
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md
@@ -0,0 +1,70 @@
+# `armv7a-none-eabi` and `armv7a-none-eabihf`
+
+* **Tier: 2** for `armv7a-none-eabi`
+* **Tier: 3** for `armv7a-none-eabihf`
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
+
+Bare-metal target for CPUs in the Armv7-A architecture family, supporting
+dual ARM/Thumb mode, with ARM mode as the default.
+
+Note, this is for processors running in AArch32 mode. For the AArch64 mode
+added in Armv8-A, see [`aarch64-unknown-none`](aarch64-unknown-none.md) instead.
+
+Processors in this family include the [Arm Cortex-A5, 8, 32, etc][cortex-a].
+
+See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
+`arm-none-eabi` targets.
+
+[cortex-a]: https://en.wikipedia.org/wiki/ARM_Cortex-A
+
+## Target maintainers
+
+[Rust Embedded Devices Working Group Arm Team]
+
+[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
+
+## Requirements
+
+Almost all Armv7-A processors include an FPU (a VFPv3 or a VFPv4). The
+difference between the `-eabi` and `-eabihf` targets is whether the FPU is
+used for passing function arguments. You may prefer the `-eabi` soft-float
+target when the processor does not have a floating point unit or the compiled
+code should not use the floating point unit.
+
+When using the hardfloat targets, the minimum floating-point features assumed
+are those of the VFPv3-D16, which includes single- and double-precision, with
+16 double-precision registers. This floating-point unit appears in Cortex-A8
+and Cortex-A9 processors. See [VFP in the Cortex-A processors][vfp] for more
+details on the possible FPU variants.
+
+If your processor supports a different set of floating-point features than the
+default expectations of VFPv3-D16, then these should also be enabled or
+disabled as needed with `-C target-feature=(+/-)`.
+
+In general, the following four combinations are possible:
+
+- VFPv3-D16, target feature `+vfp3` and `-d32`
+- VFPv3-D32, target feature `+vfp3` and `+d32`
+- VFPv4-D16, target feature `+vfp4` and `-d32`
+- VFPv4-D32, target feature `+vfp4` and `+d32`
+
+An Armv7-A processor may optionally include a NEON hardware unit which
+provides Single Instruction Multiple Data (SIMD) operations. The
+implementation of this unit implies VFPv3-D32. The target feature `+neon` may
+be added to inform the compiler about the availability of NEON.
+
+You can refer to the [arm-none-eabi](arm-none-eabi.md) documentation for a
+generic guide on target feature and target CPU specification and how to enable
+and disable them via `.cargo/config.toml` file.
+
+[vfp]: https://developer.arm.com/documentation/den0013/0400/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/ARM-VFP
+
+## Start-up and Low-Level Code
+
+The [Rust Embedded Devices Working Group Arm Team] maintain the [`cortex-ar`]
+and [`cortex-a-rt`] crates, which may be useful for writing bare-metal code
+using this target. The [`cortex-ar` repository](https://github.com/rust-embedded/cortex-ar)
+includes several examples which run in QEMU and build using these targets.
+
+[`cortex-ar`]: https://docs.rs/cortex-ar
+[`cortex-a-rt`]: https://docs.rs/cortex-a-rt
diff --git a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md
index 88b2689dcf0..c1252b4a4bf 100644
--- a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md
@@ -1,14 +1,13 @@
-# `arm(eb)?v7r-none-eabi(hf)?`
+# `armv7r-none-eabi` and `armv7r-none-eabihf`
 
-**Tier: 2**
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for CPUs in the Armv7-R architecture family, supporting
 dual ARM/Thumb mode, with ARM mode as the default.
 
 Processors in this family include the [Arm Cortex-R4, 5, 7, and 8][cortex-r].
 
-The `eb` versions of this target generate code for big-endian processors.
-
 See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
 `arm-none-eabi` targets.
 
@@ -17,15 +16,11 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
 ## Target maintainers
 
 [@chrisnc](https://github.com/chrisnc)
+[Rust Embedded Devices Working Group Arm Team]
 
-## Requirements
+[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
 
-When using the big-endian version of this target, note that some variants of
-the Cortex-R have both big-endian instructions and data. This configuration is
-known as BE-32, while data-only big-endianness is known as BE-8. To build
-programs for BE-32 processors, the GNU linker must be used with the `-mbe32`
-option. See [ARM Cortex-R Series Programmer's Guide: Endianness][endianness]
-for more details about different endian modes.
+## Requirements
 
 When using the hardfloat targets, the minimum floating-point features assumed
 are those of the `vfpv3-d16`, which includes single- and double-precision, with
@@ -41,7 +36,12 @@ disabled as needed with `-C target-feature=(+/-)`.
 
 [vfp]: https://developer.arm.com/documentation/den0042/a/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/VFP-in-the-Cortex-R-processors
 
-## Cross-compilation toolchains and C code
+## Start-up and Low-Level Code
+
+The [Rust Embedded Devices Working Group Arm Team] maintain the [`cortex-ar`]
+and [`cortex-r-rt`] crates, which may be useful for writing bare-metal code
+using this target. Those crates include several examples which run in QEMU and
+build using these targets.
 
-This target supports C code compiled with the `arm-none-eabi` target triple and
-`-march=armv7-r` or a suitable `-mcpu` flag.
+[`cortex-ar`]: https://docs.rs/cortex-ar
+[`cortex-r-rt`]: https://docs.rs/cortex-r-rt
diff --git a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md
index 569d8802ebe..0d5a36c3ee2 100644
--- a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md
+++ b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md
@@ -1,6 +1,7 @@
 # `armv8r-none-eabihf`
 
-**Tier: 3**
+* **Tier: 3**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for CPUs in the Armv8-R architecture family, supporting
 dual ARM/Thumb mode, with ARM mode as the default.
@@ -17,6 +18,9 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
 ## Target maintainers
 
 [@chrisnc](https://github.com/chrisnc)
+[Rust Embedded Devices Working Group Arm Team]
+
+[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
 
 ## Requirements
 
@@ -34,7 +38,14 @@ Technical Reference Manual for more details.
 
 [fpu]: https://developer.arm.com/documentation/100026/0104/Advanced-SIMD-and-floating-point-support/About-the-Advanced-SIMD-and-floating-point-support
 
-## Cross-compilation toolchains and C code
-
-This target supports C code compiled with the `arm-none-eabi` target triple and
-`-march=armv8-r` or a suitable `-mcpu` flag.
+### Table of supported CPUs for `armv8r-none-eabihf`
+
+| CPU         | FPU | Neon | Target CPU       | Target Features    |
+|:----------- | --- |:---- |:---------------- |:------------------ |
+| Any         | SP  | No   | None             | None               |
+| Cortex-R52  | SP  | No   | `cortex-r52`     | `-fp64,-d32,-neon` |
+| Cortex-R52  | DP  | No   | `cortex-r52`     | `-neon`            |
+| Cortex-R52  | DP  | Yes  | `cortex-r52`     | None               |
+| Cortex-R52+ | SP  | No   | `cortex-r52plus` | `-fp64,-d32,-neon` |
+| Cortex-R52+ | DP  | No   | `cortex-r52plus` | `-neon`            |
+| Cortex-R52+ | DP  | Yes  | `cortex-r52plus` | None               |
diff --git a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
index 746b8443547..d4bd0b0945a 100644
--- a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
@@ -1,6 +1,7 @@
 # `thumbv6m-none-eabi`
 
-**Tier: 2**
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for CPUs in the [Armv6-M] architecture family, supporting a
 subset of the [T32 ISA][t32-isa].
@@ -26,7 +27,7 @@ only option because there is no FPU support in [Armv6-M].
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
+[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
index 12e28265678..98dcf9bd396 100644
--- a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
@@ -1,6 +1,7 @@
 # `thumbv7em-none-eabi` and `thumbv7em-none-eabihf`
 
-**Tier: 2**
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for CPUs in the [Armv7E-M] architecture family, supporting a
 subset of the [T32 ISA][t32-isa].
@@ -21,7 +22,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
+[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
index 03324b341d0..d8f3970c8bf 100644
--- a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
@@ -1,6 +1,7 @@
 # `thumbv7m-none-eabi`
 
-**Tier: 2**
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for CPUs in the [Armv7-M] architecture family, supporting a
 subset of the [T32 ISA][t32-isa].
@@ -22,7 +23,7 @@ only option because there is no FPU support in [Armv7-M].
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
+[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
index 4a92e856466..b16d450275d 100644
--- a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
@@ -1,6 +1,7 @@
 # `thumbv8m.base-none-eabi`
 
-**Tier: 2**
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for CPUs in the Baseline [Armv8-M] architecture family,
 supporting a subset of the [T32 ISA][t32-isa].
@@ -22,7 +23,7 @@ only option because there is no FPU support in [Armv8-M] Baseline.
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
+[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
index 9f85d08fa0a..a2d515d07ea 100644
--- a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
@@ -1,6 +1,7 @@
 # `thumbv8m.main-none-eabi` and `thumbv8m.main-none-eabihf`
 
-**Tier: 2**
+* **Tier: 2**
+* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
 
 Bare-metal target for CPUs in the Mainline [Armv8-M] architecture family,
 supporting a subset of the [T32 ISA][t32-isa].
@@ -25,7 +26,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
+[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
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/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 93932936a2e..5ccacafea01 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1256,7 +1256,10 @@ pub(crate) fn clean_impl_item<'tcx>(
             })),
             hir::ImplItemKind::Fn(ref sig, body) => {
                 let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body));
-                let defaultness = cx.tcx.defaultness(impl_.owner_id);
+                let defaultness = match impl_.impl_kind {
+                    hir::ImplItemImplKind::Inherent { .. } => hir::Defaultness::Final,
+                    hir::ImplItemImplKind::Trait { defaultness, .. } => defaultness,
+                };
                 MethodItem(m, Some(defaultness))
             }
             hir::ImplItemKind::Type(hir_ty) => {
@@ -1295,12 +1298,14 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
             simplify::move_bounds_to_generic_parameters(&mut generics);
 
             match assoc_item.container {
-                ty::AssocItemContainer::Impl => ImplAssocConstItem(Box::new(Constant {
-                    generics,
-                    kind: ConstantKind::Extern { def_id: assoc_item.def_id },
-                    type_: ty,
-                })),
-                ty::AssocItemContainer::Trait => {
+                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
+                    ImplAssocConstItem(Box::new(Constant {
+                        generics,
+                        kind: ConstantKind::Extern { def_id: assoc_item.def_id },
+                        type_: ty,
+                    }))
+                }
+                ty::AssocContainer::Trait => {
                     if tcx.defaultness(assoc_item.def_id).has_value() {
                         ProvidedAssocConstItem(Box::new(Constant {
                             generics,
@@ -1318,10 +1323,10 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
 
             if has_self {
                 let self_ty = match assoc_item.container {
-                    ty::AssocItemContainer::Impl => {
+                    ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
                         tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity()
                     }
-                    ty::AssocItemContainer::Trait => tcx.types.self_param,
+                    ty::AssocContainer::Trait => tcx.types.self_param,
                 };
                 let self_param_ty =
                     tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
@@ -1338,13 +1343,13 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
             }
 
             let provided = match assoc_item.container {
-                ty::AssocItemContainer::Impl => true,
-                ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(),
+                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
+                ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
             };
             if provided {
                 let defaultness = match assoc_item.container {
-                    ty::AssocItemContainer::Impl => Some(assoc_item.defaultness(tcx)),
-                    ty::AssocItemContainer::Trait => None,
+                    ty::AssocContainer::TraitImpl(_) => Some(assoc_item.defaultness(tcx)),
+                    ty::AssocContainer::InherentImpl | ty::AssocContainer::Trait => None,
                 };
                 MethodItem(item, defaultness)
             } else {
@@ -1375,7 +1380,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
             }
 
             let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
-            if let ty::AssocItemContainer::Trait = assoc_item.container {
+            if let ty::AssocContainer::Trait = assoc_item.container {
                 let bounds = tcx.explicit_item_bounds(assoc_item.def_id).iter_identity_copied();
                 predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
             }
@@ -1386,7 +1391,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
             );
             simplify::move_bounds_to_generic_parameters(&mut generics);
 
-            if let ty::AssocItemContainer::Trait = assoc_item.container {
+            if let ty::AssocContainer::Trait = assoc_item.container {
                 // Move bounds that are (likely) directly attached to the associated type
                 // from the where-clause to the associated type.
                 // There is no guarantee that this is what the user actually wrote but we have
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index dcd67cb7ebc..bd3f4e9a6f2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -690,16 +690,13 @@ impl Item {
                 // rustc's `is_const_fn` returns `true` for associated functions that have an `impl const` parent
                 // or that have a `const trait` parent. Do not display those as `const` in rustdoc because we
                 // won't be printing correct syntax plus the syntax is unstable.
-                match tcx.opt_associated_item(def_id) {
-                    Some(ty::AssocItem {
-                        container: ty::AssocItemContainer::Impl,
-                        trait_item_def_id: Some(_),
-                        ..
-                    })
-                    | Some(ty::AssocItem { container: ty::AssocItemContainer::Trait, .. }) => {
-                        hir::Constness::NotConst
-                    }
-                    None | Some(_) => hir::Constness::Const,
+                if let Some(assoc) = tcx.opt_associated_item(def_id)
+                    && let ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) =
+                        assoc.container
+                {
+                    hir::Constness::NotConst
+                } else {
+                    hir::Constness::Const
                 }
             } else {
                 hir::Constness::NotConst
@@ -779,17 +776,13 @@ impl Item {
             | RequiredAssocTypeItem(..)
             | RequiredMethodItem(..)
             | MethodItem(..) => {
-                let assoc_item = tcx.associated_item(def_id);
-                let is_trait_item = match assoc_item.container {
-                    ty::AssocItemContainer::Trait => true,
-                    ty::AssocItemContainer::Impl => {
-                        // Trait impl items always inherit the impl's visibility --
-                        // we don't want to show `pub`.
-                        tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
+                match tcx.associated_item(def_id).container {
+                    // Trait impl items always inherit the impl's visibility --
+                    // we don't want to show `pub`.
+                    ty::AssocContainer::Trait | ty::AssocContainer::TraitImpl(_) => {
+                        return None;
                     }
-                };
-                if is_trait_item {
-                    return None;
+                    ty::AssocContainer::InherentImpl => {}
                 }
             }
             _ => {}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 719b7c6ab89..0da42f38251 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -210,7 +210,7 @@ impl UrlFragment {
             &UrlFragment::Item(def_id) => {
                 let kind = match tcx.def_kind(def_id) {
                     DefKind::AssocFn => {
-                        if tcx.defaultness(def_id).has_value() {
+                        if tcx.associated_item(def_id).defaultness(tcx).has_value() {
                             "method."
                         } else {
                             "tymethod."
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
index 23e7c7251cf..49cd2671dc0 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{
-    AmbigArg, Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty,
+    AmbigArg, Expr, ExprKind, ForeignItem, HirId, ImplItem, ImplItemImplKind, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyCtxt;
@@ -177,7 +177,9 @@ impl LateLintPass<'_> for DisallowedMacros {
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &ImplItem<'_>) {
         self.check(cx, item.span, None);
-        self.check(cx, item.vis_span, None);
+        if let ImplItemImplKind::Inherent { vis_span, .. } = item.impl_kind {
+            self.check(cx, vis_span, None);
+        }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
index f8e8f5544b9..e25611d4881 100644
--- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_errors::{Applicability, MultiSpan};
-use rustc_hir::def_id::{DefId, DefIdSet};
-use rustc_hir::hir_id::OwnerId;
+use rustc_hir::def_id::DefIdSet;
 use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind, Node, TraitRef};
 use rustc_lint::LateContext;
 use rustc_span::Span;
@@ -19,7 +18,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored
             of_trait: Some(of_trait),
             ..
         }) = &parent_item.kind
-        && let Some(did) = trait_item_def_id_of_impl(cx, item.owner_id)
+        && let Some(did) = cx.tcx.trait_item_of(item.owner_id)
         && !is_from_ignored_trait(&of_trait.trait_ref, ignored_traits)
     {
         let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id);
@@ -87,11 +86,6 @@ impl RenamedFnArgs {
     }
 }
 
-/// Get the [`trait_item_def_id`](ImplItemRef::trait_item_def_id) of a relevant impl item.
-fn trait_item_def_id_of_impl(cx: &LateContext<'_>, target: OwnerId) -> Option<DefId> {
-    cx.tcx.associated_item(target).trait_item_def_id
-}
-
 fn is_from_ignored_trait(of_trait: &TraitRef<'_>, ignored_traits: &DefIdSet) -> bool {
     of_trait
         .trait_def_id()
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index ba1ad599e11..bee3b19b597 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl,
-    FnRetTy, GenericBound, ImplItem, Item, Node, OpaqueTy, TraitRef, Ty, TyKind,
+    FnRetTy, GenericBound, Node, OpaqueTy, TraitRef, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
@@ -60,8 +60,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
             && let ExprKind::Block(block, _) = body.value.kind
             && block.stmts.is_empty()
             && let Some(closure_body) = desugared_async_block(cx, block)
-            && let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
-                cx.tcx.hir_node_by_def_id(fn_def_id)
+            && let Some(vis_span_opt) = match cx.tcx.hir_node_by_def_id(fn_def_id) {
+                Node::Item(item) => Some(Some(item.vis_span)),
+                Node::ImplItem(impl_item) => Some(impl_item.vis_span()),
+                _ => None,
+            }
             && !span.from_expansion()
         {
             let header_span = span.with_hi(ret_ty.span.hi());
@@ -72,7 +75,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
                 header_span,
                 "this function can be simplified using the `async fn` syntax",
                 |diag| {
-                    if let Some(vis_snip) = vis_span.get_source_text(cx)
+                    if let Some(vis_span) = vis_span_opt
+                        && let Some(vis_snip) = vis_span.get_source_text(cx)
                         && let Some(header_snip) = header_span.get_source_text(cx)
                         && let Some(ret_pos) = position_before_rarrow(&header_snip)
                         && let Some((_, ret_snip)) = suggested_ret(cx, output)
diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
index dbce29a8631..6258e408217 100644
--- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
+++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
@@ -5,8 +5,8 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{Visitor, walk_item, walk_trait_item};
 use rustc_hir::{
-    GenericParamKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, TraitItem,
-    UsePath,
+    GenericParamKind, HirId, Impl, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind, ItemLocalId, Node, Pat,
+    PatKind, TraitItem, UsePath,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
@@ -256,7 +256,7 @@ fn is_not_in_trait_impl(cx: &LateContext<'_>, pat: &Pat<'_>, ident: Ident) -> bo
 }
 
 fn get_param_name(impl_item: &ImplItem<'_>, cx: &LateContext<'_>, ident: Ident) -> Option<Symbol> {
-    if let Some(trait_item_def_id) = impl_item.trait_item_def_id {
+    if let ImplItemImplKind::Trait { trait_item_def_id: Ok(trait_item_def_id), .. } = impl_item.impl_kind {
         let trait_param_names = cx.tcx.fn_arg_idents(trait_item_def_id);
 
         let ImplItemKind::Fn(_, body_id) = impl_item.kind else {
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index a6be7581c9a..a63ad978626 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -158,13 +158,23 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
         let mir = cx.tcx.optimized_mir(def_id);
 
         if let Ok(()) = is_min_const_fn(cx, mir, self.msrv)
-            && let hir::Node::Item(hir::Item { vis_span, .. }) | hir::Node::ImplItem(hir::ImplItem { vis_span, .. }) =
-                cx.tcx.hir_node_by_def_id(def_id)
+            && let node = cx.tcx.hir_node_by_def_id(def_id)
+            && let Some((item_span, vis_span_opt)) = match node {
+                hir::Node::Item(item) => Some((item.span, Some(item.vis_span))),
+                hir::Node::ImplItem(impl_item) => Some((impl_item.span, impl_item.vis_span())),
+                _ => None,
+            }
         {
-            let suggestion = if vis_span.is_empty() { "const " } else { " const" };
+            let (sugg_span, suggestion) = if let Some(vis_span) = vis_span_opt
+                && !vis_span.is_empty()
+            {
+                (vis_span.shrink_to_hi(), " const")
+            } else {
+                (item_span.shrink_to_lo(), "const ")
+            };
             span_lint_and_then(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`", |diag| {
                 diag.span_suggestion_verbose(
-                    vis_span.shrink_to_hi(),
+                    sugg_span,
                     "make the function `const`",
                     suggestion,
                     Applicability::MachineApplicable,
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 7772051eb5c..39b5964bd87 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -16,7 +16,7 @@ use rustc_hir::Attribute;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::Visibility;
+use rustc_middle::ty::{AssocContainer, Visibility};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::symbol::kw;
@@ -246,12 +246,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
         // If the method is an impl for a trait, don't doc.
-        if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) {
-            if cx.tcx.impl_trait_ref(cid).is_some() {
+        match cx.tcx.associated_item(impl_item.owner_id).container {
+            AssocContainer::Trait | AssocContainer::TraitImpl(_) => {
                 note_prev_span_then_ret!(self.prev_span, impl_item.span);
-            }
-        } else {
-            note_prev_span_then_ret!(self.prev_span, impl_item.span);
+            },
+            AssocContainer::InherentImpl => {}
         }
 
         let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 28555a61090..6323e728666 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -3,7 +3,7 @@ use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, Attribute, find_attr};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::AssocItemContainer;
+use rustc_middle::ty::AssocContainer;
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
@@ -166,8 +166,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
         let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
         let container_id = assoc_item.container_id(cx.tcx);
         let trait_def_id = match assoc_item.container {
-            AssocItemContainer::Trait => Some(container_id),
-            AssocItemContainer::Impl => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
+            AssocContainer::Trait => Some(container_id),
+            AssocContainer::TraitImpl(_) => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
+            AssocContainer::InherentImpl => None,
         };
 
         if let Some(trait_def_id) = trait_def_id
diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
index 9cc93bf0653..8e9400e9d58 100644
--- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
@@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
                 .tcx
                 .associated_items(item.owner_id)
                 .in_definition_order()
-                .filter_map(|assoc_item| assoc_item.trait_item_def_id)
+                .filter_map(|assoc_item| assoc_item.expect_trait_impl().ok())
                 .collect();
 
             for assoc in cx
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 809a6728e12..c4cad592e36 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -248,7 +248,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
                         .tcx
                         .impl_trait_ref(item.owner_id)
                         .map(EarlyBinder::instantiate_identity)
-                    && let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id
+                    && let Some(trait_item_id) = cx.tcx.trait_item_of(owner_id)
                 {
                     (
                         trait_item_id,
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index aeda864b7eb..8252e6d4869 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -151,8 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             // trait, not in the impl of the trait.
             let trait_method = cx
                 .tcx
-                .associated_item(impl_item.owner_id)
-                .trait_item_def_id
+                .trait_item_of(impl_item.owner_id)
                 .expect("impl method matches a trait method");
             let trait_method_sig = cx.tcx.fn_sig(trait_method).instantiate_identity();
             let trait_method_sig = cx.tcx.instantiate_bound_regions_with_erased(trait_method_sig);
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index c4a759e919b..1a25c90d735 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -19,7 +19,7 @@ use rustc_ast::token::CommentKind;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
-    ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
+    ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
     TraitImplHeader, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
 };
 use rustc_lint::{EarlyContext, LateContext, LintContext};
@@ -280,16 +280,17 @@ fn trait_item_search_pat(item: &TraitItem<'_>) -> (Pat, Pat) {
 }
 
 fn impl_item_search_pat(item: &ImplItem<'_>) -> (Pat, Pat) {
-    let (start_pat, end_pat) = match &item.kind {
+    let (mut start_pat, end_pat) = match &item.kind {
         ImplItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")),
         ImplItemKind::Type(..) => (Pat::Str("type"), Pat::Str(";")),
         ImplItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")),
     };
-    if item.vis_span.is_empty() {
-        (start_pat, end_pat)
-    } else {
-        (Pat::Str("pub"), end_pat)
-    }
+    if let ImplItemImplKind::Inherent { vis_span, .. } = item.impl_kind
+        && !vis_span.is_empty()
+    {
+        start_pat = Pat::Str("pub");
+    };
+    (start_pat, end_pat)
 }
 
 fn field_def_search_pat(def: &FieldDef<'_>) -> (Pat, Pat) {
@@ -313,21 +314,20 @@ fn variant_search_pat(v: &Variant<'_>) -> (Pat, Pat) {
 }
 
 fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirId) -> (Pat, Pat) {
-    let (start_pat, end_pat) = match kind {
+    let (mut start_pat, end_pat) = match kind {
         FnKind::ItemFn(.., header) => (fn_header_search_pat(*header), Pat::Str("")),
         FnKind::Method(.., sig) => (fn_header_search_pat(sig.header), Pat::Str("")),
         FnKind::Closure => return (Pat::Str(""), expr_search_pat(tcx, body.value).1),
     };
-    let start_pat = match tcx.hir_node(hir_id) {
-        Node::Item(Item { vis_span, .. }) | Node::ImplItem(ImplItem { vis_span, .. }) => {
-            if vis_span.is_empty() {
-                start_pat
-            } else {
-                Pat::Str("pub")
+    match tcx.hir_node(hir_id) {
+        Node::Item(Item { vis_span, .. })
+        | Node::ImplItem(ImplItem { impl_kind: ImplItemImplKind::Inherent { vis_span, .. }, .. }) => {
+            if !vis_span.is_empty() {
+                start_pat = Pat::Str("pub")
             }
         },
-        Node::TraitItem(_) => start_pat,
-        _ => Pat::Str(""),
+        Node::ImplItem(_) | Node::TraitItem(_) => {},
+        _ => start_pat = Pat::Str(""),
     };
     (start_pat, end_pat)
 }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index e1077bdf4b1..120ab2e717d 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -3244,8 +3244,8 @@ pub fn get_path_from_caller_to_method_type<'tcx>(
     let assoc_item = tcx.associated_item(method);
     let def_id = assoc_item.container_id(tcx);
     match assoc_item.container {
-        rustc_ty::AssocItemContainer::Trait => get_path_to_callee(tcx, from, def_id),
-        rustc_ty::AssocItemContainer::Impl => {
+        rustc_ty::AssocContainer::Trait => get_path_to_callee(tcx, from, def_id),
+        rustc_ty::AssocContainer::InherentImpl | rustc_ty::AssocContainer::TraitImpl(_) => {
             let ty = tcx.type_of(def_id).instantiate_identity();
             get_path_to_ty(tcx, from, ty, args)
         },
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/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/src/tools/tidy/src/fluent_lowercase.rs b/src/tools/tidy/src/fluent_lowercase.rs
new file mode 100644
index 00000000000..13f0319909e
--- /dev/null
+++ b/src/tools/tidy/src/fluent_lowercase.rs
@@ -0,0 +1,64 @@
+//! Checks that the error messages start with a lowercased letter (except when allowed to).
+
+use std::path::Path;
+
+use fluent_syntax::ast::{Entry, Message, PatternElement};
+
+use crate::walk::{filter_dirs, walk};
+
+#[rustfmt::skip]
+const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[
+    // tidy-alphabetical-start
+    "ABI",
+    "ABIs",
+    "ADT",
+    "C",
+    "CGU",
+    "Ferris",
+    "MIR",
+    "OK",
+    "Rust",
+    "VS", // VS Code
+    // tidy-alphabetical-end
+];
+
+fn filter_fluent(path: &Path) -> bool {
+    if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
+}
+
+fn is_allowed_capitalized_word(msg: &str) -> bool {
+    ALLOWED_CAPITALIZED_WORDS.iter().any(|word| {
+        msg.strip_prefix(word)
+            .map(|tail| tail.chars().next().map(|c| c == '-' || c.is_whitespace()).unwrap_or(true))
+            .unwrap_or_default()
+    })
+}
+
+fn check_lowercase(filename: &str, contents: &str, bad: &mut bool) {
+    let (Ok(parse) | Err((parse, _))) = fluent_syntax::parser::parse(contents);
+
+    for entry in &parse.body {
+        if let Entry::Message(msg) = entry
+            && let Message { value: Some(pattern), .. } = msg
+            && let [first_pattern, ..] = &pattern.elements[..]
+            && let PatternElement::TextElement { value } = first_pattern
+            && value.chars().next().is_some_and(char::is_uppercase)
+            && !is_allowed_capitalized_word(value)
+        {
+            tidy_error!(
+                bad,
+                "{filename}: message `{value}` starts with an uppercase letter. Fix it or add it to `ALLOWED_CAPITALIZED_WORDS`"
+            );
+        }
+    }
+}
+
+pub fn check(path: &Path, bad: &mut bool) {
+    walk(
+        path,
+        |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
+        &mut |ent, contents| {
+            check_lowercase(ent.path().to_str().unwrap(), contents, bad);
+        },
+    );
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 37713cbf75e..2a9c3963d2d 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -257,6 +257,7 @@ pub mod extra_checks;
 pub mod features;
 pub mod filenames;
 pub mod fluent_alphabetical;
+pub mod fluent_lowercase;
 pub mod fluent_period;
 mod fluent_used;
 pub mod gcc_submodule;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index bfe30258915..f9e82341b7a 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -121,6 +121,7 @@ fn main() {
         check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose, &ci_info);
         check!(fluent_alphabetical, &compiler_path, bless);
         check!(fluent_period, &compiler_path);
+        check!(fluent_lowercase, &compiler_path);
         check!(target_policy, &root_path);
         check!(gcc_submodule, &root_path, &compiler_path);
 
diff --git a/src/version b/src/version
index 6979a6c0661..7f229af9647 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.91.0
+1.92.0
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/cffi/c-variadic-inline.rs b/tests/codegen-llvm/cffi/c-variadic-inline.rs
new file mode 100644
index 00000000000..369b7e571ca
--- /dev/null
+++ b/tests/codegen-llvm/cffi/c-variadic-inline.rs
@@ -0,0 +1,47 @@
+//@ compile-flags: -C opt-level=3
+#![feature(c_variadic)]
+
+// Test that the inline attributes are accepted on C-variadic functions.
+//
+// Currently LLVM is unable to inline C-variadic functions, but that is valid because despite
+// the name even `#[inline(always)]` is just a hint.
+
+#[inline(always)]
+unsafe extern "C" fn inline_always(mut ap: ...) -> u32 {
+    ap.arg::<u32>()
+}
+
+#[inline]
+unsafe extern "C" fn inline(mut ap: ...) -> u32 {
+    ap.arg::<u32>()
+}
+
+#[inline(never)]
+unsafe extern "C" fn inline_never(mut ap: ...) -> u32 {
+    ap.arg::<u32>()
+}
+
+#[cold]
+unsafe extern "C" fn cold(mut ap: ...) -> u32 {
+    ap.arg::<u32>()
+}
+
+#[unsafe(no_mangle)]
+#[inline(never)]
+fn helper() {
+    // CHECK-LABEL: helper
+    // CHECK-LABEL: call c_variadic_inline::inline_always
+    // CHECK-LABEL: call c_variadic_inline::inline
+    // CHECK-LABEL: call c_variadic_inline::inline_never
+    // CHECK-LABEL: call c_variadic_inline::cold
+    unsafe {
+        inline_always(1);
+        inline(2);
+        inline_never(3);
+        cold(4);
+    }
+}
+
+fn main() {
+    helper()
+}
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/ui/c-variadic/naked.rs b/tests/ui/c-variadic/naked.rs
new file mode 100644
index 00000000000..46b59395485
--- /dev/null
+++ b/tests/ui/c-variadic/naked.rs
@@ -0,0 +1,40 @@
+//@ run-pass
+//@ only-x86_64
+//@ only-linux
+#![feature(c_variadic)]
+
+#[repr(C)]
+#[derive(Debug, PartialEq)]
+struct Data(i32, f64);
+
+#[unsafe(naked)]
+unsafe extern "C" fn c_variadic(_: ...) -> Data {
+    // This assembly was generated with GCC, because clang/LLVM is unable to
+    // optimize out the spilling of all registers to the stack.
+    core::arch::naked_asm!(
+        "        sub     rsp, 96",
+        "        mov     QWORD PTR [rsp-88], rdi",
+        "        test    al, al",
+        "        je      .L7",
+        "        movaps  XMMWORD PTR [rsp-40], xmm0",
+        ".L7:",
+        "        lea     rax, [rsp+104]",
+        "        mov     rcx, QWORD PTR [rsp-40]",
+        "        mov     DWORD PTR [rsp-112], 0",
+        "        mov     QWORD PTR [rsp-104], rax",
+        "        lea     rax, [rsp-88]",
+        "        mov     QWORD PTR [rsp-96], rax",
+        "        movq    xmm0, rcx",
+        "        mov     eax, DWORD PTR [rsp-88]",
+        "        mov     DWORD PTR [rsp-108], 48",
+        "        add     rsp, 96",
+        "        ret",
+    )
+}
+
+fn main() {
+    unsafe {
+        assert_eq!(c_variadic(1, 2.0), Data(1, 2.0));
+        assert_eq!(c_variadic(123, 4.56), Data(123, 4.56));
+    }
+}
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_exprs/post-analysis-user-facing-param-env.rs b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.rs
index 478fa3706e8..9af351ec59f 100644
--- a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.rs
+++ b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.rs
@@ -11,7 +11,6 @@ where
 {
     fn unimplemented(self, _: &Foo) -> Self::Output {
         //~^ ERROR method `unimplemented` is not a member of trait `std::ops::Add`
-        //~| ERROR type annotations needed
         loop {}
     }
 }
diff --git a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
index 29bbd23a469..37eb895f9a8 100644
--- a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
@@ -3,7 +3,6 @@ error[E0407]: method `unimplemented` is not a member of trait `std::ops::Add`
    |
 LL | /     fn unimplemented(self, _: &Foo) -> Self::Output {
 LL | |
-LL | |
 LL | |         loop {}
 LL | |     }
    | |_____^ not a member of trait `std::ops::Add`
@@ -39,21 +38,7 @@ LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
 
-error[E0284]: type annotations needed
-  --> $DIR/post-analysis-user-facing-param-env.rs:12:40
-   |
-LL |     fn unimplemented(self, _: &Foo) -> Self::Output {
-   |                                        ^^^^^^^^^^^^ cannot infer the value of const parameter `NUM`
-   |
-note: required for `Foo` to implement `Add<&'a Foo>`
-  --> $DIR/post-analysis-user-facing-param-env.rs:6:28
-   |
-LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
-   |          ----------------  ^^^^^^^^^^^^^^^^^^^^^^     ^^^
-   |          |
-   |          unsatisfied trait bound introduced here
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0046, E0207, E0284, E0407.
+Some errors have detailed explanations: E0046, E0207, E0407.
 For more information about an error, try `rustc --explain E0046`.
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/explicit-tail-calls/c-variadic.rs b/tests/ui/explicit-tail-calls/c-variadic.rs
new file mode 100644
index 00000000000..e6eebe4228e
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/c-variadic.rs
@@ -0,0 +1,14 @@
+#![expect(incomplete_features)]
+#![feature(c_variadic, explicit_tail_calls)]
+#![allow(unused)]
+
+unsafe extern "C" fn foo(mut ap: ...) -> u32 {
+    ap.arg::<u32>()
+}
+
+extern "C" fn bar() -> u32 {
+    unsafe { become foo(1, 2, 3) }
+    //~^ ERROR c-variadic functions can't be tail-called
+}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/c-variadic.stderr b/tests/ui/explicit-tail-calls/c-variadic.stderr
new file mode 100644
index 00000000000..5293339d218
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/c-variadic.stderr
@@ -0,0 +1,8 @@
+error: c-variadic functions can't be tail-called
+  --> $DIR/c-variadic.rs:10:14
+   |
+LL |     unsafe { become foo(1, 2, 3) }
+   |              ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
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/linkage-attr/raw-dylib/windows/dlltool-failed.rs b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
index 92cb60bb16d..dac878c1cd9 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
@@ -20,4 +20,4 @@ pub fn lib_main() {
     unsafe { f(42); }
 }
 
-//~? ERROR Dlltool could not create import library with
+//~? ERROR dlltool could not create import library with
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr
index 90cca83d1c1..5f3c29c3a21 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr
@@ -1,4 +1,4 @@
-error: Dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo.dll -l $LIB_FILE $TARGET_MACHINE $ASM_FLAGS --no-leading-underscore $TEMP_PREFIX:
+error: dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo.dll -l $LIB_FILE $TARGET_MACHINE $ASM_FLAGS --no-leading-underscore $TEMP_PREFIX:
        
        $DLLTOOL: Syntax error in def file $DEF_FILE:1␍
 
diff --git a/tests/ui/macros/issue-61053-duplicate-binder.stderr b/tests/ui/macros/issue-61053-duplicate-binder.stderr
index 7c7cb26b407..1ecbc3f86d0 100644
--- a/tests/ui/macros/issue-61053-duplicate-binder.stderr
+++ b/tests/ui/macros/issue-61053-duplicate-binder.stderr
@@ -2,9 +2,9 @@ error: duplicate matcher binding
   --> $DIR/issue-61053-duplicate-binder.rs:7:20
    |
 LL |             ($x:tt $x:tt) => { $x };
-   |              --    ^^
+   |              --    ^^ duplicate binding
    |              |
-   |              previous declaration
+   |              previous binding
    |
 note: the lint level is defined here
   --> $DIR/issue-61053-duplicate-binder.rs:1:9
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,