about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-21 07:03:07 +0000
committerbors <bors@rust-lang.org>2025-08-21 07:03:07 +0000
commit57e620e56b718abaf47f18e1e20a3cc3480b258b (patch)
treecaf719c78a76b88564d2a96ed2bb9f6c09d1a5a3
parent922958cffe059e9c156835df19d199ccd861c36a (diff)
parent49eb7810e2a444befd7803c1a47b6a86d9f49c7c (diff)
downloadrust-57e620e56b718abaf47f18e1e20a3cc3480b258b.tar.gz
rust-57e620e56b718abaf47f18e1e20a3cc3480b258b.zip
Auto merge of #145701 - jhpratt:rollup-a0kg33p, r=jhpratt
Rollup of 19 pull requests

Successful merges:

 - rust-lang/rust#143383 (stabilize `const_array_each_ref`)
 - rust-lang/rust#144758 ([Doc] Add links to the various collections)
 - rust-lang/rust#144915 (Defer tail call ret ty equality to check_tail_calls)
 - rust-lang/rust#145256 (Add new `--test-codegen-backend` bootstrap option)
 - rust-lang/rust#145297 (fix(debuginfo): handle false positives in overflow check)
 - rust-lang/rust#145390 (Shorten some dependency chains in the compiler)
 - rust-lang/rust#145415 (std_detect: RISC-V: implement implication to "C")
 - rust-lang/rust#145525 (stdlib: Replace typedef -> type alias in doc comment)
 - rust-lang/rust#145590 (Prevent impossible combinations in `ast::ModKind`.)
 - rust-lang/rust#145593 (UnsafePinned::raw_get: sync signature with get)
 - rust-lang/rust#145621 (Fix some doc typos)
 - rust-lang/rust#145627 (Unconditionally-const supertraits are considered not dyn compatible)
 - rust-lang/rust#145642 (Do not use effective_visibilities query for Adt types of a local trait while proving a where-clause)
 - rust-lang/rust#145650 (Fix JS search scripts path)
 - rust-lang/rust#145654 (Download CI GCC into the correct directory)
 - rust-lang/rust#145662 (Enforce correct number of arguments for `"x86-interrupt"` functions)
 - rust-lang/rust#145673 (Add flock support for cygwin)
 - rust-lang/rust#145674 (Enable triagebot `[review-changes-since]` feature)
 - rust-lang/rust#145678 (Fix typo in docstring)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock28
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_abi/Cargo.toml2
-rw-r--r--compiler/rustc_abi/src/extern_abi.rs3
-rw-r--r--compiler/rustc_ast/src/ast.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_passes/messages.ftl4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs13
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs54
-rw-r--r--compiler/rustc_error_messages/Cargo.toml2
-rw-r--r--compiler/rustc_error_messages/src/diagnostic_impls.rs205
-rw-r--r--compiler/rustc_error_messages/src/lib.rs53
-rw-r--r--compiler/rustc_errors/Cargo.toml6
-rw-r--r--compiler/rustc_errors/src/codes.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs52
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs326
-rw-r--r--compiler/rustc_errors/src/lib.rs20
-rw-r--r--compiler/rustc_expand/src/expand.rs11
-rw-r--r--compiler/rustc_expand/src/module.rs2
-rw-r--r--compiler/rustc_hir/Cargo.toml2
-rw-r--r--compiler/rustc_hir/src/attrs/data_structures.rs26
-rw-r--r--compiler/rustc_hir/src/def.rs14
-rw-r--r--compiler/rustc_hir/src/hir.rs13
-rw-r--r--compiler/rustc_hir/src/lib.rs6
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs21
-rw-r--r--compiler/rustc_hir/src/target.rs2
-rw-r--r--compiler/rustc_hir/src/version.rs8
-rw-r--r--compiler/rustc_hir_id/Cargo.toml13
-rw-r--r--compiler/rustc_hir_id/src/lib.rs (renamed from compiler/rustc_hir/src/hir_id.rs)31
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/early/diagnostics.rs10
-rw-r--r--compiler/rustc_lint/src/lints.rs3
-rw-r--r--compiler/rustc_lint_defs/Cargo.toml2
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs21
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs23
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs4
-rw-r--r--compiler/rustc_mir_build/src/check_tail_calls.rs41
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs5
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/ident.rs2
-rw-r--r--compiler/rustc_target/Cargo.toml1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs27
-rw-r--r--compiler/rustc_traits/Cargo.toml1
-rw-r--r--compiler/rustc_traits/src/coroutine_witnesses.rs2
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs2
-rw-r--r--compiler/rustc_type_ir/Cargo.toml2
-rw-r--r--compiler/rustc_type_ir/src/ir_print.rs49
-rw-r--r--library/core/src/array/mod.rs8
-rw-r--r--library/core/src/pin/unsafe_pinned.rs4
-rw-r--r--library/core/src/task/poll.rs2
-rw-r--r--library/std/src/collections/mod.rs12
-rw-r--r--library/std/src/io/error.rs2
-rw-r--r--library/std/src/sys/fs/unix.rs10
-rw-r--r--library/std_detect/src/detect/os/riscv.rs22
-rw-r--r--src/bootstrap/src/core/build_steps/gcc.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs23
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs7
-rw-r--r--src/bootstrap/src/core/builder/tests.rs10
-rw-r--r--src/bootstrap/src/core/config/config.rs4
-rw-r--r--src/bootstrap/src/core/config/flags.rs12
-rw-r--r--src/bootstrap/src/lib.rs14
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/etc/completions/x.fish1
-rw-r--r--src/etc/completions/x.ps11
-rw-r--r--src/etc/completions/x.py.fish1
-rw-r--r--src/etc/completions/x.py.ps11
-rw-r--r--src/etc/completions/x.py.sh6
-rw-r--r--src/etc/completions/x.py.zsh1
-rw-r--r--src/etc/completions/x.sh6
-rw-r--r--src/etc/completions/x.zsh1
-rw-r--r--src/librustdoc/html/static/js/search.js4
-rw-r--r--src/tools/clippy/clippy_lints/src/duplicate_mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_line_after.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_nesting.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs2
-rw-r--r--src/tools/compiletest/src/common.rs7
-rw-r--r--src/tools/compiletest/src/directives.rs6
-rw-r--r--src/tools/compiletest/src/lib.rs22
-rw-r--r--src/tools/compiletest/src/runtest.rs5
-rw-r--r--src/tools/rustfmt/src/items.rs2
-rw-r--r--src/tools/rustfmt/src/modules.rs7
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--tests/codegen-llvm/abi-x86-interrupt.rs2
-rw-r--r--tests/codegen-llvm/naked-asan.rs4
-rw-r--r--tests/debuginfo/recursive-struct.rs9
-rw-r--r--tests/ui/abi/cannot-be-called.avr.stderr18
-rw-r--r--tests/ui/abi/cannot-be-called.i686.stderr24
-rw-r--r--tests/ui/abi/cannot-be-called.msp430.stderr18
-rw-r--r--tests/ui/abi/cannot-be-called.riscv32.stderr24
-rw-r--r--tests/ui/abi/cannot-be-called.riscv64.stderr24
-rw-r--r--tests/ui/abi/cannot-be-called.rs6
-rw-r--r--tests/ui/abi/cannot-be-called.x64.stderr24
-rw-r--r--tests/ui/abi/cannot-be-called.x64_win.stderr24
-rw-r--r--tests/ui/abi/cannot-be-coroutine.i686.stderr8
-rw-r--r--tests/ui/abi/cannot-be-coroutine.rs2
-rw-r--r--tests/ui/abi/cannot-be-coroutine.x64.stderr8
-rw-r--r--tests/ui/abi/cannot-be-coroutine.x64_win.stderr8
-rw-r--r--tests/ui/abi/interrupt-invalid-signature.i686.stderr30
-rw-r--r--tests/ui/abi/interrupt-invalid-signature.rs18
-rw-r--r--tests/ui/abi/interrupt-invalid-signature.x64.stderr30
-rw-r--r--tests/ui/abi/interrupt-returns-never-or-unit.rs4
-rw-r--r--tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.rs15
-rw-r--r--tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.stderr12
-rw-r--r--tests/ui/explicit-tail-calls/ret-ty-modulo-anonymization.rs16
-rw-r--r--tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs10
-rw-r--r--tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr10
-rw-r--r--tests/ui/trait-bounds/trait-bound-adt-issue-145611.rs11
-rw-r--r--tests/ui/trait-bounds/trait-bound-adt-issue-145611.stderr20
-rw-r--r--tests/ui/traits/const-traits/const-supertraits-dyn-compat.rs18
-rw-r--r--tests/ui/traits/const-traits/const-supertraits-dyn-compat.stderr18
-rw-r--r--triagebot.toml5
121 files changed, 1107 insertions, 698 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 51427f57822..6f7a309894c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3367,6 +3367,7 @@ dependencies = [
  "rand 0.9.2",
  "rand_xoshiro",
  "rustc_data_structures",
+ "rustc_error_messages",
  "rustc_hashes",
  "rustc_index",
  "rustc_macros",
@@ -3779,6 +3780,8 @@ dependencies = [
  "icu_locid",
  "icu_provider_adapters",
  "intl-memoizer",
+ "rustc_ast",
+ "rustc_ast_pretty",
  "rustc_baked_icu_data",
  "rustc_data_structures",
  "rustc_macros",
@@ -3795,22 +3798,18 @@ dependencies = [
  "annotate-snippets 0.11.5",
  "derive_setters",
  "rustc_abi",
- "rustc_ast",
- "rustc_ast_pretty",
  "rustc_data_structures",
  "rustc_error_codes",
  "rustc_error_messages",
  "rustc_fluent_macro",
  "rustc_hashes",
- "rustc_hir",
+ "rustc_hir_id",
  "rustc_index",
  "rustc_lexer",
  "rustc_lint_defs",
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
- "rustc_target",
- "rustc_type_ir",
  "serde",
  "serde_json",
  "termcolor",
@@ -3898,7 +3897,9 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_data_structures",
+ "rustc_error_messages",
  "rustc_hashes",
+ "rustc_hir_id",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -3937,6 +3938,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_hir_id"
+version = "0.0.0"
+dependencies = [
+ "rustc_data_structures",
+ "rustc_index",
+ "rustc_macros",
+ "rustc_serialize",
+ "rustc_span",
+]
+
+[[package]]
 name = "rustc_hir_pretty"
 version = "0.0.0"
 dependencies = [
@@ -4127,7 +4139,7 @@ dependencies = [
  "rustc_ast",
  "rustc_data_structures",
  "rustc_error_messages",
- "rustc_hir",
+ "rustc_hir_id",
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
@@ -4268,7 +4280,6 @@ dependencies = [
  "rustc_errors",
  "rustc_fluent_macro",
  "rustc_graphviz",
- "rustc_hir",
  "rustc_index",
  "rustc_macros",
  "rustc_middle",
@@ -4647,6 +4658,7 @@ dependencies = [
  "object 0.37.2",
  "rustc_abi",
  "rustc_data_structures",
+ "rustc_error_messages",
  "rustc_fs_util",
  "rustc_macros",
  "rustc_serialize",
@@ -4710,7 +4722,6 @@ name = "rustc_traits"
 version = "0.0.0"
 dependencies = [
  "rustc_data_structures",
- "rustc_hir",
  "rustc_infer",
  "rustc_middle",
  "rustc_span",
@@ -4765,6 +4776,7 @@ dependencies = [
  "rustc-hash 2.1.1",
  "rustc_ast_ir",
  "rustc_data_structures",
+ "rustc_error_messages",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
diff --git a/RELEASES.md b/RELEASES.md
index b6dc0628646..33abe45ce46 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1778,7 +1778,7 @@ Language
 - [Undeprecate lint `unstable_features` and make use of it in the compiler.](https://github.com/rust-lang/rust/pull/118639/)
 - [Make inductive cycles in coherence ambiguous always.](https://github.com/rust-lang/rust/pull/118649/)
 - [Get rid of type-driven traversal in const-eval interning](https://github.com/rust-lang/rust/pull/119044/),
-  only as a [future compatiblity lint](https://github.com/rust-lang/rust/pull/122204) for now.
+  only as a [future compatibility lint](https://github.com/rust-lang/rust/pull/122204) for now.
 - [Deny braced macro invocations in let-else.](https://github.com/rust-lang/rust/pull/119062/)
 
 <a id="1.77.0-Compiler"></a>
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 5f9afc46a1a..83d96d8d04d 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -9,6 +9,7 @@ bitflags = "2.4.1"
 rand = { version = "0.9.0", default-features = false, optional = true }
 rand_xoshiro = { version = "0.7.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
+rustc_error_messages = { path = "../rustc_error_messages", optional = true }
 rustc_hashes = { path = "../rustc_hashes" }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
@@ -24,6 +25,7 @@ default = ["nightly", "randomize"]
 # without depending on rustc_data_structures, rustc_macros and rustc_serialize
 nightly = [
     "dep:rustc_data_structures",
+    "dep:rustc_error_messages",
     "dep:rustc_macros",
     "dep:rustc_serialize",
     "dep:rustc_span",
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs
index 29a3678abf3..41d744e1946 100644
--- a/compiler/rustc_abi/src/extern_abi.rs
+++ b/compiler/rustc_abi/src/extern_abi.rs
@@ -223,6 +223,9 @@ impl StableOrd for ExternAbi {
     const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
 }
 
+#[cfg(feature = "nightly")]
+rustc_error_messages::into_diag_arg_using_display!(ExternAbi);
+
 impl ExternAbi {
     /// An ABI "like Rust"
     ///
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 87c9c797ea5..de3e0e0c87f 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3137,7 +3137,7 @@ impl FnRetTy {
 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, Walkable)]
 pub enum Inline {
     Yes,
-    No,
+    No { had_parse_error: Result<(), ErrorGuaranteed> },
 }
 
 /// Module item kind.
@@ -3147,7 +3147,7 @@ pub enum ModKind {
     /// or with definition outlined to a separate file `mod foo;` and already loaded from it.
     /// The inner span is from the first token past `{` to the last token until `}`,
     /// or from the first to the last token in the loaded file.
-    Loaded(ThinVec<Box<Item>>, Inline, ModSpans, Result<(), ErrorGuaranteed>),
+    Loaded(ThinVec<Box<Item>>, Inline, ModSpans),
     /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
     Unloaded,
 }
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 72817a0a9a0..cd0f9f2403e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -251,7 +251,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Mod(_, ident, mod_kind) => {
                 let ident = self.lower_ident(*ident);
                 match mod_kind {
-                    ModKind::Loaded(items, _, spans, _) => {
+                    ModKind::Loaded(items, _, spans) => {
                         hir::ItemKind::Mod(ident, self.lower_mod(items, spans))
                     }
                     ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 73cbcdd30ce..c0679c1b8ff 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -20,6 +20,10 @@ ast_passes_abi_must_not_have_return_type=
     .note = functions with the {$abi} ABI cannot have a return type
     .help = remove the return type
 
+ast_passes_abi_x86_interrupt =
+    invalid signature for `extern "x86-interrupt"` function
+    .note = functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found {$param_count})
+
 ast_passes_assoc_const_without_body =
     associated constant in `impl` without body
     .suggestion = provide a definition for the constant
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 0c72f319007..ef4410566c5 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -405,6 +405,17 @@ impl<'a> AstValidator<'a> {
                         if let InterruptKind::X86 = interrupt_kind {
                             // "x86-interrupt" is special because it does have arguments.
                             // FIXME(workingjubilee): properly lint on acceptable input types.
+                            let inputs = &sig.decl.inputs;
+                            let param_count = inputs.len();
+                            if !matches!(param_count, 1 | 2) {
+                                let mut spans: Vec<Span> =
+                                    inputs.iter().map(|arg| arg.span).collect();
+                                if spans.is_empty() {
+                                    spans = vec![sig.span];
+                                }
+                                self.dcx().emit_err(errors::AbiX86Interrupt { spans, param_count });
+                            }
+
                             if let FnRetTy::Ty(ref ret_ty) = sig.decl.output
                                 && match &ret_ty.kind {
                                     TyKind::Never => false,
@@ -1169,7 +1180,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
                 }
                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
-                if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _))
+                if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
                     && !attr::contains_name(&item.attrs, sym::path)
                 {
                     self.check_mod_file_item_asciionly(*ident);
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 5ecc0d21411..b9b2d271954 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -891,3 +891,12 @@ pub(crate) struct AbiMustNotHaveReturnType {
     pub span: Span,
     pub abi: ExternAbi,
 }
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_abi_x86_interrupt)]
+#[note]
+pub(crate) struct AbiX86Interrupt {
+    #[primary_span]
+    pub spans: Vec<Span>,
+    pub param_count: usize,
+}
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 540700a6894..0e1dd5c701f 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1879,7 +1879,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             if !output_ty
                 .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
             {
-                span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
+                span_mirbug!(self, term, "call to non-diverging function {:?} w/o dest", sig);
             }
         } else {
             let dest_ty = destination.ty(self.body, tcx).ty;
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index e803f3be82b..a9d91f77560 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -141,7 +141,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
         if let ast::ItemKind::Mod(
             _,
             _,
-            ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _),
+            ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }),
         ) = item.kind
         {
             let prev_tests = mem::take(&mut self.tests);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index d1502d2b1e6..18a783a348a 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -276,7 +276,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
         && let ty::Adt(adt_def, args) = ty.kind()
     {
         let def_id = adt_def.did();
-        // If any sub type reference the original type definition and the sub type has a type
+        // If any child type references the original type definition and the child type has a type
         // parameter that strictly contains the original parameter, the original type is a recursive
         // type that can expanding indefinitely. Example,
         // ```
@@ -285,21 +285,43 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
         //     Item(T),
         // }
         // ```
-        let is_expanding_recursive = adt_def.is_enum()
-            && debug_context(cx).adt_stack.borrow().iter().any(|(parent_def_id, parent_args)| {
-                if def_id == *parent_def_id {
-                    args.iter().zip(parent_args.iter()).any(|(arg, parent_arg)| {
-                        if let (Some(arg), Some(parent_arg)) = (arg.as_type(), parent_arg.as_type())
-                        {
-                            arg != parent_arg && arg.contains(parent_arg)
-                        } else {
-                            false
-                        }
-                    })
-                } else {
-                    false
-                }
-            });
+        let is_expanding_recursive = {
+            let stack = debug_context(cx).adt_stack.borrow();
+            stack
+                .iter()
+                .enumerate()
+                .rev()
+                .skip(1)
+                .filter(|(_, (ancestor_def_id, _))| def_id == *ancestor_def_id)
+                .any(|(ancestor_index, (_, ancestor_args))| {
+                    args.iter()
+                        .zip(ancestor_args.iter())
+                        .filter_map(|(arg, ancestor_arg)| arg.as_type().zip(ancestor_arg.as_type()))
+                        .any(|(arg, ancestor_arg)|
+                            // Strictly contains.
+                            (arg != ancestor_arg && arg.contains(ancestor_arg))
+                            // Check all types between current and ancestor use the
+                            // ancestor_arg.
+                            // Otherwise, duplicate wrappers in normal recursive type may be
+                            // regarded as expanding.
+                            // ```
+                            // struct Recursive {
+                            //     a: Box<Box<Recursive>>,
+                            // }
+                            // ```
+                            // It can produce an ADT stack like this,
+                            // - Box<Recursive>
+                            // - Recursive
+                            // - Box<Box<Recursive>>
+                            && stack[ancestor_index + 1..stack.len()].iter().all(
+                                |(_, intermediate_args)|
+                                    intermediate_args
+                                        .iter()
+                                        .filter_map(|arg| arg.as_type())
+                                        .any(|mid_arg| mid_arg.contains(ancestor_arg))
+                            ))
+                })
+        };
         if is_expanding_recursive {
             // FIXME: indicate that this is an expanding recursive type in stub metadata?
             return DINodeCreationResult::new(stub_info.metadata, false);
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 0951859fa53..552ad672752 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -11,6 +11,8 @@ icu_list = "1.2"
 icu_locid = "1.2"
 icu_provider_adapters = "1.2"
 intl-memoizer = "0.5.1"
+rustc_ast = { path = "../rustc_ast" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_baked_icu_data = { path = "../rustc_baked_icu_data" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_error_messages/src/diagnostic_impls.rs b/compiler/rustc_error_messages/src/diagnostic_impls.rs
new file mode 100644
index 00000000000..3b664cce577
--- /dev/null
+++ b/compiler/rustc_error_messages/src/diagnostic_impls.rs
@@ -0,0 +1,205 @@
+use std::backtrace::Backtrace;
+use std::borrow::Cow;
+use std::fmt;
+use std::num::ParseIntError;
+use std::path::{Path, PathBuf};
+use std::process::ExitStatus;
+
+use rustc_ast as ast;
+use rustc_ast_pretty::pprust;
+use rustc_span::edition::Edition;
+
+use crate::{DiagArgValue, IntoDiagArg};
+
+pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
+
+impl IntoDiagArg for DiagArgFromDisplay<'_> {
+    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        self.0.to_string().into_diag_arg(path)
+    }
+}
+
+impl<'a> From<&'a dyn fmt::Display> for DiagArgFromDisplay<'a> {
+    fn from(t: &'a dyn fmt::Display) -> Self {
+        DiagArgFromDisplay(t)
+    }
+}
+
+impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> {
+    fn from(t: &'a T) -> Self {
+        DiagArgFromDisplay(t)
+    }
+}
+
+impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
+    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        self.clone().into_diag_arg(path)
+    }
+}
+
+#[macro_export]
+macro_rules! into_diag_arg_using_display {
+    ($( $ty:ty ),+ $(,)?) => {
+        $(
+            impl $crate::IntoDiagArg for $ty {
+                fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> $crate::DiagArgValue {
+                    self.to_string().into_diag_arg(path)
+                }
+            }
+        )+
+    }
+}
+
+macro_rules! into_diag_arg_for_number {
+    ($( $ty:ty ),+ $(,)?) => {
+        $(
+            impl $crate::IntoDiagArg for $ty {
+                fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> $crate::DiagArgValue {
+                    // Convert to a string if it won't fit into `Number`.
+                    #[allow(irrefutable_let_patterns)]
+                    if let Ok(n) = TryInto::<i32>::try_into(self) {
+                        $crate::DiagArgValue::Number(n)
+                    } else {
+                        self.to_string().into_diag_arg(path)
+                    }
+                }
+            }
+        )+
+    }
+}
+
+into_diag_arg_using_display!(
+    ast::ParamKindOrd,
+    std::io::Error,
+    Box<dyn std::error::Error>,
+    std::num::NonZero<u32>,
+    Edition,
+    rustc_span::Ident,
+    rustc_span::MacroRulesNormalizedIdent,
+    ParseIntError,
+    ExitStatus,
+);
+
+into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
+
+impl IntoDiagArg for bool {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        if self {
+            DiagArgValue::Str(Cow::Borrowed("true"))
+        } else {
+            DiagArgValue::Str(Cow::Borrowed("false"))
+        }
+    }
+}
+
+impl IntoDiagArg for char {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
+    }
+}
+
+impl IntoDiagArg for Vec<char> {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::StrListSepByAnd(
+            self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
+        )
+    }
+}
+
+impl IntoDiagArg for rustc_span::Symbol {
+    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        self.to_ident_string().into_diag_arg(path)
+    }
+}
+
+impl<'a> IntoDiagArg for &'a str {
+    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        self.to_string().into_diag_arg(path)
+    }
+}
+
+impl IntoDiagArg for String {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self))
+    }
+}
+
+impl<'a> IntoDiagArg for Cow<'a, str> {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self.into_owned()))
+    }
+}
+
+impl<'a> IntoDiagArg for &'a Path {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self.display().to_string()))
+    }
+}
+
+impl IntoDiagArg for PathBuf {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self.display().to_string()))
+    }
+}
+
+impl IntoDiagArg for ast::Expr {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
+    }
+}
+
+impl IntoDiagArg for ast::Path {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
+    }
+}
+
+impl IntoDiagArg for ast::token::Token {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(pprust::token_to_string(&self))
+    }
+}
+
+impl IntoDiagArg for ast::token::TokenKind {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(pprust::token_kind_to_string(&self))
+    }
+}
+
+impl IntoDiagArg for std::ffi::CString {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
+    }
+}
+
+impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
+    }
+}
+
+impl IntoDiagArg for ast::Visibility {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        let s = pprust::vis_to_string(&self);
+        let s = s.trim_end().to_string();
+        DiagArgValue::Str(Cow::Owned(s))
+    }
+}
+
+impl IntoDiagArg for Backtrace {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::from(self.to_string()))
+    }
+}
+
+impl IntoDiagArg for ast::util::parser::ExprPrecedence {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Number(self as i32)
+    }
+}
+
+impl IntoDiagArg for ast::FloatTy {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Borrowed(self.name_str()))
+    }
+}
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 4b3ecad307f..d8bacbe762b 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -23,6 +23,9 @@ use rustc_span::Span;
 use tracing::{instrument, trace};
 pub use unic_langid::{LanguageIdentifier, langid};
 
+mod diagnostic_impls;
+pub use diagnostic_impls::DiagArgFromDisplay;
+
 pub type FluentBundle =
     IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;
 
@@ -589,3 +592,53 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValu
 
     FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
 }
+
+/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
+/// `DiagArg` are converted to `FluentArgs` (consuming the collection) at the start of diagnostic
+/// emission.
+pub type DiagArg<'iter> = (&'iter DiagArgName, &'iter DiagArgValue);
+
+/// Name of a diagnostic argument.
+pub type DiagArgName = Cow<'static, str>;
+
+/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
+/// to a `FluentValue` by the emitter to be used in diagnostic translation.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
+pub enum DiagArgValue {
+    Str(Cow<'static, str>),
+    // This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
+    // safely fits in an `f64`. Any integers bigger than that will be converted
+    // to strings in `into_diag_arg` and stored using the `Str` variant.
+    Number(i32),
+    StrListSepByAnd(Vec<Cow<'static, str>>),
+}
+
+/// Converts a value of a type into a `DiagArg` (typically a field of an `Diag` struct).
+/// Implemented as a custom trait rather than `From` so that it is implemented on the type being
+/// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
+/// implement this.
+pub trait IntoDiagArg {
+    /// Convert `Self` into a `DiagArgValue` suitable for rendering in a diagnostic.
+    ///
+    /// It takes a `path` where "long values" could be written to, if the `DiagArgValue` is too big
+    /// for displaying on the terminal. This path comes from the `Diag` itself. When rendering
+    /// values that come from `TyCtxt`, like `Ty<'_>`, they can use `TyCtxt::short_string`. If a
+    /// value has no shortening logic that could be used, the argument can be safely ignored.
+    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
+}
+
+impl IntoDiagArg for DiagArgValue {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        self
+    }
+}
+
+impl From<DiagArgValue> for FluentValue<'static> {
+    fn from(val: DiagArgValue) -> Self {
+        match val {
+            DiagArgValue::Str(s) => From::from(s),
+            DiagArgValue::Number(n) => From::from(n),
+            DiagArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
+        }
+    }
+}
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 3e8cf6207ae..ad6d29e21fc 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -8,22 +8,18 @@ edition = "2024"
 annotate-snippets = "0.11"
 derive_setters = "0.1.6"
 rustc_abi = { path = "../rustc_abi" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hashes = { path = "../rustc_hashes" }
-rustc_hir = { path = "../rustc_hir" }
+rustc_hir_id = { path = "../rustc_hir_id" }
 rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
-rustc_type_ir = { path = "../rustc_type_ir" }
 serde = { version = "1.0.125", features = ["derive"] }
 serde_json = "1.0.59"
 termcolor = "1.2.0"
diff --git a/compiler/rustc_errors/src/codes.rs b/compiler/rustc_errors/src/codes.rs
index 947cf27ca79..787a8af99b1 100644
--- a/compiler/rustc_errors/src/codes.rs
+++ b/compiler/rustc_errors/src/codes.rs
@@ -20,6 +20,8 @@ impl fmt::Display for ErrCode {
     }
 }
 
+rustc_error_messages::into_diag_arg_using_display!(ErrCode);
+
 macro_rules! define_error_code_constants_and_diagnostics_table {
     ($($name:ident: $num:literal,)*) => (
         $(
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index e579370ce4e..183dceddd2c 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -8,7 +8,7 @@ use std::path::PathBuf;
 use std::thread::panicking;
 
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_error_messages::{FluentValue, fluent_value_from_str_list_sep_by_and};
+use rustc_error_messages::{DiagArgName, DiagArgValue, IntoDiagArg};
 use rustc_lint_defs::{Applicability, LintExpectationId};
 use rustc_macros::{Decodable, Encodable};
 use rustc_span::source_map::Spanned;
@@ -22,26 +22,6 @@ use crate::{
     Suggestions,
 };
 
-/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
-/// `DiagArg` are converted to `FluentArgs` (consuming the collection) at the start of diagnostic
-/// emission.
-pub type DiagArg<'iter> = (&'iter DiagArgName, &'iter DiagArgValue);
-
-/// Name of a diagnostic argument.
-pub type DiagArgName = Cow<'static, str>;
-
-/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
-/// to a `FluentValue` by the emitter to be used in diagnostic translation.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
-pub enum DiagArgValue {
-    Str(Cow<'static, str>),
-    // This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
-    // safely fits in an `f64`. Any integers bigger than that will be converted
-    // to strings in `into_diag_arg` and stored using the `Str` variant.
-    Number(i32),
-    StrListSepByAnd(Vec<Cow<'static, str>>),
-}
-
 pub type DiagArgMap = FxIndexMap<DiagArgName, DiagArgValue>;
 
 /// Trait for types that `Diag::emit` can return as a "guarantee" (or "proof")
@@ -143,36 +123,6 @@ where
     }
 }
 
-/// Converts a value of a type into a `DiagArg` (typically a field of an `Diag` struct).
-/// Implemented as a custom trait rather than `From` so that it is implemented on the type being
-/// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
-/// implement this.
-pub trait IntoDiagArg {
-    /// Convert `Self` into a `DiagArgValue` suitable for rendering in a diagnostic.
-    ///
-    /// It takes a `path` where "long values" could be written to, if the `DiagArgValue` is too big
-    /// for displaying on the terminal. This path comes from the `Diag` itself. When rendering
-    /// values that come from `TyCtxt`, like `Ty<'_>`, they can use `TyCtxt::short_string`. If a
-    /// value has no shortening logic that could be used, the argument can be safely ignored.
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
-}
-
-impl IntoDiagArg for DiagArgValue {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self
-    }
-}
-
-impl From<DiagArgValue> for FluentValue<'static> {
-    fn from(val: DiagArgValue) -> Self {
-        match val {
-            DiagArgValue::Str(s) => From::from(s),
-            DiagArgValue::Number(n) => From::from(n),
-            DiagArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
-        }
-    }
-}
-
 /// Trait implemented by error types. This should not be implemented manually. Instead, use
 /// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
 #[rustc_diagnostic_item = "Subdiagnostic"]
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 698b6b8d504..435d16a8380 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -1,340 +1,22 @@
-use std::backtrace::Backtrace;
 use std::borrow::Cow;
-use std::fmt;
-use std::num::ParseIntError;
-use std::path::{Path, PathBuf};
-use std::process::ExitStatus;
 
 use rustc_abi::TargetDataLayoutErrors;
-use rustc_ast::util::parser::ExprPrecedence;
-use rustc_ast_pretty::pprust;
-use rustc_hir::RustcVersion;
-use rustc_hir::attrs::{MirDialect, MirPhase};
+use rustc_error_messages::{DiagArgValue, IntoDiagArg};
 use rustc_macros::Subdiagnostic;
-use rustc_span::edition::Edition;
-use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol};
-use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTuple};
-use rustc_type_ir::{ClosureKind, FloatTy};
-use {rustc_ast as ast, rustc_hir as hir};
+use rustc_span::{Span, Symbol};
 
 use crate::diagnostic::DiagLocation;
 use crate::{
-    Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, ErrCode, IntoDiagArg, Level,
-    Subdiagnostic, fluent_generated as fluent,
+    Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic,
+    fluent_generated as fluent,
 };
 
-pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
-
-impl IntoDiagArg for DiagArgFromDisplay<'_> {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self.0.to_string().into_diag_arg(path)
-    }
-}
-
-impl<'a> From<&'a dyn fmt::Display> for DiagArgFromDisplay<'a> {
-    fn from(t: &'a dyn fmt::Display) -> Self {
-        DiagArgFromDisplay(t)
-    }
-}
-
-impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> {
-    fn from(t: &'a T) -> Self {
-        DiagArgFromDisplay(t)
-    }
-}
-
-impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self.clone().into_diag_arg(path)
-    }
-}
-
-#[macro_export]
-macro_rules! into_diag_arg_using_display {
-    ($( $ty:ty ),+ $(,)?) => {
-        $(
-            impl IntoDiagArg for $ty {
-                fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-                    self.to_string().into_diag_arg(path)
-                }
-            }
-        )+
-    }
-}
-
-macro_rules! into_diag_arg_for_number {
-    ($( $ty:ty ),+ $(,)?) => {
-        $(
-            impl IntoDiagArg for $ty {
-                fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-                    // Convert to a string if it won't fit into `Number`.
-                    #[allow(irrefutable_let_patterns)]
-                    if let Ok(n) = TryInto::<i32>::try_into(self) {
-                        DiagArgValue::Number(n)
-                    } else {
-                        self.to_string().into_diag_arg(path)
-                    }
-                }
-            }
-        )+
-    }
-}
-
-into_diag_arg_using_display!(
-    ast::ParamKindOrd,
-    std::io::Error,
-    Box<dyn std::error::Error>,
-    std::num::NonZero<u32>,
-    hir::Target,
-    Edition,
-    Ident,
-    MacroRulesNormalizedIdent,
-    ParseIntError,
-    StackProtector,
-    &TargetTuple,
-    SplitDebuginfo,
-    ExitStatus,
-    ErrCode,
-    rustc_abi::ExternAbi,
-);
-
-impl IntoDiagArg for RustcVersion {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self.to_string()))
-    }
-}
-
-impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self.to_string().into_diag_arg(path)
-    }
-}
-
-impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTraitRef<I> {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self.to_string().into_diag_arg(path)
-    }
-}
-
-impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        format!("{self:?}").into_diag_arg(path)
-    }
-}
-
-impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        format!("{self:?}").into_diag_arg(path)
-    }
-}
-
-impl<I: rustc_type_ir::Interner, T> IntoDiagArg for rustc_type_ir::Binder<I, T>
-where
-    T: IntoDiagArg,
-{
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self.skip_binder().into_diag_arg(path)
-    }
-}
-
-into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
-
-impl IntoDiagArg for bool {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        if self {
-            DiagArgValue::Str(Cow::Borrowed("true"))
-        } else {
-            DiagArgValue::Str(Cow::Borrowed("false"))
-        }
-    }
-}
-
-impl IntoDiagArg for char {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
-    }
-}
-
-impl IntoDiagArg for Vec<char> {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::StrListSepByAnd(
-            self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
-        )
-    }
-}
-
-impl IntoDiagArg for Symbol {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self.to_ident_string().into_diag_arg(path)
-    }
-}
-
-impl<'a> IntoDiagArg for &'a str {
-    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        self.to_string().into_diag_arg(path)
-    }
-}
-
-impl IntoDiagArg for String {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self))
-    }
-}
-
-impl<'a> IntoDiagArg for Cow<'a, str> {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self.into_owned()))
-    }
-}
-
-impl<'a> IntoDiagArg for &'a Path {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self.display().to_string()))
-    }
-}
-
-impl IntoDiagArg for PathBuf {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self.display().to_string()))
-    }
-}
-
-impl IntoDiagArg for PanicStrategy {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
-    }
-}
-
-impl IntoDiagArg for hir::ConstContext {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Borrowed(match self {
-            hir::ConstContext::ConstFn => "const_fn",
-            hir::ConstContext::Static(_) => "static",
-            hir::ConstContext::Const { .. } => "const",
-        }))
-    }
-}
-
-impl IntoDiagArg for ast::Expr {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
-    }
-}
-
-impl IntoDiagArg for ast::Path {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
-    }
-}
-
-impl IntoDiagArg for ast::token::Token {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(pprust::token_to_string(&self))
-    }
-}
-
-impl IntoDiagArg for ast::token::TokenKind {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(pprust::token_kind_to_string(&self))
-    }
-}
-
-impl IntoDiagArg for FloatTy {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Borrowed(self.name_str()))
-    }
-}
-
-impl IntoDiagArg for std::ffi::CString {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
-    }
-}
-
-impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
-    }
-}
-
-impl IntoDiagArg for ast::Visibility {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        let s = pprust::vis_to_string(&self);
-        let s = s.trim_end().to_string();
-        DiagArgValue::Str(Cow::Owned(s))
-    }
-}
-
-impl IntoDiagArg for rustc_lint_defs::Level {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
-    }
-}
-
-impl<Id> IntoDiagArg for hir::def::Res<Id> {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Borrowed(self.descr()))
-    }
-}
-
 impl IntoDiagArg for DiagLocation {
     fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
         DiagArgValue::Str(Cow::from(self.to_string()))
     }
 }
 
-impl IntoDiagArg for Backtrace {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::from(self.to_string()))
-    }
-}
-
-impl IntoDiagArg for Level {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::from(self.to_string()))
-    }
-}
-
-impl IntoDiagArg for ClosureKind {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(self.as_str().into())
-    }
-}
-
-impl IntoDiagArg for hir::def::Namespace {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Str(Cow::Borrowed(self.descr()))
-    }
-}
-
-impl IntoDiagArg for ExprPrecedence {
-    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
-        DiagArgValue::Number(self as i32)
-    }
-}
-
-impl IntoDiagArg for MirDialect {
-    fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
-        let arg = match self {
-            MirDialect::Analysis => "analysis",
-            MirDialect::Built => "built",
-            MirDialect::Runtime => "runtime",
-        };
-        DiagArgValue::Str(Cow::Borrowed(arg))
-    }
-}
-
-impl IntoDiagArg for MirPhase {
-    fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
-        let arg = match self {
-            MirPhase::Initial => "initial",
-            MirPhase::PostCleanup => "post-cleanup",
-            MirPhase::Optimized => "optimized",
-        };
-        DiagArgValue::Str(Cow::Borrowed(arg))
-    }
-}
-
 #[derive(Clone)]
 pub struct DiagSymbolList<S = Symbol>(Vec<S>);
 
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 2534cddf105..a775b70dbee 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -41,12 +41,11 @@ use std::{fmt, panic};
 use Level::*;
 pub use codes::*;
 pub use diagnostic::{
-    BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString,
-    Diagnostic, EmissionGuarantee, FatalAbort, IntoDiagArg, LintDiagnostic, StringPart, Subdiag,
-    Subdiagnostic,
+    BugAbort, Diag, DiagArgMap, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee,
+    FatalAbort, LintDiagnostic, StringPart, Subdiag, Subdiagnostic,
 };
 pub use diagnostic_impls::{
-    DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
+    DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
     IndicateAnonymousLifetime, SingleLabelManySpans,
 };
 pub use emitter::ColorConfig;
@@ -56,11 +55,12 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{DynSend, Lock};
 pub use rustc_error_messages::{
-    DiagMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel,
-    SubdiagMessage, fallback_fluent_bundle, fluent_bundle,
+    DiagArg, DiagArgFromDisplay, DiagArgName, DiagArgValue, DiagMessage, FluentBundle, IntoDiagArg,
+    LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
+    fallback_fluent_bundle, fluent_bundle, into_diag_arg_using_display,
 };
 use rustc_hashes::Hash128;
-use rustc_hir::HirId;
+use rustc_hir_id::HirId;
 pub use rustc_lint_defs::{Applicability, listify, pluralize};
 use rustc_lint_defs::{Lint, LintExpectationId};
 use rustc_macros::{Decodable, Encodable};
@@ -1999,6 +1999,12 @@ impl Level {
     }
 }
 
+impl IntoDiagArg for Level {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::from(self.to_string()))
+    }
+}
+
 // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite.
 pub fn elided_lifetime_in_path_suggestion(
     source_map: &SourceMap,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 1f7f4c7d856..755275d3cda 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -801,7 +801,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                     ItemKind::Mod(
                                         _,
                                         _,
-                                        ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _),
+                                        ModKind::Unloaded
+                                            | ModKind::Loaded(_, Inline::No { .. }, _),
                                     )
                                 ) =>
                         {
@@ -1035,7 +1036,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
                     ItemKind::Mod(_, _, mod_kind)
-                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) =>
+                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
                     {
                         feature_err(
                             self.sess,
@@ -1346,7 +1347,7 @@ impl InvocationCollectorNode for Box<ast::Item> {
         let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() };
         let ecx = &mut collector.cx;
         let (file_path, dir_path, dir_ownership) = match mod_kind {
-            ModKind::Loaded(_, inline, _, _) => {
+            ModKind::Loaded(_, inline, _) => {
                 // Inline `mod foo { ... }`, but we still need to push directories.
                 let (dir_path, dir_ownership) = mod_dir_path(
                     ecx.sess,
@@ -1360,7 +1361,7 @@ impl InvocationCollectorNode for Box<ast::Item> {
                 // This lets `parse_external_mod` catch cycles if it's self-referential.
                 let file_path = match inline {
                     Inline::Yes => None,
-                    Inline::No => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path),
+                    Inline::No { .. } => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path),
                 };
                 node.attrs = attrs;
                 (file_path, dir_path, dir_ownership)
@@ -1396,7 +1397,7 @@ impl InvocationCollectorNode for Box<ast::Item> {
                     );
                 }
 
-                *mod_kind = ModKind::Loaded(items, Inline::No, spans, had_parse_error);
+                *mod_kind = ModKind::Loaded(items, Inline::No { had_parse_error }, spans);
                 node.attrs = attrs;
                 if node.attrs.len() > old_attrs_len {
                     // If we loaded an out-of-line module and added some inner attributes,
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 662c67f2d3f..6666ea33cd3 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -120,7 +120,7 @@ pub(crate) fn mod_dir_path(
 
             (dir_path, dir_ownership)
         }
-        Inline::No => {
+        Inline::No { .. } => {
             // FIXME: This is a subset of `parse_external_mod` without actual parsing,
             // check whether the logic for unloaded, loaded and inline modules can be unified.
             let file_path = mod_file_path(sess, ident, attrs, &module.dir_path, dir_ownership)
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 71496b7ec32..1008a3e787d 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -12,7 +12,9 @@ rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_hashes = { path = "../rustc_hashes" }
+rustc_hir_id = { path = "../rustc_hir_id" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index 31715955ed3..a17350f0392 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -1,7 +1,11 @@
+use std::borrow::Cow;
+use std::path::PathBuf;
+
 pub use ReprAttr::*;
 use rustc_abi::Align;
 use rustc_ast::token::CommentKind;
 use rustc_ast::{AttrStyle, ast};
+use rustc_error_messages::{DiagArgValue, IntoDiagArg};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::Transparency;
@@ -213,6 +217,17 @@ pub enum MirDialect {
     Runtime,
 }
 
+impl IntoDiagArg for MirDialect {
+    fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
+        let arg = match self {
+            MirDialect::Analysis => "analysis",
+            MirDialect::Built => "built",
+            MirDialect::Runtime => "runtime",
+        };
+        DiagArgValue::Str(Cow::Borrowed(arg))
+    }
+}
+
 #[derive(Clone, Copy, Decodable, Debug, Encodable, PartialEq)]
 #[derive(HashStable_Generic, PrintAttribute)]
 pub enum MirPhase {
@@ -221,6 +236,17 @@ pub enum MirPhase {
     Optimized,
 }
 
+impl IntoDiagArg for MirPhase {
+    fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
+        let arg = match self {
+            MirPhase::Initial => "initial",
+            MirPhase::PostCleanup => "post-cleanup",
+            MirPhase::Optimized => "optimized",
+        };
+        DiagArgValue::Str(Cow::Borrowed(arg))
+    }
+}
+
 /// Represents parsed *built-in* inert attributes.
 ///
 /// ## Overview
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 79319e24266..8af4740f376 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -1,10 +1,12 @@
 use std::array::IntoIter;
+use std::borrow::Cow;
 use std::fmt::Debug;
 
 use rustc_ast as ast;
 use rustc_ast::NodeId;
 use rustc_data_structures::stable_hasher::ToStableHashKey;
 use rustc_data_structures::unord::UnordMap;
+use rustc_error_messages::{DiagArgValue, IntoDiagArg};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::Symbol;
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -586,6 +588,12 @@ pub enum Res<Id = hir::HirId> {
     Err,
 }
 
+impl<Id> IntoDiagArg for Res<Id> {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Borrowed(self.descr()))
+    }
+}
+
 /// The result of resolving a path before lowering to HIR,
 /// with "module" segments resolved and associated item
 /// segments deferred to type checking.
@@ -673,6 +681,12 @@ impl Namespace {
     }
 }
 
+impl IntoDiagArg for Namespace {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Borrowed(self.descr()))
+    }
+}
+
 impl<CTX: crate::HashStableContext> ToStableHashKey<CTX> for Namespace {
     type KeyType = Namespace;
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 2c8986b7c7d..39696f74d51 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1,4 +1,5 @@
 // ignore-tidy-filelength
+use std::borrow::Cow;
 use std::fmt;
 
 use rustc_abi::ExternAbi;
@@ -17,6 +18,7 @@ pub use rustc_ast::{
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::tagged_ptr::TaggedRef;
+use rustc_error_messages::{DiagArgValue, IntoDiagArg};
 use rustc_index::IndexVec;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::def_id::LocalDefId;
@@ -2259,8 +2261,15 @@ impl fmt::Display for ConstContext {
     }
 }
 
-// NOTE: `IntoDiagArg` impl for `ConstContext` lives in `rustc_errors`
-// due to a cyclical dependency between hir and that crate.
+impl IntoDiagArg for ConstContext {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Borrowed(match self {
+            ConstContext::ConstFn => "const_fn",
+            ConstContext::Static(_) => "static",
+            ConstContext::Const { .. } => "const",
+        }))
+    }
+}
 
 /// A literal.
 pub type Lit = Spanned<LitKind>;
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index f1212d07ff6..78fc63753a2 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -3,14 +3,11 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 // tidy-alphabetical-start
-#![allow(internal_features)]
 #![feature(associated_type_defaults)]
 #![feature(closure_track_caller)]
 #![feature(debug_closure_helpers)]
 #![feature(exhaustive_patterns)]
-#![feature(negative_impls)]
 #![feature(never_type)]
-#![feature(rustc_attrs)]
 #![feature(variant_count)]
 #![recursion_limit = "256"]
 // tidy-alphabetical-end
@@ -25,7 +22,7 @@ pub mod definitions;
 pub mod diagnostic_items;
 pub use rustc_span::def_id;
 mod hir;
-pub mod hir_id;
+pub use rustc_hir_id::{self as hir_id, *};
 pub mod intravisit;
 pub mod lang_items;
 pub mod lints;
@@ -41,7 +38,6 @@ mod tests;
 
 #[doc(no_inline)]
 pub use hir::*;
-pub use hir_id::*;
 pub use lang_items::{LangItem, LanguageItems};
 pub use stability::*;
 pub use stable_hash_impls::HashStableContext;
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index ecc608d437b..16e8bac3d8a 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -5,7 +5,7 @@ use crate::HashIgnoredAttrId;
 use crate::hir::{
     AttributeMap, BodyId, Crate, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId,
 };
-use crate::hir_id::{HirId, ItemLocalId};
+use crate::hir_id::ItemLocalId;
 use crate::lints::DelayedLints;
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
@@ -15,25 +15,6 @@ pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStabl
     fn hash_attr_id(&mut self, id: &HashIgnoredAttrId, hasher: &mut StableHasher);
 }
 
-impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
-    type KeyType = (DefPathHash, ItemLocalId);
-
-    #[inline]
-    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
-        let def_path_hash = self.owner.def_id.to_stable_hash_key(hcx);
-        (def_path_hash, self.local_id)
-    }
-}
-
-impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemLocalId {
-    type KeyType = ItemLocalId;
-
-    #[inline]
-    fn to_stable_hash_key(&self, _: &HirCtx) -> ItemLocalId {
-        *self
-    }
-}
-
 impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for BodyId {
     type KeyType = (DefPathHash, ItemLocalId);
 
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index f68dad3a5e8..dcac51b10b4 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -79,6 +79,8 @@ impl Display for Target {
     }
 }
 
+rustc_error_messages::into_diag_arg_using_display!(Target);
+
 impl Target {
     pub fn is_associated_item(self) -> bool {
         match self {
diff --git a/compiler/rustc_hir/src/version.rs b/compiler/rustc_hir/src/version.rs
index ab5ab026b4c..bc2c38a4935 100644
--- a/compiler/rustc_hir/src/version.rs
+++ b/compiler/rustc_hir/src/version.rs
@@ -1,6 +1,8 @@
+use std::borrow::Cow;
 use std::fmt::{self, Display};
 use std::sync::OnceLock;
 
+use rustc_error_messages::{DiagArgValue, IntoDiagArg};
 use rustc_macros::{
     Decodable, Encodable, HashStable_Generic, PrintAttribute, current_rustc_version,
 };
@@ -45,3 +47,9 @@ impl Display for RustcVersion {
         write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
     }
 }
+
+impl IntoDiagArg for RustcVersion {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self.to_string()))
+    }
+}
diff --git a/compiler/rustc_hir_id/Cargo.toml b/compiler/rustc_hir_id/Cargo.toml
new file mode 100644
index 00000000000..c357a4f62d9
--- /dev/null
+++ b/compiler/rustc_hir_id/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "rustc_hir_id"
+version = "0.0.0"
+edition = "2024"
+
+[dependencies]
+# tidy-alphabetical-start
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_index = { path = "../rustc_index" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_serialize = { path = "../rustc_serialize" }
+rustc_span = { path = "../rustc_span" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir_id/src/lib.rs
index b48a081d371..d07bc88e66a 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir_id/src/lib.rs
@@ -1,11 +1,15 @@
+//! Library containing Id types from `rustc_hir`, split out so crates can use it without depending
+//! on all of `rustc_hir` (which is large and depends on other large things like `rustc_target`).
+#![allow(internal_features)]
+#![feature(negative_impls)]
+#![feature(rustc_attrs)]
+
 use std::fmt::{self, Debug};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::HashStableContext;
-use rustc_span::def_id::DefPathHash;
-
-use crate::def_id::{CRATE_DEF_ID, DefId, DefIndex, LocalDefId};
+pub use rustc_span::HashStableContext;
+use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId};
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub struct OwnerId {
@@ -171,3 +175,22 @@ pub const CRATE_HIR_ID: HirId =
     HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::ZERO };
 
 pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID };
+
+impl<CTX: rustc_span::HashStableContext> ToStableHashKey<CTX> for HirId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &CTX) -> (DefPathHash, ItemLocalId) {
+        let def_path_hash = self.owner.def_id.to_stable_hash_key(hcx);
+        (def_path_hash, self.local_id)
+    }
+}
+
+impl<CTX: HashStableContext> ToStableHashKey<CTX> for ItemLocalId {
+    type KeyType = ItemLocalId;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &CTX) -> ItemLocalId {
+        *self
+    }
+}
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index c485e6fc849..f26e5f05e1a 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -732,7 +732,7 @@ 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} `{$ident}` in this scope
+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
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 8006cfcf30f..c3c0a34df71 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -3097,7 +3097,7 @@ impl EarlyLintPass for SpecialModuleName {
             if let ast::ItemKind::Mod(
                 _,
                 ident,
-                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _),
+                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No { .. }, _),
             ) = item.kind
             {
                 if item.attrs.iter().any(|a| a.has_name(sym::path)) {
diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs
index 678d3d1f8ed..0e283ed923a 100644
--- a/compiler/rustc_lint/src/early/diagnostics.rs
+++ b/compiler/rustc_lint/src/early/diagnostics.rs
@@ -64,10 +64,12 @@ pub fn decorate_builtin_lint(
             }
             .decorate_lint(diag);
         }
-        BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident } => {
-            lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident }
-                .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)
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index a6d59af6900..a1e26bf1503 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -8,7 +8,6 @@ use rustc_errors::{
     EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle,
 };
 use rustc_hir as hir;
-use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::VisitorExt;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
@@ -2769,7 +2768,7 @@ pub(crate) struct AbsPathWithModuleSugg {
 pub(crate) struct ProcMacroDeriveResolutionFallback {
     #[label]
     pub span: Span,
-    pub ns: Namespace,
+    pub ns_descr: &'static str,
     pub ident: Ident,
 }
 
diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml
index 9ab350daf69..152eb4fb380 100644
--- a/compiler/rustc_lint_defs/Cargo.toml
+++ b/compiler/rustc_lint_defs/Cargo.toml
@@ -9,7 +9,7 @@ rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" }
-rustc_hir = { path = "../rustc_hir" }
+rustc_hir_id = { path = "../rustc_hir_id" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 3bb7bbce567..d1f5cc21277 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -1,3 +1,5 @@
+use std::borrow::Cow;
+
 use rustc_abi::ExternAbi;
 use rustc_ast::AttrId;
 use rustc_ast::attr::AttributeExt;
@@ -6,11 +8,10 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{
     HashStable, StableCompare, StableHasher, ToStableHashKey,
 };
-use rustc_error_messages::{DiagMessage, MultiSpan};
-use rustc_hir::def::Namespace;
-use rustc_hir::def_id::DefPathHash;
-use rustc_hir::{HashStableContext, HirId, ItemLocalId};
+use rustc_error_messages::{DiagArgValue, DiagMessage, IntoDiagArg, MultiSpan};
+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 serde::{Deserialize, Serialize};
@@ -138,7 +139,7 @@ impl LintExpectationId {
     }
 }
 
-impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId {
+impl<HCX: HashStableContext> HashStable<HCX> for LintExpectationId {
     #[inline]
     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
         match self {
@@ -156,7 +157,7 @@ impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId {
     }
 }
 
-impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectationId {
+impl<HCX: HashStableContext> ToStableHashKey<HCX> for LintExpectationId {
     type KeyType = (DefPathHash, ItemLocalId, u16, u16);
 
     #[inline]
@@ -297,6 +298,12 @@ impl Level {
     }
 }
 
+impl IntoDiagArg for Level {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
+    }
+}
+
 /// Specification of a single lint.
 #[derive(Copy, Clone, Debug)]
 pub struct Lint {
@@ -617,7 +624,7 @@ pub enum BuiltinLintDiag {
     AbsPathWithModule(Span),
     ProcMacroDeriveResolutionFallback {
         span: Span,
-        ns: Namespace,
+        ns_descr: &'static str,
         ident: Ident,
     },
     MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 5bdde3a514e..32f91bfba6b 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -760,6 +760,9 @@ pub enum DynCompatibilityViolation {
     // Supertrait has a non-lifetime `for<T>` binder.
     SupertraitNonLifetimeBinder(SmallVec<[Span; 1]>),
 
+    // Trait has a `const Trait` supertrait.
+    SupertraitConst(SmallVec<[Span; 1]>),
+
     /// Method has something illegal.
     Method(Symbol, MethodViolationCode, Span),
 
@@ -785,6 +788,9 @@ impl DynCompatibilityViolation {
             DynCompatibilityViolation::SupertraitNonLifetimeBinder(_) => {
                 "where clause cannot reference non-lifetime `for<...>` variables".into()
             }
+            DynCompatibilityViolation::SupertraitConst(_) => {
+                "it cannot have a `const` supertrait".into()
+            }
             DynCompatibilityViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
                 format!("associated function `{name}` has no `self` parameter").into()
             }
@@ -842,7 +848,8 @@ impl DynCompatibilityViolation {
         match self {
             DynCompatibilityViolation::SizedSelf(_)
             | DynCompatibilityViolation::SupertraitSelf(_)
-            | DynCompatibilityViolation::SupertraitNonLifetimeBinder(..) => {
+            | DynCompatibilityViolation::SupertraitNonLifetimeBinder(..)
+            | DynCompatibilityViolation::SupertraitConst(_) => {
                 DynCompatibilityViolationSolution::None
             }
             DynCompatibilityViolation::Method(
@@ -873,15 +880,17 @@ impl DynCompatibilityViolation {
         match self {
             DynCompatibilityViolation::SupertraitSelf(spans)
             | DynCompatibilityViolation::SizedSelf(spans)
-            | DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans) => spans.clone(),
+            | DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)
+            | DynCompatibilityViolation::SupertraitConst(spans) => spans.clone(),
             DynCompatibilityViolation::AssocConst(_, span)
             | DynCompatibilityViolation::GAT(_, span)
-            | DynCompatibilityViolation::Method(_, _, span)
-                if *span != DUMMY_SP =>
-            {
-                smallvec![*span]
+            | DynCompatibilityViolation::Method(_, _, span) => {
+                if *span != DUMMY_SP {
+                    smallvec![*span]
+                } else {
+                    smallvec![]
+                }
             }
-            _ => smallvec![],
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index b3042904a29..b9a6f67ab0d 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -23,7 +23,7 @@ impl IntoDiagArg for Ty<'_> {
     fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
         ty::tls::with(|tcx| {
             let ty = tcx.short_string(self, path);
-            rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(ty))
+            DiagArgValue::Str(std::borrow::Cow::Owned(ty))
         })
     }
 }
@@ -32,7 +32,7 @@ impl IntoDiagArg for Instance<'_> {
     fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
         ty::tls::with(|tcx| {
             let instance = tcx.short_string_namespace(self, path, Namespace::ValueNS);
-            rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(instance))
+            DiagArgValue::Str(std::borrow::Cow::Owned(instance))
         })
     }
 }
diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs
index d4b6da2c14b..e0cbe8519ed 100644
--- a/compiler/rustc_mir_build/src/check_tail_calls.rs
+++ b/compiler/rustc_mir_build/src/check_tail_calls.rs
@@ -135,30 +135,23 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
             self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi);
         }
 
+        // FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
+        // e.g.
+        // ```
+        // fn a() -> impl Sized { become b() } // ICE
+        // fn b() -> u8 { 0 }
+        // ```
+        // we should think what is the expected behavior here.
+        // (we should probably just accept this by revealing opaques?)
         if caller_sig.inputs_and_output != callee_sig.inputs_and_output {
-            if caller_sig.inputs() != callee_sig.inputs() {
-                self.report_arguments_mismatch(
-                    expr.span,
-                    self.tcx.liberate_late_bound_regions(
-                        CRATE_DEF_ID.to_def_id(),
-                        self.caller_ty.fn_sig(self.tcx),
-                    ),
-                    self.tcx
-                        .liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)),
-                );
-            }
-
-            // FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
-            // e.g.
-            // ```
-            // fn a() -> impl Sized { become b() } // ICE
-            // fn b() -> u8 { 0 }
-            // ```
-            // we should think what is the expected behavior here.
-            // (we should probably just accept this by revealing opaques?)
-            if caller_sig.output() != callee_sig.output() {
-                span_bug!(expr.span, "hir typeck should have checked the return type already");
-            }
+            self.report_signature_mismatch(
+                expr.span,
+                self.tcx.liberate_late_bound_regions(
+                    CRATE_DEF_ID.to_def_id(),
+                    self.caller_ty.fn_sig(self.tcx),
+                ),
+                self.tcx.liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)),
+            );
         }
 
         {
@@ -365,7 +358,7 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
         self.found_errors = Err(err);
     }
 
-    fn report_arguments_mismatch(
+    fn report_signature_mismatch(
         &mut self,
         sp: Span,
         caller_sig: ty::FnSig<'_>,
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 293bcbef21b..9621f9f20bd 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -13,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_graphviz = { path = "../rustc_graphviz" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index f86a15a8f92..372a3f3a8b8 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -8,7 +8,6 @@ use std::sync::OnceLock;
 use std::{io, ops, str};
 
 use regex::Regex;
-use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_middle::mir::{
     self, BasicBlock, Body, Location, create_dump_file, dump_enabled, graphviz_safe_def_name,
@@ -16,6 +15,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_span::def_id::DefId;
 use rustc_span::{Symbol, sym};
 use tracing::debug;
 use {rustc_ast as ast, rustc_graphviz as dot};
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 1682f332857..a899ec1fa88 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -1,7 +1,7 @@
 use rustc_ast::MetaItem;
-use rustc_hir::def_id::DefId;
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::def_id::DefId;
 use rustc_span::{Span, Symbol, sym};
 use tracing::{debug, info};
 
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index ca89eb1e2cf..fd9fb65417c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -43,7 +43,7 @@ impl<'a> Parser<'a> {
             self.expect(exp!(OpenBrace))?;
             let (inner_attrs, items, inner_span) = self.parse_mod(exp!(CloseBrace))?;
             attrs.extend(inner_attrs);
-            ModKind::Loaded(items, Inline::Yes, inner_span, Ok(()))
+            ModKind::Loaded(items, Inline::Yes, inner_span)
         };
         Ok(ItemKind::Mod(safety, ident, mod_kind))
     }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index e0d8fce0685..f75a625a279 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -11,7 +11,7 @@ use std::sync::Arc;
 use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
 use rustc_ast::{
     self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
-    ForeignItemKind, Item, ItemKind, NodeId, StaticItem, StmtKind, TyAlias,
+    ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TyAlias,
 };
 use rustc_attr_parsing as attr;
 use rustc_attr_parsing::AttributeParser;
@@ -813,7 +813,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             ItemKind::Mod(_, ident, ref mod_kind) => {
                 self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion);
 
-                if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
+                if let ast::ModKind::Loaded(_, Inline::No { had_parse_error: Err(_) }, _) = mod_kind
+                {
                     self.r.mods_with_parse_errors.insert(def_id);
                 }
                 self.parent_scope.module = self.r.new_local_module(
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index ff39ba46d97..64641ecc080 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -3410,7 +3410,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
 
     fn visit_item(&mut self, item: &'tcx ast::Item) {
         if self.target_module == item.id {
-            if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
+            if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
                 let inject = mod_spans.inject_use_span;
                 if is_span_suitable_for_use_injection(inject) {
                     self.first_legal_span = Some(inject);
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index c1b3aff4e69..650154d586f 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -528,7 +528,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                                         orig_ident.span,
                                         BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
                                             span: orig_ident.span,
-                                            ns,
+                                            ns_descr: ns.descr(),
                                             ident,
                                         },
                                     );
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index 56932c24922..57c90a703f1 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2024"
 bitflags = "2.4.1"
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 2aa8ab5d317..399770022b2 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -50,6 +50,7 @@ use rustc_abi::{
     Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
 };
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_error_messages::{DiagArgValue, IntoDiagArg, into_diag_arg_using_display};
 use rustc_fs_util::try_canonicalize;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -875,6 +876,12 @@ impl FromStr for PanicStrategy {
 
 crate::json::serde_deserialize_from_str!(PanicStrategy);
 
+impl IntoDiagArg for PanicStrategy {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
+    }
+}
+
 impl ToJson for PanicStrategy {
     fn to_json(&self) -> Json {
         match *self {
@@ -1518,6 +1525,8 @@ impl fmt::Display for SplitDebuginfo {
     }
 }
 
+into_diag_arg_using_display!(SplitDebuginfo);
+
 #[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize)]
 #[serde(tag = "kind")]
 #[serde(rename_all = "kebab-case")]
@@ -1795,6 +1804,8 @@ impl fmt::Display for StackProtector {
     }
 }
 
+into_diag_arg_using_display!(StackProtector);
+
 #[derive(PartialEq, Clone, Debug)]
 pub enum BinaryFormat {
     Coff,
@@ -3806,3 +3817,5 @@ impl fmt::Display for TargetTuple {
         write!(f, "{}", self.debug_tuple())
     }
 }
+
+into_diag_arg_using_display!(&TargetTuple);
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 bc8c8a44405..953449c6758 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -2878,7 +2878,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 // we check if `TraitB` can be reachable from `S`
                                 // to determine whether to note `TraitA` is sealed trait.
                                 if let ty::Adt(adt, _) = ty.kind() {
-                                    let visibilities = tcx.effective_visibilities(());
+                                    let visibilities = &tcx.resolutions(()).effective_visibilities;
                                     visibilities.effective_vis(local).is_none_or(|v| {
                                         v.at_level(Level::Reexported)
                                             .is_accessible_from(adt.did(), tcx)
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index ea1eed95723..4b493c95d59 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -106,6 +106,10 @@ fn dyn_compatibility_violations_for_trait(
     if !spans.is_empty() {
         violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans));
     }
+    let spans = super_predicates_are_unconditionally_const(tcx, trait_def_id);
+    if !spans.is_empty() {
+        violations.push(DynCompatibilityViolation::SupertraitConst(spans));
+    }
 
     violations
 }
@@ -247,16 +251,31 @@ fn super_predicates_have_non_lifetime_binders(
     tcx: TyCtxt<'_>,
     trait_def_id: DefId,
 ) -> SmallVec<[Span; 1]> {
-    // If non_lifetime_binders is disabled, then exit early
-    if !tcx.features().non_lifetime_binders() {
-        return SmallVec::new();
-    }
     tcx.explicit_super_predicates_of(trait_def_id)
         .iter_identity_copied()
         .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(span))
         .collect()
 }
 
+/// Checks for `const Trait` supertraits. We're okay with `[const] Trait`,
+/// supertraits since for a non-const instantiation of that trait, the
+/// conditionally-const supertrait is also not required to be const.
+fn super_predicates_are_unconditionally_const(
+    tcx: TyCtxt<'_>,
+    trait_def_id: DefId,
+) -> SmallVec<[Span; 1]> {
+    tcx.explicit_super_predicates_of(trait_def_id)
+        .iter_identity_copied()
+        .filter_map(|(pred, span)| {
+            if let ty::ClauseKind::HostEffect(_) = pred.kind().skip_binder() {
+                Some(span)
+            } else {
+                None
+            }
+        })
+        .collect()
+}
+
 fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
     tcx.generics_require_sized_self(trait_def_id)
 }
diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml
index 04aef4e7b9e..9f40f4d5c23 100644
--- a/compiler/rustc_traits/Cargo.toml
+++ b/compiler/rustc_traits/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs
index 8a2a0832ddb..20f9b013724 100644
--- a/compiler/rustc_traits/src/coroutine_witnesses.rs
+++ b/compiler/rustc_traits/src/coroutine_witnesses.rs
@@ -1,9 +1,9 @@
-use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions};
+use rustc_span::def_id::DefId;
 use rustc_trait_selection::traits::{ObligationCtxt, with_replaced_escaping_bound_vars};
 
 /// Return the set of types that should be taken into account when checking
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 5eddad39e2b..d33ade7a9e1 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -1,5 +1,4 @@
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_middle::bug;
@@ -7,6 +6,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
 use rustc_middle::ty::{self, GenericArgs, TyCtxt};
 use rustc_span::DUMMY_SP;
+use rustc_span::def_id::DefId;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::dropck_outlives::{
     compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner,
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index e7fee574dd4..d55e9b3b1be 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -12,6 +12,7 @@ indexmap = "2.0.0"
 rustc-hash = "2.0.0"
 rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
+rustc_error_messages = { path = "../rustc_error_messages", optional = true }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true }
@@ -27,6 +28,7 @@ tracing = "0.1"
 default = ["nightly"]
 nightly = [
     "dep:rustc_data_structures",
+    "dep:rustc_error_messages",
     "dep:rustc_macros",
     "dep:rustc_serialize",
     "dep:rustc_span",
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
index 388ad09cb20..82bb8791b84 100644
--- a/compiler/rustc_type_ir/src/ir_print.rs
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -1,9 +1,9 @@
 use std::fmt;
 
 use crate::{
-    AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
-    HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, PatternKind,
-    ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+    AliasTerm, AliasTy, Binder, ClosureKind, CoercePredicate, ExistentialProjection,
+    ExistentialTraitRef, FnSig, HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate,
+    PatternKind, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, UnevaluatedConst,
 };
 
 pub trait IrPrint<T> {
@@ -70,3 +70,46 @@ where
         <I as IrPrint<OutlivesPredicate<I, T>>>::print(self, fmt)
     }
 }
+
+#[cfg(feature = "nightly")]
+mod into_diag_arg_impls {
+    use rustc_error_messages::{DiagArgValue, IntoDiagArg};
+
+    use super::*;
+
+    impl<I: Interner> IntoDiagArg for TraitRef<I> {
+        fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+            self.to_string().into_diag_arg(path)
+        }
+    }
+
+    impl<I: Interner> IntoDiagArg for ExistentialTraitRef<I> {
+        fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+            self.to_string().into_diag_arg(path)
+        }
+    }
+
+    impl<I: Interner> IntoDiagArg for UnevaluatedConst<I> {
+        fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+            format!("{self:?}").into_diag_arg(path)
+        }
+    }
+
+    impl<I: Interner> IntoDiagArg for FnSig<I> {
+        fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+            format!("{self:?}").into_diag_arg(path)
+        }
+    }
+
+    impl<I: Interner, T: IntoDiagArg> IntoDiagArg for Binder<I, T> {
+        fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+            self.skip_binder().into_diag_arg(path)
+        }
+    }
+
+    impl IntoDiagArg for ClosureKind {
+        fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
+            DiagArgValue::Str(self.as_str().into())
+        }
+    }
+}
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index b3a498570f9..bb75ec74c81 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -621,11 +621,11 @@ impl<T, const N: usize> [T; N] {
     /// assert_eq!(strings.len(), 3);
     /// ```
     #[stable(feature = "array_methods", since = "1.77.0")]
-    #[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")]
+    #[rustc_const_stable(feature = "const_array_each_ref", since = "CURRENT_RUSTC_VERSION")]
     pub const fn each_ref(&self) -> [&T; N] {
         let mut buf = [null::<T>(); N];
 
-        // FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
+        // FIXME(const_trait_impl): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
         let mut i = 0;
         while i < N {
             buf[i] = &raw const self[i];
@@ -652,11 +652,11 @@ impl<T, const N: usize> [T; N] {
     /// assert_eq!(floats, [0.0, 2.7, -1.0]);
     /// ```
     #[stable(feature = "array_methods", since = "1.77.0")]
-    #[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")]
+    #[rustc_const_stable(feature = "const_array_each_ref", since = "CURRENT_RUSTC_VERSION")]
     pub const fn each_mut(&mut self) -> [&mut T; N] {
         let mut buf = [null_mut::<T>(); N];
 
-        // FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
+        // FIXME(const_trait_impl): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
         let mut i = 0;
         while i < N {
             buf[i] = &raw mut self[i];
diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs
index b18b5d7c9ec..ede6e0d6106 100644
--- a/library/core/src/pin/unsafe_pinned.rs
+++ b/library/core/src/pin/unsafe_pinned.rs
@@ -120,8 +120,8 @@ impl<T: ?Sized> UnsafePinned<T> {
     #[inline(always)]
     #[must_use]
     #[unstable(feature = "unsafe_pinned", issue = "125735")]
-    pub const fn raw_get(this: *const Self) -> *const T {
-        this as *const T
+    pub const fn raw_get(this: *const Self) -> *mut T {
+        this as *const T as *mut T
     }
 
     /// Gets a mutable pointer to the wrapped value.
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index ca668361ef6..59ffe7ad49c 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -125,7 +125,7 @@ impl<T, E> Poll<Result<T, E>> {
         }
     }
 
-    /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, F>>` by
+    /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, U>>` by
     /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other
     /// variants untouched.
     ///
diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs
index 889ed3c5380..6104a02c739 100644
--- a/library/std/src/collections/mod.rs
+++ b/library/std/src/collections/mod.rs
@@ -26,7 +26,7 @@
 //! should be considered. Detailed discussions of strengths and weaknesses of
 //! individual collections can be found on their own documentation pages.
 //!
-//! ### Use a `Vec` when:
+//! ### Use a [`Vec`] when:
 //! * You want to collect items up to be processed or sent elsewhere later, and
 //!   don't care about any properties of the actual values being stored.
 //! * You want a sequence of elements in a particular order, and will only be
@@ -35,25 +35,25 @@
 //! * You want a resizable array.
 //! * You want a heap-allocated array.
 //!
-//! ### Use a `VecDeque` when:
+//! ### Use a [`VecDeque`] when:
 //! * You want a [`Vec`] that supports efficient insertion at both ends of the
 //!   sequence.
 //! * You want a queue.
 //! * You want a double-ended queue (deque).
 //!
-//! ### Use a `LinkedList` when:
+//! ### Use a [`LinkedList`] when:
 //! * You want a [`Vec`] or [`VecDeque`] of unknown size, and can't tolerate
 //!   amortization.
 //! * You want to efficiently split and append lists.
 //! * You are *absolutely* certain you *really*, *truly*, want a doubly linked
 //!   list.
 //!
-//! ### Use a `HashMap` when:
+//! ### Use a [`HashMap`] when:
 //! * You want to associate arbitrary keys with an arbitrary value.
 //! * You want a cache.
 //! * You want a map, with no extra functionality.
 //!
-//! ### Use a `BTreeMap` when:
+//! ### Use a [`BTreeMap`] when:
 //! * You want a map sorted by its keys.
 //! * You want to be able to get a range of entries on-demand.
 //! * You're interested in what the smallest or largest key-value pair is.
@@ -65,7 +65,7 @@
 //! * There is no meaningful value to associate with your keys.
 //! * You just want a set.
 //!
-//! ### Use a `BinaryHeap` when:
+//! ### Use a [`BinaryHeap`] when:
 //!
 //! * You want to store a bunch of elements, but only ever want to process the
 //!   "biggest" or "most important" one at any given time.
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 562fdbf4ff7..dcfa189823f 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -18,7 +18,7 @@ use crate::{error, fmt, result, sys};
 /// This type is broadly used across [`std::io`] for any operation which may
 /// produce an error.
 ///
-/// This typedef is generally used to avoid writing out [`io::Error`] directly and
+/// This type alias is generally used to avoid writing out [`io::Error`] directly and
 /// is otherwise a direct mapping to [`Result`].
 ///
 /// While usual Rust style is to import types directly, aliases of [`Result`]
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index 7ee9f3c445a..0d710a4b2a6 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -1265,6 +1265,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     ))]
     pub fn lock(&self) -> io::Result<()> {
@@ -1278,6 +1279,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     )))]
     pub fn lock(&self) -> io::Result<()> {
@@ -1290,6 +1292,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     ))]
     pub fn lock_shared(&self) -> io::Result<()> {
@@ -1303,6 +1306,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     )))]
     pub fn lock_shared(&self) -> io::Result<()> {
@@ -1315,6 +1319,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     ))]
     pub fn try_lock(&self) -> Result<(), TryLockError> {
@@ -1336,6 +1341,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     )))]
     pub fn try_lock(&self) -> Result<(), TryLockError> {
@@ -1351,6 +1357,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     ))]
     pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
@@ -1372,6 +1379,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     )))]
     pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
@@ -1387,6 +1395,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     ))]
     pub fn unlock(&self) -> io::Result<()> {
@@ -1400,6 +1409,7 @@ impl File {
         target_os = "linux",
         target_os = "netbsd",
         target_os = "openbsd",
+        target_os = "cygwin",
         target_vendor = "apple",
     )))]
     pub fn unlock(&self) -> io::Result<()> {
diff --git a/library/std_detect/src/detect/os/riscv.rs b/library/std_detect/src/detect/os/riscv.rs
index c6acbd3525b..9b9e0cba09d 100644
--- a/library/std_detect/src/detect/os/riscv.rs
+++ b/library/std_detect/src/detect/os/riscv.rs
@@ -119,11 +119,31 @@ pub(crate) fn imply_features(mut value: cache::Initializer) -> cache::Initialize
         imply!(d | zfhmin | zfa => f);
         imply!(zfbfmin => f); // and some of (not all) "Zfh" instructions.
 
-        // Relatively complex implication rules from the "C" extension.
+        // Relatively complex implication rules around the "C" extension.
+        // (from "C" and some others)
         imply!(c => zca);
         imply!(c & d => zcd);
         #[cfg(target_arch = "riscv32")]
         imply!(c & f => zcf);
+        // (to "C"; defined as superset)
+        cfg_select! {
+            target_arch = "riscv32" => {
+                if value.test(Feature::d as u32) {
+                    imply!(zcf & zcd => c);
+                } else if value.test(Feature::f as u32) {
+                    imply!(zcf => c);
+                } else {
+                    imply!(zca => c);
+                }
+            }
+            _ => {
+                if value.test(Feature::d as u32) {
+                    imply!(zcd => c);
+                } else {
+                    imply!(zca => c);
+                }
+            }
+        }
 
         imply!(zicntr | zihpm | f | zfinx | zve32x => zicsr);
 
diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs
index 2b36b0f2e27..77c9622a9bf 100644
--- a/src/bootstrap/src/core/build_steps/gcc.rs
+++ b/src/bootstrap/src/core/build_steps/gcc.rs
@@ -122,7 +122,7 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<Pa
     match source {
         PathFreshness::LastModifiedUpstream { upstream } => {
             // Download from upstream CI
-            let root = ci_gcc_root(&builder.config);
+            let root = ci_gcc_root(&builder.config, target);
             let gcc_stamp = BuildStamp::new(&root).with_prefix("gcc").add_stamp(&upstream);
             if !gcc_stamp.is_up_to_date() && !builder.config.dry_run() {
                 builder.config.download_ci_gcc(&upstream, &root);
@@ -286,8 +286,8 @@ pub fn add_cg_gcc_cargo_flags(cargo: &mut Cargo, gcc: &GccOutput) {
 
 /// The absolute path to the downloaded GCC artifacts.
 #[cfg(not(test))]
-fn ci_gcc_root(config: &crate::Config) -> PathBuf {
-    config.out.join(config.host_target).join("ci-gcc")
+fn ci_gcc_root(config: &crate::Config, target: TargetSelection) -> PathBuf {
+    config.out.join(target).join("ci-gcc")
 }
 
 /// Detect whether GCC sources have been modified locally or not.
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index e7a57a7f375..56e7582a6ff 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1830,10 +1830,27 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         cmd.arg("--host").arg(&*compiler.host.triple);
         cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
 
-        if let Some(codegen_backend) = builder.config.default_codegen_backend(compiler.host) {
-            // Tells compiletest which codegen backend is used by default by the compiler.
+        if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
+            if !builder.config.enabled_codegen_backends(compiler.host).contains(codegen_backend) {
+                eprintln!(
+                    "\
+ERROR: No configured backend named `{name}`
+HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
+                    name = codegen_backend.name(),
+                );
+                crate::exit!(1);
+            }
+            // Tells compiletest that we want to use this codegen in particular and to override
+            // the default one.
+            cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
+            // Tells compiletest which codegen backend to use.
+            // It is used to e.g. ignore tests that don't support that codegen backend.
+            cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
+        } else {
+            // Tells compiletest which codegen backend to use.
             // It is used to e.g. ignore tests that don't support that codegen backend.
-            cmd.arg("--codegen-backend").arg(codegen_backend.name());
+            cmd.arg("--default-codegen-backend")
+                .arg(builder.config.default_codegen_backend(compiler.host).unwrap().name());
         }
 
         if builder.build.config.llvm_enzyme {
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 69a744a86cb..72192403412 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -1326,7 +1326,12 @@ impl Builder<'_> {
 
             if let Some(limit) = limit
                 && (build_compiler_stage == 0
-                    || self.config.default_codegen_backend(target).unwrap_or_default().is_llvm())
+                    || self
+                        .config
+                        .default_codegen_backend(target)
+                        .cloned()
+                        .unwrap_or_default()
+                        .is_llvm())
             {
                 rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
             }
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index a7db96055e6..a2fe546c60a 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -1591,7 +1591,7 @@ mod snapshot {
         insta::assert_snapshot!(
             ctx.config("check")
                 .path("compiler")
-                .render_steps(), @"[check] rustc 0 <host> -> rustc 1 <host> (73 crates)");
+                .render_steps(), @"[check] rustc 0 <host> -> rustc 1 <host> (74 crates)");
     }
 
     #[test]
@@ -1617,7 +1617,7 @@ mod snapshot {
             ctx.config("check")
                 .path("compiler")
                 .stage(1)
-                .render_steps(), @"[check] rustc 0 <host> -> rustc 1 <host> (73 crates)");
+                .render_steps(), @"[check] rustc 0 <host> -> rustc 1 <host> (74 crates)");
     }
 
     #[test]
@@ -1631,7 +1631,7 @@ mod snapshot {
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
-        [check] rustc 1 <host> -> rustc 2 <host> (73 crates)
+        [check] rustc 1 <host> -> rustc 2 <host> (74 crates)
         ");
     }
 
@@ -1647,7 +1647,7 @@ mod snapshot {
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [check] rustc 1 <host> -> std 1 <target1>
-        [check] rustc 1 <host> -> rustc 2 <target1> (73 crates)
+        [check] rustc 1 <host> -> rustc 2 <target1> (74 crates)
         [check] rustc 1 <host> -> rustc 2 <target1>
         [check] rustc 1 <host> -> Rustdoc 2 <target1>
         [check] rustc 1 <host> -> rustc_codegen_cranelift 2 <target1>
@@ -1743,7 +1743,7 @@ mod snapshot {
             ctx.config("check")
                 .paths(&["library", "compiler"])
                 .args(&args)
-                .render_steps(), @"[check] rustc 0 <host> -> rustc 1 <host> (73 crates)");
+                .render_steps(), @"[check] rustc 0 <host> -> rustc 1 <host> (74 crates)");
     }
 
     #[test]
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 5eea5436023..d0647537e56 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1755,8 +1755,8 @@ impl Config {
 
     /// Returns the codegen backend that should be configured as the *default* codegen backend
     /// for a rustc compiled by bootstrap.
-    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<CodegenBackendKind> {
-        self.enabled_codegen_backends(target).first().cloned()
+    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<&CodegenBackendKind> {
+        self.enabled_codegen_backends(target).first()
     }
 
     pub fn jemalloc(&self, target: TargetSelection) -> bool {
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index 17bfb388280..c01b71b9260 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -15,7 +15,7 @@ use crate::core::build_steps::setup::Profile;
 use crate::core::builder::{Builder, Kind};
 use crate::core::config::Config;
 use crate::core::config::target_selection::{TargetSelectionList, target_selection_list};
-use crate::{Build, DocTests};
+use crate::{Build, CodegenBackendKind, DocTests};
 
 #[derive(Copy, Clone, Default, Debug, ValueEnum)]
 pub enum Color {
@@ -419,6 +419,9 @@ pub enum Subcommand {
         #[arg(long)]
         /// don't capture stdout/stderr of tests
         no_capture: bool,
+        #[arg(long)]
+        /// Use a different codegen backend when running tests.
+        test_codegen_backend: Option<CodegenBackendKind>,
     },
     /// Build and run some test suites *in Miri*
     Miri {
@@ -658,6 +661,13 @@ impl Subcommand {
             _ => vec![],
         }
     }
+
+    pub fn test_codegen_backend(&self) -> Option<&CodegenBackendKind> {
+        match self {
+            Subcommand::Test { test_codegen_backend, .. } => test_codegen_backend.as_ref(),
+            _ => None,
+        }
+    }
 }
 
 /// Returns the shell completion for a given shell, if the result differs from the current
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 8f766ed00a5..ec7edbf7531 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -165,6 +165,20 @@ impl CodegenBackendKind {
     }
 }
 
+impl std::str::FromStr for CodegenBackendKind {
+    type Err = &'static str;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s.to_lowercase().as_str() {
+            "" => Err("Invalid empty backend name"),
+            "gcc" => Ok(Self::Gcc),
+            "llvm" => Ok(Self::Llvm),
+            "cranelift" => Ok(Self::Cranelift),
+            _ => Ok(Self::Custom(s.to_string())),
+        }
+    }
+}
+
 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
 pub enum DocTests {
     /// Run normal tests and doc tests (default).
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index b2f9960a449..4fb5891ed18 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -507,6 +507,11 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         summary: "It is no longer possible to `x clippy` with stage 0. All clippy commands have to be on stage 1+.",
     },
     ChangeInfo {
+        change_id: 145256,
+        severity: ChangeSeverity::Info,
+        summary: "Added `--test-codegen-backend` CLI option for tests",
+    },
+    ChangeInfo {
         change_id: 145379,
         severity: ChangeSeverity::Info,
         summary: "Build/check now supports forwarding `--timings` flag to cargo.",
diff --git a/src/etc/completions/x.fish b/src/etc/completions/x.fish
index 0b9af334214..544f9b97237 100644
--- a/src/etc/completions/x.fish
+++ b/src/etc/completions/x.fish
@@ -305,6 +305,7 @@ complete -c x -n "__fish_x_using_subcommand test" -l extra-checks -d 'comma-sepa
 complete -c x -n "__fish_x_using_subcommand test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r
 complete -c x -n "__fish_x_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r
 complete -c x -n "__fish_x_using_subcommand test" -l run -d 'whether to execute run-* tests' -r
+complete -c x -n "__fish_x_using_subcommand test" -l test-codegen-backend -d 'Use a different codegen backend when running tests' -r
 complete -c x -n "__fish_x_using_subcommand test" -l config -d 'TOML configuration file for build' -r -F
 complete -c x -n "__fish_x_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)"
 complete -c x -n "__fish_x_using_subcommand test" -l build -d 'host target of the stage0 compiler' -r -f
diff --git a/src/etc/completions/x.ps1 b/src/etc/completions/x.ps1
index 95cee4b6336..b03acf930f7 100644
--- a/src/etc/completions/x.ps1
+++ b/src/etc/completions/x.ps1
@@ -351,6 +351,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock {
             [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to')
             [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode')
             [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests')
+            [CompletionResult]::new('--test-codegen-backend', '--test-codegen-backend', [CompletionResultType]::ParameterName, 'Use a different codegen backend when running tests')
             [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
             [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`')
             [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler')
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 6fba6a45623..08e4cd26ce8 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -305,6 +305,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand test" -l extra-checks -d 'comm
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l run -d 'whether to execute run-* tests' -r
+complete -c x.py -n "__fish_x.py_using_subcommand test" -l test-codegen-backend -d 'Use a different codegen backend when running tests' -r
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l config -d 'TOML configuration file for build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)"
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l build -d 'host target of the stage0 compiler' -r -f
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index 458879a17a7..3d95d88af49 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -351,6 +351,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to')
             [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode')
             [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests')
+            [CompletionResult]::new('--test-codegen-backend', '--test-codegen-backend', [CompletionResultType]::ParameterName, 'Use a different codegen backend when running tests')
             [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
             [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`')
             [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index e003bf7fd0b..8ff0eaf35c8 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -3875,7 +3875,7 @@ _x.py() {
             return 0
             ;;
         x.py__test)
-            opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -3905,6 +3905,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --test-codegen-backend)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
                 --config)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh
index b82c2d65e86..9d2d73e582e 100644
--- a/src/etc/completions/x.py.zsh
+++ b/src/etc/completions/x.py.zsh
@@ -351,6 +351,7 @@ _arguments "${_arguments_options[@]}" : \
 '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \
 '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \
 '--run=[whether to execute run-* tests]:auto | always | never:_default' \
+'--test-codegen-backend=[Use a different codegen backend when running tests]:TEST_CODEGEN_BACKEND:_default' \
 '--config=[TOML configuration file for build]:FILE:_files' \
 '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \
 '--build=[host target of the stage0 compiler]:BUILD:' \
diff --git a/src/etc/completions/x.sh b/src/etc/completions/x.sh
index c2cb7710020..c1b73fb7c9e 100644
--- a/src/etc/completions/x.sh
+++ b/src/etc/completions/x.sh
@@ -3875,7 +3875,7 @@ _x() {
             return 0
             ;;
         x__test)
-            opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -3905,6 +3905,10 @@ _x() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --test-codegen-backend)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
                 --config)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
diff --git a/src/etc/completions/x.zsh b/src/etc/completions/x.zsh
index 49139e70f7f..29237ef9bf8 100644
--- a/src/etc/completions/x.zsh
+++ b/src/etc/completions/x.zsh
@@ -351,6 +351,7 @@ _arguments "${_arguments_options[@]}" : \
 '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \
 '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \
 '--run=[whether to execute run-* tests]:auto | always | never:_default' \
+'--test-codegen-backend=[Use a different codegen backend when running tests]:TEST_CODEGEN_BACKEND:_default' \
 '--config=[TOML configuration file for build]:FILE:_files' \
 '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \
 '--build=[host target of the stage0 compiler]:BUILD:' \
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index d55208150b8..42b87d56252 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -5252,7 +5252,7 @@ if (typeof window !== "undefined") {
         },
         loadTreeByHash: hashHex => {
             const script = document.createElement("script");
-            script.src = `${ROOT_PATH}/search.index/${hashHex}.js`;
+            script.src = `${ROOT_PATH}search.index/${hashHex}.js`;
             script.onerror = e => {
                 if (databaseCallbacks) {
                     databaseCallbacks.err_rn_(hashHex, e);
@@ -5262,7 +5262,7 @@ if (typeof window !== "undefined") {
         },
         loadDataByNameAndHash: (name, hashHex) => {
             const script = document.createElement("script");
-            script.src = `${ROOT_PATH}/search.index/${name}/${hashHex}.js`;
+            script.src = `${ROOT_PATH}search.index/${name}/${hashHex}.js`;
             script.onerror = e => {
                 if (databaseCallbacks) {
                     databaseCallbacks.err_rd_(hashHex, e);
diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
index ce551a64d99..759b7b6837b 100644
--- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
+++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
@@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
 
 impl EarlyLintPass for DuplicateMod {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
+        if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No { .. }, mod_spans)) = &item.kind
             && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
             && let Some(local_path) = real.into_local_path()
             && let Ok(absolute_path) = local_path.canonicalize()
diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
index 3bd74856165..76e67b1154b 100644
--- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
@@ -442,7 +442,7 @@ impl EmptyLineAfter {
                 None => span.shrink_to_lo(),
             },
             mod_items: match kind {
-                ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items
+                ItemKind::Mod(_, _, ModKind::Loaded(items, _, _)) => items
                     .iter()
                     .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
                     .map(|i| i.id)
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
index 1d3ae894944..5368701c304 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -164,7 +164,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> {
         }
 
         match &item.kind {
-            ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => {
+            ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => {
                 self.nest_level += 1;
 
                 if !self.check_indent(item.span, item.id) {
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 24e017f7cf7..d80a9d9dd07 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -403,7 +403,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
             ls == rs
                 && eq_id(*li, *ri)
                 && match (lmk, rmk) {
-                    (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
+                    (ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => {
                         linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
                     },
                     (ModKind::Unloaded, ModKind::Unloaded) => true,
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 2d49b1a7097..7fc80c1edb1 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -692,7 +692,9 @@ pub struct Config {
     pub minicore_path: Utf8PathBuf,
 
     /// Current codegen backend used.
-    pub codegen_backend: CodegenBackend,
+    pub default_codegen_backend: CodegenBackend,
+    /// Name/path of the backend to use instead of `default_codegen_backend`.
+    pub override_codegen_backend: Option<String>,
 }
 
 impl Config {
@@ -796,7 +798,8 @@ impl Config {
             profiler_runtime: Default::default(),
             diff_command: Default::default(),
             minicore_path: Default::default(),
-            codegen_backend: CodegenBackend::Llvm,
+            default_codegen_backend: CodegenBackend::Llvm,
+            override_codegen_backend: None,
         }
     }
 
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 13e694b7f03..00007aa1d66 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -1624,7 +1624,7 @@ fn ignore_backends(
                 }
             }
         }) {
-            if config.codegen_backend == backend {
+            if config.default_codegen_backend == backend {
                 return IgnoreDecision::Ignore {
                     reason: format!("{} backend is marked as ignore", backend.as_str()),
                 };
@@ -1651,12 +1651,12 @@ fn needs_backends(
                     panic!("Invalid needs-backends value `{backend}` in `{path}`: {error}")
                 }
             })
-            .any(|backend| config.codegen_backend == backend)
+            .any(|backend| config.default_codegen_backend == backend)
         {
             return IgnoreDecision::Ignore {
                 reason: format!(
                     "{} backend is not part of required backends",
-                    config.codegen_backend.as_str()
+                    config.default_codegen_backend.as_str()
                 ),
             };
         }
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index f5409e78341..469dd68207e 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -212,9 +212,15 @@ pub fn parse_config(args: Vec<String>) -> Config {
         )
         .optopt(
             "",
-            "codegen-backend",
+            "default-codegen-backend",
             "the codegen backend currently used",
             "CODEGEN BACKEND NAME",
+        )
+        .optopt(
+            "",
+            "override-codegen-backend",
+            "the codegen backend to use instead of the default one",
+            "CODEGEN BACKEND [NAME | PATH]",
         );
 
     let (argv0, args_) = args.split_first().unwrap();
@@ -276,14 +282,17 @@ pub fn parse_config(args: Vec<String>) -> Config {
             || directives::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
         );
 
-    let codegen_backend = match matches.opt_str("codegen-backend").as_deref() {
+    let default_codegen_backend = match matches.opt_str("default-codegen-backend").as_deref() {
         Some(backend) => match CodegenBackend::try_from(backend) {
             Ok(backend) => backend,
-            Err(error) => panic!("invalid value `{backend}` for `--codegen-backend`: {error}"),
+            Err(error) => {
+                panic!("invalid value `{backend}` for `--defalt-codegen-backend`: {error}")
+            }
         },
         // By default, it's always llvm.
         None => CodegenBackend::Llvm,
     };
+    let override_codegen_backend = matches.opt_str("override-codegen-backend");
 
     let run_ignored = matches.opt_present("ignored");
     let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
@@ -472,7 +481,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
         minicore_path: opt_path(matches, "minicore-path"),
 
-        codegen_backend,
+        default_codegen_backend,
+        override_codegen_backend,
     }
 }
 
@@ -812,13 +822,13 @@ fn collect_tests_from_dir(
         && let Some(Utf8Component::Normal(parent)) = components.next()
         && parent == "tests"
         && let Ok(backend) = CodegenBackend::try_from(backend)
-        && backend != cx.config.codegen_backend
+        && backend != cx.config.default_codegen_backend
     {
         // We ignore asm tests which don't match the current codegen backend.
         warning!(
             "Ignoring tests in `{dir}` because they don't match the configured codegen \
              backend (`{}`)",
-            cx.config.codegen_backend.as_str(),
+            cx.config.default_codegen_backend.as_str(),
         );
         return Ok(TestCollector::new());
     }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 821cb128647..2402ed9a950 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1558,6 +1558,11 @@ impl<'test> TestCx<'test> {
             rustc.arg("--sysroot").arg(&self.config.sysroot_base);
         }
 
+        // If the provided codegen backend is not LLVM, we need to pass it.
+        if let Some(ref backend) = self.config.override_codegen_backend {
+            rustc.arg(format!("-Zcodegen-backend={}", backend));
+        }
+
         // Optionally prevent default --target if specified in test compile-flags.
         let custom_target = self.props.compile_flags.iter().any(|x| x.starts_with("--target"));
 
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 10df6f96702..6555679c394 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -3600,7 +3600,7 @@ pub(crate) fn rewrite_extern_crate(
 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
     !matches!(
         item.kind,
-        ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
+        ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _))
     )
 }
 
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 3bc656b64b3..af9feccb32e 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -316,11 +316,12 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
             self.directory = directory;
         }
         match (sub_mod.ast_mod_kind, sub_mod.items) {
-            (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _, _))), _) => {
+            (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
                 self.visit_mod_from_ast(items)
             }
-            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _, _))), _)
-            | (_, Cow::Owned(items)) => self.visit_mod_outside_ast(items),
+            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
+                self.visit_mod_outside_ast(items)
+            }
             (_, _) => Ok(()),
         }
     }
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 23d07c930d9..a3acbb218ff 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -942,7 +942,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         let ident_str = rewrite_ident(&self.get_context(), ident).to_owned();
         self.push_str(&ident_str);
 
-        if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans, _) = mod_kind {
+        if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans) = mod_kind {
             let ast::ModSpans {
                 inner_span,
                 inject_use_span: _,
diff --git a/tests/codegen-llvm/abi-x86-interrupt.rs b/tests/codegen-llvm/abi-x86-interrupt.rs
index 9a1ded2c9e3..b5c495803d8 100644
--- a/tests/codegen-llvm/abi-x86-interrupt.rs
+++ b/tests/codegen-llvm/abi-x86-interrupt.rs
@@ -15,4 +15,4 @@ use minicore::*;
 
 // CHECK: define x86_intrcc void @has_x86_interrupt_abi
 #[no_mangle]
-pub extern "x86-interrupt" fn has_x86_interrupt_abi() {}
+pub extern "x86-interrupt" fn has_x86_interrupt_abi(_p: *const u8) {}
diff --git a/tests/codegen-llvm/naked-asan.rs b/tests/codegen-llvm/naked-asan.rs
index 46218cf79d6..a57e55d1366 100644
--- a/tests/codegen-llvm/naked-asan.rs
+++ b/tests/codegen-llvm/naked-asan.rs
@@ -18,10 +18,10 @@ pub fn caller() {
     unsafe { asm!("call {}", sym page_fault_handler) }
 }
 
-// CHECK: declare x86_intrcc void @page_fault_handler(){{.*}}#[[ATTRS:[0-9]+]]
+// CHECK: declare x86_intrcc void @page_fault_handler(ptr {{.*}}, i64{{.*}}){{.*}}#[[ATTRS:[0-9]+]]
 #[unsafe(naked)]
 #[no_mangle]
-pub extern "x86-interrupt" fn page_fault_handler() {
+pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) {
     naked_asm!("ud2")
 }
 
diff --git a/tests/debuginfo/recursive-struct.rs b/tests/debuginfo/recursive-struct.rs
index 5be90992848..427a7100a4f 100644
--- a/tests/debuginfo/recursive-struct.rs
+++ b/tests/debuginfo/recursive-struct.rs
@@ -62,6 +62,7 @@
 
 use self::Opt::{Empty, Val};
 use std::boxed::Box as B;
+use std::marker::PhantomData;
 
 enum Opt<T> {
     Empty,
@@ -98,6 +99,11 @@ struct LongCycleWithAnonymousTypes {
     value: usize,
 }
 
+struct Expanding<T> {
+    a: PhantomData<T>,
+    b: *const Expanding<(T, T)>,
+}
+
 // This test case makes sure that recursive structs are properly described. The Node structs are
 // generic so that we can have a new type (that newly needs to be described) for the different
 // cases. The potential problem with recursive types is that the DI generation algorithm gets
@@ -205,6 +211,9 @@ fn main() {
         value: 30
     })))));
 
+    // This type can generate new instances infinitely if not handled properly.
+    std::hint::black_box(Expanding::<()> { a: PhantomData, b: std::ptr::null() });
+
     zzz(); // #break
 }
 
diff --git a/tests/ui/abi/cannot-be-called.avr.stderr b/tests/ui/abi/cannot-be-called.avr.stderr
index 1129893cbfa..ed3fa4a20c5 100644
--- a/tests/ui/abi/cannot-be-called.avr.stderr
+++ b/tests/ui/abi/cannot-be-called.avr.stderr
@@ -19,53 +19,53 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
   --> $DIR/cannot-be-called.rs:45:8
    |
-LL | extern "x86-interrupt" fn x86() {}
+LL | extern "x86-interrupt" fn x86(_x: *const u8) {}
    |        ^^^^^^^^^^^^^^^
 
 error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:70:25
+  --> $DIR/cannot-be-called.rs:72:25
    |
 LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
    |                         ^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:76:26
+  --> $DIR/cannot-be-called.rs:78:26
    |
 LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:82:26
+  --> $DIR/cannot-be-called.rs:84:26
    |
 LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:88:22
+  --> $DIR/cannot-be-called.rs:90:22
    |
 LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error: functions with the "avr-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:50:5
+  --> $DIR/cannot-be-called.rs:52:5
    |
 LL |     avr();
    |     ^^^^^
    |
 note: an `extern "avr-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:50:5
+  --> $DIR/cannot-be-called.rs:52:5
    |
 LL |     avr();
    |     ^^^^^
 
 error: functions with the "avr-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:66:5
+  --> $DIR/cannot-be-called.rs:68:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "avr-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:66:5
+  --> $DIR/cannot-be-called.rs:68:5
    |
 LL |     f()
    |     ^^^
diff --git a/tests/ui/abi/cannot-be-called.i686.stderr b/tests/ui/abi/cannot-be-called.i686.stderr
index 024d5e2e93d..6ccb10c44fd 100644
--- a/tests/ui/abi/cannot-be-called.i686.stderr
+++ b/tests/ui/abi/cannot-be-called.i686.stderr
@@ -23,49 +23,49 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
    |        ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "avr-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:64:22
+  --> $DIR/cannot-be-called.rs:66:22
    |
 LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:70:25
+  --> $DIR/cannot-be-called.rs:72:25
    |
 LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
    |                         ^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:76:26
+  --> $DIR/cannot-be-called.rs:78:26
    |
 LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:82:26
+  --> $DIR/cannot-be-called.rs:84:26
    |
 LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error: functions with the "x86-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:58:5
+  --> $DIR/cannot-be-called.rs:60:5
    |
-LL |     x86();
-   |     ^^^^^
+LL |     x86(&raw const BYTE);
+   |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: an `extern "x86-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:58:5
+  --> $DIR/cannot-be-called.rs:60:5
    |
-LL |     x86();
-   |     ^^^^^
+LL |     x86(&raw const BYTE);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: functions with the "x86-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:90:5
+  --> $DIR/cannot-be-called.rs:92:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "x86-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:90:5
+  --> $DIR/cannot-be-called.rs:92:5
    |
 LL |     f()
    |     ^^^
diff --git a/tests/ui/abi/cannot-be-called.msp430.stderr b/tests/ui/abi/cannot-be-called.msp430.stderr
index 52d7d792510..0bd5bb40b71 100644
--- a/tests/ui/abi/cannot-be-called.msp430.stderr
+++ b/tests/ui/abi/cannot-be-called.msp430.stderr
@@ -19,53 +19,53 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
   --> $DIR/cannot-be-called.rs:45:8
    |
-LL | extern "x86-interrupt" fn x86() {}
+LL | extern "x86-interrupt" fn x86(_x: *const u8) {}
    |        ^^^^^^^^^^^^^^^
 
 error[E0570]: "avr-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:64:22
+  --> $DIR/cannot-be-called.rs:66:22
    |
 LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:76:26
+  --> $DIR/cannot-be-called.rs:78:26
    |
 LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:82:26
+  --> $DIR/cannot-be-called.rs:84:26
    |
 LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:88:22
+  --> $DIR/cannot-be-called.rs:90:22
    |
 LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error: functions with the "msp430-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:52:5
+  --> $DIR/cannot-be-called.rs:54:5
    |
 LL |     msp430();
    |     ^^^^^^^^
    |
 note: an `extern "msp430-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:52:5
+  --> $DIR/cannot-be-called.rs:54:5
    |
 LL |     msp430();
    |     ^^^^^^^^
 
 error: functions with the "msp430-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:72:5
+  --> $DIR/cannot-be-called.rs:74:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "msp430-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:72:5
+  --> $DIR/cannot-be-called.rs:74:5
    |
 LL |     f()
    |     ^^^
diff --git a/tests/ui/abi/cannot-be-called.riscv32.stderr b/tests/ui/abi/cannot-be-called.riscv32.stderr
index 119d93bd58e..6d763bd6379 100644
--- a/tests/ui/abi/cannot-be-called.riscv32.stderr
+++ b/tests/ui/abi/cannot-be-called.riscv32.stderr
@@ -13,71 +13,71 @@ LL | extern "avr-interrupt" fn avr() {}
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
   --> $DIR/cannot-be-called.rs:45:8
    |
-LL | extern "x86-interrupt" fn x86() {}
+LL | extern "x86-interrupt" fn x86(_x: *const u8) {}
    |        ^^^^^^^^^^^^^^^
 
 error[E0570]: "avr-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:64:22
+  --> $DIR/cannot-be-called.rs:66:22
    |
 LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:70:25
+  --> $DIR/cannot-be-called.rs:72:25
    |
 LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
    |                         ^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:88:22
+  --> $DIR/cannot-be-called.rs:90:22
    |
 LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error: functions with the "riscv-interrupt-m" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:54:5
+  --> $DIR/cannot-be-called.rs:56:5
    |
 LL |     riscv_m();
    |     ^^^^^^^^^
    |
 note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:54:5
+  --> $DIR/cannot-be-called.rs:56:5
    |
 LL |     riscv_m();
    |     ^^^^^^^^^
 
 error: functions with the "riscv-interrupt-s" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:56:5
+  --> $DIR/cannot-be-called.rs:58:5
    |
 LL |     riscv_s();
    |     ^^^^^^^^^
    |
 note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:56:5
+  --> $DIR/cannot-be-called.rs:58:5
    |
 LL |     riscv_s();
    |     ^^^^^^^^^
 
 error: functions with the "riscv-interrupt-m" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:78:5
+  --> $DIR/cannot-be-called.rs:80:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:78:5
+  --> $DIR/cannot-be-called.rs:80:5
    |
 LL |     f()
    |     ^^^
 
 error: functions with the "riscv-interrupt-s" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:84:5
+  --> $DIR/cannot-be-called.rs:86:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:84:5
+  --> $DIR/cannot-be-called.rs:86:5
    |
 LL |     f()
    |     ^^^
diff --git a/tests/ui/abi/cannot-be-called.riscv64.stderr b/tests/ui/abi/cannot-be-called.riscv64.stderr
index 119d93bd58e..6d763bd6379 100644
--- a/tests/ui/abi/cannot-be-called.riscv64.stderr
+++ b/tests/ui/abi/cannot-be-called.riscv64.stderr
@@ -13,71 +13,71 @@ LL | extern "avr-interrupt" fn avr() {}
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
   --> $DIR/cannot-be-called.rs:45:8
    |
-LL | extern "x86-interrupt" fn x86() {}
+LL | extern "x86-interrupt" fn x86(_x: *const u8) {}
    |        ^^^^^^^^^^^^^^^
 
 error[E0570]: "avr-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:64:22
+  --> $DIR/cannot-be-called.rs:66:22
    |
 LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:70:25
+  --> $DIR/cannot-be-called.rs:72:25
    |
 LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
    |                         ^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "x86-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:88:22
+  --> $DIR/cannot-be-called.rs:90:22
    |
 LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error: functions with the "riscv-interrupt-m" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:54:5
+  --> $DIR/cannot-be-called.rs:56:5
    |
 LL |     riscv_m();
    |     ^^^^^^^^^
    |
 note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:54:5
+  --> $DIR/cannot-be-called.rs:56:5
    |
 LL |     riscv_m();
    |     ^^^^^^^^^
 
 error: functions with the "riscv-interrupt-s" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:56:5
+  --> $DIR/cannot-be-called.rs:58:5
    |
 LL |     riscv_s();
    |     ^^^^^^^^^
    |
 note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:56:5
+  --> $DIR/cannot-be-called.rs:58:5
    |
 LL |     riscv_s();
    |     ^^^^^^^^^
 
 error: functions with the "riscv-interrupt-m" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:78:5
+  --> $DIR/cannot-be-called.rs:80:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:78:5
+  --> $DIR/cannot-be-called.rs:80:5
    |
 LL |     f()
    |     ^^^
 
 error: functions with the "riscv-interrupt-s" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:84:5
+  --> $DIR/cannot-be-called.rs:86:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:84:5
+  --> $DIR/cannot-be-called.rs:86:5
    |
 LL |     f()
    |     ^^^
diff --git a/tests/ui/abi/cannot-be-called.rs b/tests/ui/abi/cannot-be-called.rs
index af979d65d33..b0267cfa37e 100644
--- a/tests/ui/abi/cannot-be-called.rs
+++ b/tests/ui/abi/cannot-be-called.rs
@@ -42,9 +42,11 @@ extern "riscv-interrupt-m" fn riscv_m() {}
 //[x64,x64_win,i686,avr,msp430]~^ ERROR is not a supported ABI
 extern "riscv-interrupt-s" fn riscv_s() {}
 //[x64,x64_win,i686,avr,msp430]~^ ERROR is not a supported ABI
-extern "x86-interrupt" fn x86() {}
+extern "x86-interrupt" fn x86(_x: *const u8) {}
 //[riscv32,riscv64,avr,msp430]~^ ERROR is not a supported ABI
 
+static BYTE: u8 = 0;
+
 /* extern "interrupt" calls  */
 fn call_the_interrupts() {
     avr();
@@ -55,7 +57,7 @@ fn call_the_interrupts() {
     //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-m" ABI cannot be called
     riscv_s();
     //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-s" ABI cannot be called
-    x86();
+    x86(&raw const BYTE);
     //[x64,x64_win,i686]~^ ERROR functions with the "x86-interrupt" ABI cannot be called
 }
 
diff --git a/tests/ui/abi/cannot-be-called.x64.stderr b/tests/ui/abi/cannot-be-called.x64.stderr
index 024d5e2e93d..6ccb10c44fd 100644
--- a/tests/ui/abi/cannot-be-called.x64.stderr
+++ b/tests/ui/abi/cannot-be-called.x64.stderr
@@ -23,49 +23,49 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
    |        ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "avr-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:64:22
+  --> $DIR/cannot-be-called.rs:66:22
    |
 LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:70:25
+  --> $DIR/cannot-be-called.rs:72:25
    |
 LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
    |                         ^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:76:26
+  --> $DIR/cannot-be-called.rs:78:26
    |
 LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:82:26
+  --> $DIR/cannot-be-called.rs:84:26
    |
 LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error: functions with the "x86-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:58:5
+  --> $DIR/cannot-be-called.rs:60:5
    |
-LL |     x86();
-   |     ^^^^^
+LL |     x86(&raw const BYTE);
+   |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: an `extern "x86-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:58:5
+  --> $DIR/cannot-be-called.rs:60:5
    |
-LL |     x86();
-   |     ^^^^^
+LL |     x86(&raw const BYTE);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: functions with the "x86-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:90:5
+  --> $DIR/cannot-be-called.rs:92:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "x86-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:90:5
+  --> $DIR/cannot-be-called.rs:92:5
    |
 LL |     f()
    |     ^^^
diff --git a/tests/ui/abi/cannot-be-called.x64_win.stderr b/tests/ui/abi/cannot-be-called.x64_win.stderr
index 024d5e2e93d..6ccb10c44fd 100644
--- a/tests/ui/abi/cannot-be-called.x64_win.stderr
+++ b/tests/ui/abi/cannot-be-called.x64_win.stderr
@@ -23,49 +23,49 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
    |        ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "avr-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:64:22
+  --> $DIR/cannot-be-called.rs:66:22
    |
 LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
    |                      ^^^^^^^^^^^^^^^
 
 error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:70:25
+  --> $DIR/cannot-be-called.rs:72:25
    |
 LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
    |                         ^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:76:26
+  --> $DIR/cannot-be-called.rs:78:26
    |
 LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
-  --> $DIR/cannot-be-called.rs:82:26
+  --> $DIR/cannot-be-called.rs:84:26
    |
 LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
    |                          ^^^^^^^^^^^^^^^^^^^
 
 error: functions with the "x86-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:58:5
+  --> $DIR/cannot-be-called.rs:60:5
    |
-LL |     x86();
-   |     ^^^^^
+LL |     x86(&raw const BYTE);
+   |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: an `extern "x86-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:58:5
+  --> $DIR/cannot-be-called.rs:60:5
    |
-LL |     x86();
-   |     ^^^^^
+LL |     x86(&raw const BYTE);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: functions with the "x86-interrupt" ABI cannot be called
-  --> $DIR/cannot-be-called.rs:90:5
+  --> $DIR/cannot-be-called.rs:92:5
    |
 LL |     f()
    |     ^^^
    |
 note: an `extern "x86-interrupt"` function can only be called using inline assembly
-  --> $DIR/cannot-be-called.rs:90:5
+  --> $DIR/cannot-be-called.rs:92:5
    |
 LL |     f()
    |     ^^^
diff --git a/tests/ui/abi/cannot-be-coroutine.i686.stderr b/tests/ui/abi/cannot-be-coroutine.i686.stderr
index 8c9292b6a32..230847ff269 100644
--- a/tests/ui/abi/cannot-be-coroutine.i686.stderr
+++ b/tests/ui/abi/cannot-be-coroutine.i686.stderr
@@ -1,13 +1,13 @@
 error: functions with the "x86-interrupt" ABI cannot be `async`
   --> $DIR/cannot-be-coroutine.rs:52:1
    |
-LL | async extern "x86-interrupt" fn x86() {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | async extern "x86-interrupt" fn x86(_p: *mut ()) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: remove the `async` keyword from this definition
    |
-LL - async extern "x86-interrupt" fn x86() {
-LL + extern "x86-interrupt" fn x86() {
+LL - async extern "x86-interrupt" fn x86(_p: *mut ()) {
+LL + extern "x86-interrupt" fn x86(_p: *mut ()) {
    |
 
 error: requires `ResumeTy` lang_item
diff --git a/tests/ui/abi/cannot-be-coroutine.rs b/tests/ui/abi/cannot-be-coroutine.rs
index 7270a55f69e..e3d3d45c632 100644
--- a/tests/ui/abi/cannot-be-coroutine.rs
+++ b/tests/ui/abi/cannot-be-coroutine.rs
@@ -49,6 +49,6 @@ async extern "riscv-interrupt-s" fn riscv_s() {
     //[riscv32,riscv64]~^ ERROR functions with the "riscv-interrupt-s" ABI cannot be `async`
 }
 
-async extern "x86-interrupt" fn x86() {
+async extern "x86-interrupt" fn x86(_p: *mut ()) {
     //[x64,x64_win,i686]~^ ERROR functions with the "x86-interrupt" ABI cannot be `async`
 }
diff --git a/tests/ui/abi/cannot-be-coroutine.x64.stderr b/tests/ui/abi/cannot-be-coroutine.x64.stderr
index 8c9292b6a32..230847ff269 100644
--- a/tests/ui/abi/cannot-be-coroutine.x64.stderr
+++ b/tests/ui/abi/cannot-be-coroutine.x64.stderr
@@ -1,13 +1,13 @@
 error: functions with the "x86-interrupt" ABI cannot be `async`
   --> $DIR/cannot-be-coroutine.rs:52:1
    |
-LL | async extern "x86-interrupt" fn x86() {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | async extern "x86-interrupt" fn x86(_p: *mut ()) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: remove the `async` keyword from this definition
    |
-LL - async extern "x86-interrupt" fn x86() {
-LL + extern "x86-interrupt" fn x86() {
+LL - async extern "x86-interrupt" fn x86(_p: *mut ()) {
+LL + extern "x86-interrupt" fn x86(_p: *mut ()) {
    |
 
 error: requires `ResumeTy` lang_item
diff --git a/tests/ui/abi/cannot-be-coroutine.x64_win.stderr b/tests/ui/abi/cannot-be-coroutine.x64_win.stderr
index 8c9292b6a32..230847ff269 100644
--- a/tests/ui/abi/cannot-be-coroutine.x64_win.stderr
+++ b/tests/ui/abi/cannot-be-coroutine.x64_win.stderr
@@ -1,13 +1,13 @@
 error: functions with the "x86-interrupt" ABI cannot be `async`
   --> $DIR/cannot-be-coroutine.rs:52:1
    |
-LL | async extern "x86-interrupt" fn x86() {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | async extern "x86-interrupt" fn x86(_p: *mut ()) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: remove the `async` keyword from this definition
    |
-LL - async extern "x86-interrupt" fn x86() {
-LL + extern "x86-interrupt" fn x86() {
+LL - async extern "x86-interrupt" fn x86(_p: *mut ()) {
+LL + extern "x86-interrupt" fn x86(_p: *mut ()) {
    |
 
 error: requires `ResumeTy` lang_item
diff --git a/tests/ui/abi/interrupt-invalid-signature.i686.stderr b/tests/ui/abi/interrupt-invalid-signature.i686.stderr
index 86f2e097c37..df8e318bf0a 100644
--- a/tests/ui/abi/interrupt-invalid-signature.i686.stderr
+++ b/tests/ui/abi/interrupt-invalid-signature.i686.stderr
@@ -1,15 +1,31 @@
 error: invalid signature for `extern "x86-interrupt"` function
-  --> $DIR/interrupt-invalid-signature.rs:83:40
+  --> $DIR/interrupt-invalid-signature.rs:83:53
    |
-LL | extern "x86-interrupt" fn x86_ret() -> u8 {
-   |                                        ^^
+LL | extern "x86-interrupt" fn x86_ret(_p: *const u8) -> u8 {
+   |                                                     ^^
    |
    = note: functions with the "x86-interrupt" ABI cannot have a return type
 help: remove the return type
-  --> $DIR/interrupt-invalid-signature.rs:83:40
+  --> $DIR/interrupt-invalid-signature.rs:83:53
    |
-LL | extern "x86-interrupt" fn x86_ret() -> u8 {
-   |                                        ^^
+LL | extern "x86-interrupt" fn x86_ret(_p: *const u8) -> u8 {
+   |                                                     ^^
 
-error: aborting due to 1 previous error
+error: invalid signature for `extern "x86-interrupt"` function
+  --> $DIR/interrupt-invalid-signature.rs:89:1
+   |
+LL | extern "x86-interrupt" fn x86_0() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found 0)
+
+error: invalid signature for `extern "x86-interrupt"` function
+  --> $DIR/interrupt-invalid-signature.rs:100:33
+   |
+LL | extern "x86-interrupt" fn x86_3(_p1: *const u8, _p2: *const u8, _p3: *const u8) {
+   |                                 ^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^
+   |
+   = note: functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found 3)
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/abi/interrupt-invalid-signature.rs b/tests/ui/abi/interrupt-invalid-signature.rs
index e389285b069..09bda0d5faf 100644
--- a/tests/ui/abi/interrupt-invalid-signature.rs
+++ b/tests/ui/abi/interrupt-invalid-signature.rs
@@ -80,11 +80,27 @@ extern "riscv-interrupt-s" fn riscv_s_ret() -> u8 {
 }
 
 #[cfg(any(x64,i686))]
-extern "x86-interrupt" fn x86_ret() -> u8 {
+extern "x86-interrupt" fn x86_ret(_p: *const u8) -> u8 {
     //[x64,i686]~^ ERROR invalid signature
     1
 }
 
+#[cfg(any(x64,i686))]
+extern "x86-interrupt" fn x86_0() {
+    //[x64,i686]~^ ERROR invalid signature
+}
+
+#[cfg(any(x64,i686))]
+extern "x86-interrupt" fn x86_1(_p1: *const u8) { }
+
+#[cfg(any(x64,i686))]
+extern "x86-interrupt" fn x86_2(_p1: *const u8, _p2: *const u8) { }
+
+#[cfg(any(x64,i686))]
+extern "x86-interrupt" fn x86_3(_p1: *const u8, _p2: *const u8, _p3: *const u8) {
+    //[x64,i686]~^ ERROR invalid signature
+}
+
 
 
 /* extern "interrupt" fnptrs with invalid signatures */
diff --git a/tests/ui/abi/interrupt-invalid-signature.x64.stderr b/tests/ui/abi/interrupt-invalid-signature.x64.stderr
index 86f2e097c37..df8e318bf0a 100644
--- a/tests/ui/abi/interrupt-invalid-signature.x64.stderr
+++ b/tests/ui/abi/interrupt-invalid-signature.x64.stderr
@@ -1,15 +1,31 @@
 error: invalid signature for `extern "x86-interrupt"` function
-  --> $DIR/interrupt-invalid-signature.rs:83:40
+  --> $DIR/interrupt-invalid-signature.rs:83:53
    |
-LL | extern "x86-interrupt" fn x86_ret() -> u8 {
-   |                                        ^^
+LL | extern "x86-interrupt" fn x86_ret(_p: *const u8) -> u8 {
+   |                                                     ^^
    |
    = note: functions with the "x86-interrupt" ABI cannot have a return type
 help: remove the return type
-  --> $DIR/interrupt-invalid-signature.rs:83:40
+  --> $DIR/interrupt-invalid-signature.rs:83:53
    |
-LL | extern "x86-interrupt" fn x86_ret() -> u8 {
-   |                                        ^^
+LL | extern "x86-interrupt" fn x86_ret(_p: *const u8) -> u8 {
+   |                                                     ^^
 
-error: aborting due to 1 previous error
+error: invalid signature for `extern "x86-interrupt"` function
+  --> $DIR/interrupt-invalid-signature.rs:89:1
+   |
+LL | extern "x86-interrupt" fn x86_0() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found 0)
+
+error: invalid signature for `extern "x86-interrupt"` function
+  --> $DIR/interrupt-invalid-signature.rs:100:33
+   |
+LL | extern "x86-interrupt" fn x86_3(_p1: *const u8, _p2: *const u8, _p3: *const u8) {
+   |                                 ^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^
+   |
+   = note: functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found 3)
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/abi/interrupt-returns-never-or-unit.rs b/tests/ui/abi/interrupt-returns-never-or-unit.rs
index 8e224229a0b..104b36363d0 100644
--- a/tests/ui/abi/interrupt-returns-never-or-unit.rs
+++ b/tests/ui/abi/interrupt-returns-never-or-unit.rs
@@ -56,7 +56,7 @@ extern "riscv-interrupt-s" fn riscv_s_ret_never() -> ! {
 }
 
 #[cfg(any(x64,i686))]
-extern "x86-interrupt" fn x86_ret_never() -> ! {
+extern "x86-interrupt" fn x86_ret_never(_p: *const u8) -> ! {
     loop {}
 }
 
@@ -83,7 +83,7 @@ extern "riscv-interrupt-s" fn riscv_s_ret_unit() -> () {
 }
 
 #[cfg(any(x64,i686))]
-extern "x86-interrupt" fn x86_ret_unit() -> () {
+extern "x86-interrupt" fn x86_ret_unit(_x: *const u8) -> () {
     ()
 }
 
diff --git a/tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.rs b/tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.rs
new file mode 100644
index 00000000000..8ad244568a3
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.rs
@@ -0,0 +1,15 @@
+#![feature(explicit_tail_calls)]
+#![expect(incomplete_features)]
+
+fn foo() -> for<'a> fn(&'a i32) {
+    become bar();
+    //~^ ERROR mismatched signatures
+}
+
+fn bar() -> fn(&'static i32) {
+    dummy
+}
+
+fn dummy(_: &i32) {}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.stderr b/tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.stderr
new file mode 100644
index 00000000000..f6594580ba5
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/ret-ty-hr-mismatch.stderr
@@ -0,0 +1,12 @@
+error: mismatched signatures
+  --> $DIR/ret-ty-hr-mismatch.rs:5:5
+   |
+LL |     become bar();
+   |     ^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have matching signatures
+   = note: caller signature: `fn() -> for<'a> fn(&'a i32)`
+   = note: callee signature: `fn() -> fn(&'static i32)`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/explicit-tail-calls/ret-ty-modulo-anonymization.rs b/tests/ui/explicit-tail-calls/ret-ty-modulo-anonymization.rs
new file mode 100644
index 00000000000..0cd4e204278
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/ret-ty-modulo-anonymization.rs
@@ -0,0 +1,16 @@
+// Ensure that we anonymize the output of a function for tail call signature compatibility.
+
+//@ check-pass
+
+#![feature(explicit_tail_calls)]
+#![expect(incomplete_features)]
+
+fn foo() -> for<'a> fn(&'a ()) {
+    become bar();
+}
+
+fn bar() -> for<'b> fn(&'b ()) {
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs
index c4fdb5f427c..0abdf0c5309 100644
--- a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs
+++ b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs
@@ -7,22 +7,22 @@
 extern crate minicore;
 use minicore::*;
 
-extern "x86-interrupt" fn f7() {} //~ ERROR "x86-interrupt" ABI is experimental
+extern "x86-interrupt" fn f7(_p: *const u8) {} //~ ERROR "x86-interrupt" ABI is experimental
 trait Tr {
-    extern "x86-interrupt" fn m7(); //~ ERROR "x86-interrupt" ABI is experimental
-    extern "x86-interrupt" fn dm7() {} //~ ERROR "x86-interrupt" ABI is experimental
+    extern "x86-interrupt" fn m7(_p: *const u8); //~ ERROR "x86-interrupt" ABI is experimental
+    extern "x86-interrupt" fn dm7(_p: *const u8) {} //~ ERROR "x86-interrupt" ABI is experimental
 }
 
 struct S;
 
 // Methods in trait impl
 impl Tr for S {
-    extern "x86-interrupt" fn m7() {} //~ ERROR "x86-interrupt" ABI is experimental
+    extern "x86-interrupt" fn m7(_p: *const u8) {} //~ ERROR "x86-interrupt" ABI is experimental
 }
 
 // Methods in inherent impl
 impl S {
-    extern "x86-interrupt" fn im7() {} //~ ERROR "x86-interrupt" ABI is experimental
+    extern "x86-interrupt" fn im7(_p: *const u8) {} //~ ERROR "x86-interrupt" ABI is experimental
 }
 
 type A7 = extern "x86-interrupt" fn(); //~ ERROR "x86-interrupt" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr
index 67211d402c6..b53917dda61 100644
--- a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr
@@ -1,7 +1,7 @@
 error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:10:8
    |
-LL | extern "x86-interrupt" fn f7() {}
+LL | extern "x86-interrupt" fn f7(_p: *const u8) {}
    |        ^^^^^^^^^^^^^^^
    |
    = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
@@ -11,7 +11,7 @@ LL | extern "x86-interrupt" fn f7() {}
 error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:12:12
    |
-LL |     extern "x86-interrupt" fn m7();
+LL |     extern "x86-interrupt" fn m7(_p: *const u8);
    |            ^^^^^^^^^^^^^^^
    |
    = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
@@ -21,7 +21,7 @@ LL |     extern "x86-interrupt" fn m7();
 error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:13:12
    |
-LL |     extern "x86-interrupt" fn dm7() {}
+LL |     extern "x86-interrupt" fn dm7(_p: *const u8) {}
    |            ^^^^^^^^^^^^^^^
    |
    = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
@@ -31,7 +31,7 @@ LL |     extern "x86-interrupt" fn dm7() {}
 error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:20:12
    |
-LL |     extern "x86-interrupt" fn m7() {}
+LL |     extern "x86-interrupt" fn m7(_p: *const u8) {}
    |            ^^^^^^^^^^^^^^^
    |
    = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
@@ -41,7 +41,7 @@ LL |     extern "x86-interrupt" fn m7() {}
 error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:25:12
    |
-LL |     extern "x86-interrupt" fn im7() {}
+LL |     extern "x86-interrupt" fn im7(_p: *const u8) {}
    |            ^^^^^^^^^^^^^^^
    |
    = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
diff --git a/tests/ui/trait-bounds/trait-bound-adt-issue-145611.rs b/tests/ui/trait-bounds/trait-bound-adt-issue-145611.rs
new file mode 100644
index 00000000000..74551ce493f
--- /dev/null
+++ b/tests/ui/trait-bounds/trait-bound-adt-issue-145611.rs
@@ -0,0 +1,11 @@
+// This test is for regression of issue #145611
+// There should not be cycle error in effective_visibilities query.
+
+trait LocalTrait {}
+struct SomeType;
+fn impls_trait<T: LocalTrait>() {}
+fn foo() -> impl Sized {
+    impls_trait::<SomeType>(); //~ ERROR the trait bound `SomeType: LocalTrait` is not satisfied [E0277]
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/trait-bound-adt-issue-145611.stderr b/tests/ui/trait-bounds/trait-bound-adt-issue-145611.stderr
new file mode 100644
index 00000000000..21a2cce20cb
--- /dev/null
+++ b/tests/ui/trait-bounds/trait-bound-adt-issue-145611.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `SomeType: LocalTrait` is not satisfied
+  --> $DIR/trait-bound-adt-issue-145611.rs:8:19
+   |
+LL |     impls_trait::<SomeType>();
+   |                   ^^^^^^^^ the trait `LocalTrait` is not implemented for `SomeType`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/trait-bound-adt-issue-145611.rs:4:1
+   |
+LL | trait LocalTrait {}
+   | ^^^^^^^^^^^^^^^^
+note: required by a bound in `impls_trait`
+  --> $DIR/trait-bound-adt-issue-145611.rs:6:19
+   |
+LL | fn impls_trait<T: LocalTrait>() {}
+   |                   ^^^^^^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-supertraits-dyn-compat.rs b/tests/ui/traits/const-traits/const-supertraits-dyn-compat.rs
new file mode 100644
index 00000000000..2d12bc81af6
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-supertraits-dyn-compat.rs
@@ -0,0 +1,18 @@
+#![feature(const_trait_impl)]
+
+const trait Super {}
+
+// Not ok
+const trait Unconditionally: const Super {}
+fn test() {
+    let _: &dyn Unconditionally;
+    //~^ ERROR the trait `Unconditionally` is not dyn compatible
+}
+
+// Okay
+const trait Conditionally: [const] Super {}
+fn test2() {
+    let _: &dyn Conditionally;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/const-supertraits-dyn-compat.stderr b/tests/ui/traits/const-traits/const-supertraits-dyn-compat.stderr
new file mode 100644
index 00000000000..ceb07081c9e
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-supertraits-dyn-compat.stderr
@@ -0,0 +1,18 @@
+error[E0038]: the trait `Unconditionally` is not dyn compatible
+  --> $DIR/const-supertraits-dyn-compat.rs:8:17
+   |
+LL |     let _: &dyn Unconditionally;
+   |                 ^^^^^^^^^^^^^^^ `Unconditionally` 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>
+  --> $DIR/const-supertraits-dyn-compat.rs:6:30
+   |
+LL | const trait Unconditionally: const Super {}
+   |             ---------------  ^^^^^^^^^^^ ...because it cannot have a `const` supertrait
+   |             |
+   |             this trait is not dyn compatible...
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/triagebot.toml b/triagebot.toml
index 31411747848..955b0ba2b05 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1603,3 +1603,8 @@ labels = ["S-waiting-on-concerns"]
 # onto a different base commit
 # Documentation at: https://forge.rust-lang.org/triagebot/range-diff.html
 [range-diff]
+
+# Adds at the end of a review body a link to view the changes that happened
+# since the review
+# Documentation at: https://forge.rust-lang.org/triagebot/review-changes-since.html
+[review-changes-since]