about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-30 18:47:55 +0000
committerbors <bors@rust-lang.org>2023-10-30 18:47:55 +0000
commit236ac911de2f4b6210ba99e25c6c4843c9381a1a (patch)
treec4e21832b6a573d253d5e83326e8bc184cf13265
parente6e931dda5fffbae0fd87c5b1af753cc95556880 (diff)
parent9e4ab9f1118444962ef64eba0a7c07877b2e35c4 (diff)
downloadrust-236ac911de2f4b6210ba99e25c6c4843c9381a1a.tar.gz
rust-236ac911de2f4b6210ba99e25c6c4843c9381a1a.zip
Auto merge of #117405 - GuillaumeGomez:rollup-i3jxtwh, r=GuillaumeGomez
Rollup of 11 pull requests

Successful merges:

 - #112463 (rustdoc: elide cross-crate default generic arguments)
 - #117068 (Clean up `compiler/rustc*/Cargo.toml`)
 - #117132 (On object safety error, mention new enum as alternative)
 - #117317 (share some track_caller logic between interpret and codegen)
 - #117356 (Add support for mipsel-unknown-netbsd, 32-bit LE mips.)
 - #117357 (Rename a few remaining references to abort terminator)
 - #117370 (C-variadic error improvements)
 - #117376 (More `rustc_interface` cleanups)
 - #117383 (improve and fix `x install`)
 - #117390 (Fix unused variables lint issue for args in macro)
 - #117395 (Fix missing leading space in suggestion)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc/Cargo.toml13
-rw-r--r--compiler/rustc_abi/Cargo.toml8
-rw-r--r--compiler/rustc_arena/Cargo.toml2
-rw-r--r--compiler/rustc_ast/Cargo.toml6
-rw-r--r--compiler/rustc_ast_lowering/Cargo.toml6
-rw-r--r--compiler/rustc_ast_passes/Cargo.toml4
-rw-r--r--compiler/rustc_ast_passes/messages.ftl4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs37
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs13
-rw-r--r--compiler/rustc_ast_pretty/Cargo.toml4
-rw-r--r--compiler/rustc_attr/Cargo.toml4
-rw-r--r--compiler/rustc_baked_icu_data/Cargo.toml4
-rw-r--r--compiler/rustc_borrowck/Cargo.toml12
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs2
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml6
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs46
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml17
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml31
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs43
-rw-r--r--compiler/rustc_const_eval/Cargo.toml10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs19
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs44
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs136
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/util/caller_location.rs63
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs1
-rw-r--r--compiler/rustc_data_structures/Cargo.toml22
-rw-r--r--compiler/rustc_driver/Cargo.toml2
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml6
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs6
-rw-r--r--compiler/rustc_error_codes/Cargo.toml4
-rw-r--r--compiler/rustc_error_messages/Cargo.toml14
-rw-r--r--compiler/rustc_errors/Cargo.toml26
-rw-r--r--compiler/rustc_expand/Cargo.toml6
-rw-r--r--compiler/rustc_feature/Cargo.toml4
-rw-r--r--compiler/rustc_fluent_macro/Cargo.toml4
-rw-r--r--compiler/rustc_fs_util/Cargo.toml4
-rw-r--r--compiler/rustc_graphviz/Cargo.toml4
-rw-r--r--compiler/rustc_hir/Cargo.toml16
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml22
-rw-r--r--compiler/rustc_hir_pretty/Cargo.toml8
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml16
-rw-r--r--compiler/rustc_incremental/Cargo.toml6
-rw-r--r--compiler/rustc_index/Cargo.toml8
-rw-r--r--compiler/rustc_infer/Cargo.toml8
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs64
-rw-r--r--compiler/rustc_interface/Cargo.toml48
-rw-r--r--compiler/rustc_interface/src/callbacks.rs4
-rw-r--r--compiler/rustc_interface/src/interface.rs482
-rw-r--r--compiler/rustc_interface/src/passes.rs48
-rw-r--r--compiler/rustc_interface/src/tests.rs32
-rw-r--r--compiler/rustc_interface/src/util.rs33
-rw-r--r--compiler/rustc_lexer/Cargo.toml1
-rw-r--r--compiler/rustc_lint/Cargo.toml26
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_lint_defs/Cargo.toml10
-rw-r--r--compiler/rustc_llvm/Cargo.toml4
-rw-r--r--compiler/rustc_log/Cargo.toml8
-rw-r--r--compiler/rustc_macros/Cargo.toml6
-rw-r--r--compiler/rustc_metadata/Cargo.toml20
-rw-r--r--compiler/rustc_middle/Cargo.toml15
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs34
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs2
-rw-r--r--compiler/rustc_mir_build/Cargo.toml14
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml10
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml22
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml12
-rw-r--r--compiler/rustc_parse/Cargo.toml4
-rw-r--r--compiler/rustc_parse_format/Cargo.toml4
-rw-r--r--compiler/rustc_passes/Cargo.toml20
-rw-r--r--compiler/rustc_passes/messages.ftl3
-rw-r--r--compiler/rustc_passes/src/errors.rs21
-rw-r--r--compiler/rustc_passes/src/liveness.rs25
-rw-r--r--compiler/rustc_plugin_impl/Cargo.toml8
-rw-r--r--compiler/rustc_privacy/Cargo.toml6
-rw-r--r--compiler/rustc_query_impl/Cargo.toml12
-rw-r--r--compiler/rustc_query_system/Cargo.toml8
-rw-r--r--compiler/rustc_resolve/Cargo.toml4
-rw-r--r--compiler/rustc_serialize/Cargo.toml4
-rw-r--r--compiler/rustc_session/Cargo.toml20
-rw-r--r--compiler/rustc_session/src/config.rs61
-rw-r--r--compiler/rustc_session/src/parse.rs4
-rw-r--r--compiler/rustc_smir/Cargo.toml4
-rw-r--r--compiler/rustc_span/Cargo.toml18
-rw-r--r--compiler/rustc_symbol_mangling/Cargo.toml19
-rw-r--r--compiler/rustc_target/Cargo.toml14
-rw-r--r--compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs21
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml14
-rw-r--r--compiler/rustc_traits/Cargo.toml8
-rw-r--r--compiler/rustc_transmute/Cargo.toml12
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml12
-rw-r--r--compiler/rustc_type_ir/Cargo.toml8
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs52
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs6
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/librustdoc/clean/mod.rs12
-rw-r--r--src/librustdoc/clean/utils.rs132
-rw-r--r--src/librustdoc/core.rs7
-rw-r--r--src/librustdoc/doctest.rs11
-rw-r--r--src/librustdoc/lib.rs5
-rw-r--r--tests/rustdoc/const-generics/add-impl.rs2
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/default-generic-args.rs45
-rw-r--r--tests/rustdoc/inline_cross/default-generic-args.rs104
-rw-r--r--tests/rustdoc/inline_cross/dyn_trait.rs8
-rw-r--r--tests/rustdoc/inline_cross/impl_trait.rs4
-rw-r--r--tests/rustdoc/normalize-assoc-item.rs4
-rw-r--r--tests/rustdoc/where-clause-order.rs2
-rw-r--r--tests/ui/c-variadic/issue-86053-1.stderr10
-rw-r--r--tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr1
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr2
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.base.stderr3
-rw-r--r--tests/ui/generic-associated-types/issue-76535.base.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-79422.base.stderr6
-rw-r--r--tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr1
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety.stderr4
-rw-r--r--tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr6
-rw-r--r--tests/ui/issues/issue-19380.stderr2
-rw-r--r--tests/ui/lint/lint-unnecessary-parens.fixed8
-rw-r--r--tests/ui/lint/lint-unnecessary-parens.rs8
-rw-r--r--tests/ui/lint/lint-unnecessary-parens.stderr74
-rw-r--r--tests/ui/lint/unused/issue-117284-arg-in-macro.rs17
-rw-r--r--tests/ui/lint/unused/issue-117284-arg-in-macro.stderr29
-rw-r--r--tests/ui/object-safety/issue-19538.stderr2
-rw-r--r--tests/ui/object-safety/object-safety-issue-22040.stderr1
-rw-r--r--tests/ui/object-safety/object-safety-no-static.curr.stderr1
-rw-r--r--tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr1
-rw-r--r--tests/ui/parser/variadic-ffi-semantic-restrictions.rs17
-rw-r--r--tests/ui/parser/variadic-ffi-semantic-restrictions.stderr103
-rw-r--r--tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr2
-rw-r--r--tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr1
-rw-r--r--tests/ui/traits/issue-38604.stderr2
-rw-r--r--tests/ui/traits/item-privacy.stderr1
-rw-r--r--tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr3
-rw-r--r--tests/ui/traits/object/safety.stderr2
-rw-r--r--tests/ui/traits/test-2.stderr9
-rw-r--r--tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr1
-rw-r--r--tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr3
-rw-r--r--tests/ui/wf/wf-convert-unsafe-trait-obj.stderr3
-rw-r--r--tests/ui/wf/wf-unsafe-trait-obj-match.stderr6
145 files changed, 1651 insertions, 1079 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0761268c9d4..2b1e918e2f5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4412,7 +4412,6 @@ version = "0.0.0"
 dependencies = [
  "field-offset",
  "measureme",
- "memoffset",
  "rustc-rayon-core",
  "rustc_data_structures",
  "rustc_errors",
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index dcb165f9fdb..3cb56a7d312 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -4,16 +4,21 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-rustc_driver = { path = "../rustc_driver" }
-rustc_driver_impl = { path = "../rustc_driver_impl" }
+# tidy-alphabetical-start
 
 # Make sure rustc_codegen_ssa ends up in the sysroot, because this
 # crate is intended to be used by codegen backends, which may not be in-tree.
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
+
+rustc_driver = { path = "../rustc_driver" }
+rustc_driver_impl = { path = "../rustc_driver_impl" }
+
 # Make sure rustc_smir ends up in the sysroot, because this
-# crate is intended to be used by stable MIR consumers, which are not in-tree
+# crate is intended to be used by stable MIR consumers, which are not in-tree.
 rustc_smir = { path = "../rustc_smir" }
+
 stable_mir = { path = "../stable_mir" }
+# tidy-alphabetical-end
 
 [dependencies.jemalloc-sys]
 version = "0.5.0"
@@ -21,7 +26,9 @@ optional = true
 features = ['unprefixed_malloc_on_supported_platforms']
 
 [features]
+# tidy-alphabetical-start
 jemalloc = ['jemalloc-sys']
 llvm = ['rustc_driver_impl/llvm']
 max_level_info = ['rustc_driver_impl/max_level_info']
 rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler']
+# tidy-alphabetical-end
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index c43fd745e8f..e549724b1c0 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -4,18 +4,20 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
-tracing = "0.1"
 rand = { version = "0.8.4", default-features = false, optional = true }
 rand_xoshiro = { version = "0.6.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true  }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true  }
+tracing = "0.1"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 default = ["nightly", "randomize"]
-randomize = ["rand", "rand_xoshiro", "nightly"]
 # rust-analyzer depends on this crate and we therefore require it to built on a stable toolchain
 # without depending on rustc_data_structures, rustc_macros and rustc_serialize
 nightly = [
@@ -24,3 +26,5 @@ nightly = [
     "rustc_macros",
     "rustc_serialize",
 ]
+randomize = ["rand", "rand_xoshiro", "nightly"]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_arena/Cargo.toml b/compiler/rustc_arena/Cargo.toml
index 5c2aee6b47f..382ab2b0775 100644
--- a/compiler/rustc_arena/Cargo.toml
+++ b/compiler/rustc_arena/Cargo.toml
@@ -4,4 +4,6 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index e0948471acb..59e3d85589a 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -3,9 +3,8 @@ name = "rustc_ast"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
 memchr = "2.5.0"
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -14,8 +13,9 @@ rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-# depends on Mutability and Movability, which could be uplifted into a common crate.
+# For Mutability and Movability, which could be uplifted into a common crate.
 rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index 6b0da256505..8cc4521e0a7 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -7,18 +7,20 @@ edition = "2021"
 doctest = false
 
 [dependencies]
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
-rustc_middle = { path = "../rustc_middle" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index eb736123520..c1ebfb3e6d0 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 itertools = "0.10.1"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -11,11 +12,12 @@ rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
-rustc_macros = { path = "../rustc_macros" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 43020a93078..d22bae816ef 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -42,6 +42,10 @@ ast_passes_const_and_async = functions cannot be both `const` and `async`
     .async = `async` because of this
     .label = {""}
 
+ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
+    .const = `const` because of this
+    .variadic = C-variadic because of this
+
 ast_passes_const_without_body =
     free constant item 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 0477c7b2ba9..477d3732d46 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -482,9 +482,36 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    /// Reject C-variadic type unless the function is foreign,
-    /// or free and `unsafe extern "C"` semantically.
+    /// Reject invalid C-variadic types.
+    ///
+    /// C-variadics must be:
+    /// - Non-const
+    /// - Either foreign, or free and `unsafe extern "C"` semantically
     fn check_c_variadic_type(&self, fk: FnKind<'a>) {
+        let variadic_spans: Vec<_> = fk
+            .decl()
+            .inputs
+            .iter()
+            .filter(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
+            .map(|arg| arg.span)
+            .collect();
+
+        if variadic_spans.is_empty() {
+            return;
+        }
+
+        if let Some(header) = fk.header() {
+            if let Const::Yes(const_span) = header.constness {
+                let mut spans = variadic_spans.clone();
+                spans.push(const_span);
+                self.err_handler().emit_err(errors::ConstAndCVariadic {
+                    spans,
+                    const_span,
+                    variadic_spans: variadic_spans.clone(),
+                });
+            }
+        }
+
         match (fk.ctxt(), fk.header()) {
             (Some(FnCtxt::Foreign), _) => return,
             (Some(FnCtxt::Free), Some(header)) => match header.ext {
@@ -499,11 +526,7 @@ impl<'a> AstValidator<'a> {
             _ => {}
         };
 
-        for Param { ty, span, .. } in &fk.decl().inputs {
-            if let TyKind::CVarArgs = ty.kind {
-                self.err_handler().emit_err(errors::BadCVariadic { span: *span });
-            }
-        }
+        self.err_handler().emit_err(errors::BadCVariadic { span: variadic_spans });
     }
 
     fn check_item_named(&self, ident: Ident, kind: &str) {
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index e74d94e4347..d14b62d6bdc 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -271,7 +271,7 @@ pub struct ExternItemAscii {
 #[diag(ast_passes_bad_c_variadic)]
 pub struct BadCVariadic {
     #[primary_span]
-    pub span: Span,
+    pub span: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
@@ -584,6 +584,17 @@ pub struct ConstAndAsync {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_const_and_c_variadic)]
+pub struct ConstAndCVariadic {
+    #[primary_span]
+    pub spans: Vec<Span>,
+    #[label(ast_passes_const)]
+    pub const_span: Span,
+    #[label(ast_passes_variadic)]
+    pub variadic_spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_pattern_in_foreign, code = "E0130")]
 pub struct PatternInForeign {
     #[primary_span]
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index 980a8fa93a9..af1524c8baa 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -3,9 +3,9 @@ name = "rustc_ast_pretty"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 thin-vec = "0.2.12"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml
index a14d2796817..d33416d2003 100644
--- a/compiler/rustc_attr/Cargo.toml
+++ b/compiler/rustc_attr/Cargo.toml
@@ -3,9 +3,8 @@ name = "rustc_attr"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -17,3 +16,4 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml
index d3a307675ac..fb54937a098 100644
--- a/compiler/rustc_baked_icu_data/Cargo.toml
+++ b/compiler/rustc_baked_icu_data/Cargo.toml
@@ -4,11 +4,15 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 icu_list = "1.2"
 icu_locid = "1.2"
 icu_provider = "1.2"
 icu_provider_adapters = "1.2"
 zerovec = "0.9.4"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 rustc_use_parallel_compiler = ['icu_provider/sync']
+# tidy-alphabetical-end
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index 56a9deb6aab..636817a7ce1 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -3,19 +3,16 @@ name = "rustc_borrowck"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 either = "1.5.0"
 itertools = "0.10.1"
-tracing = "0.1"
 polonius-engine = "0.13.0"
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 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_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_lexer = { path = "../rustc_lexer" }
@@ -24,7 +21,10 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_traits = { path = "../rustc_traits" }
-rustc_span = { path = "../rustc_span" }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 9eb02be2f15..8477686d4f5 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1640,7 +1640,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::UnwindTerminate(_) => {
                 if !is_cleanup {
-                    span_mirbug!(self, block_data, "abort on non-cleanup block!")
+                    span_mirbug!(self, block_data, "terminate on non-cleanup block!")
                 }
             }
             TerminatorKind::Return => {
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index 44012e802aa..21b87be4b81 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 doctest = false
 
 [dependencies]
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
@@ -14,16 +15,17 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
-rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_parse_format = { path = "../rustc_parse_format" }
 rustc_parse = { path = "../rustc_parse" }
+rustc_parse_format = { path = "../rustc_parse_format" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 9771f44f62c..63562d33508 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -430,47 +430,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         }
     }
 
-    // Note: must be kept in sync with get_caller_location from cg_ssa
-    pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
-        let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
-            use rustc_session::RemapFileNameExt;
-            let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
-            let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
-            let const_loc = fx.tcx.const_caller_location((
-                rustc_span::symbol::Symbol::intern(
-                    &caller.file.name.for_codegen(&fx.tcx.sess).to_string_lossy(),
-                ),
-                caller.line as u32,
-                caller.col_display as u32 + 1,
-            ));
-            crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty())
-        };
-
-        // Walk up the `SourceScope`s, in case some of them are from MIR inlining.
-        // If so, the starting `source_info.span` is in the innermost inlined
-        // function, and will be replaced with outer callsite spans as long
-        // as the inlined functions were `#[track_caller]`.
-        loop {
-            let scope_data = &self.mir.source_scopes[source_info.scope];
-
-            if let Some((callee, callsite_span)) = scope_data.inlined {
-                // Stop inside the most nested non-`#[track_caller]` function,
-                // before ever reaching its caller (which is irrelevant).
-                if !callee.def.requires_caller_location(self.tcx) {
-                    return span_to_caller_location(self, source_info.span);
-                }
-                source_info.span = callsite_span;
-            }
-
-            // Skip past all of the parents with `inlined: None`.
-            match scope_data.inlined_parent_scope {
-                Some(parent) => source_info.scope = parent,
-                None => break,
-            }
-        }
-
-        // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
-        self.caller_location.unwrap_or_else(|| span_to_caller_location(self, source_info.span))
+    pub(crate) fn get_caller_location(&mut self, source_info: mir::SourceInfo) -> CValue<'tcx> {
+        self.mir.caller_location_span(source_info, self.caller_location, self.tcx, |span| {
+            let const_loc = self.tcx.span_as_caller_location(span);
+            crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
+        })
     }
 
     pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index e864337e5dc..1d309eb908e 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -7,18 +7,15 @@ edition = "2021"
 test = false
 
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.0"
 cstr = "0.2"
 itertools = "0.10.5"
 libc = "0.2"
 measureme = "10.0.0"
-object = { version = "0.32.0", default-features = false, features = [
-    "std",
-    "read",
-] }
-tracing = "0.1"
-rustc_middle = { path = "../rustc_middle" }
+object = { version = "0.32.0", default-features = false, features = ["std", "read"] }
 rustc-demangle = "0.1.21"
+rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -30,12 +27,14 @@ rustc_index = { path = "../rustc_index" }
 rustc_llvm = { path = "../rustc_llvm" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_metadata = { path = "../rustc_metadata" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
 rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_target = { path = "../rustc_target" }
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-rustc_ast = { path = "../rustc_ast" }
-rustc_span = { path = "../rustc_span" }
 serde = { version = "1", features = [ "derive" ]}
 serde_json = "1"
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 454e2f80676..4dae49f81a3 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -4,43 +4,46 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 ar_archive_writer = "0.1.5"
 bitflags = "1.2.1"
 cc = "1.0.69"
 itertools = "0.10.1"
-tracing = "0.1"
 jobserver = "0.1.22"
-tempfile = "3.2"
-thorin-dwp = "0.7"
 pathdiff = "0.2.0"
-serde_json = "1.0.59"
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 regex = "1.4"
-thin-vec = "0.2.12"
-
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_span = { path = "../rustc_span" }
-rustc_middle = { path = "../rustc_middle" }
-rustc_type_ir = { path = "../rustc_type_ir" }
 rustc_attr = { path = "../rustc_attr" }
-rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_incremental = { path = "../rustc_incremental" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_metadata = { path = "../rustc_metadata" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_query_system = { path = "../rustc_query_system" }
-rustc_target = { path = "../rustc_target" }
+rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
+rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
+rustc_target = { path = "../rustc_target" }
+rustc_type_ir = { path = "../rustc_type_ir" }
+serde_json = "1.0.59"
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tempfile = "3.2"
+thin-vec = "0.2.12"
+thorin-dwp = "0.7"
+tracing = "0.1"
+# tidy-alphabetical-end
 
 [target.'cfg(unix)'.dependencies]
+# tidy-alphabetical-start
 libc = "0.2.50"
+# tidy-alphabetical-end
 
 [dependencies.object]
 version = "0.32.0"
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index caade768795..22afb406326 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1449,47 +1449,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     fn get_caller_location(
         &mut self,
         bx: &mut Bx,
-        mut source_info: mir::SourceInfo,
+        source_info: mir::SourceInfo,
     ) -> OperandRef<'tcx, Bx::Value> {
-        let tcx = bx.tcx();
-
-        let mut span_to_caller_location = |span: Span| {
-            use rustc_session::RemapFileNameExt;
-            let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
-            let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
-            let const_loc = tcx.const_caller_location((
-                Symbol::intern(&caller.file.name.for_codegen(self.cx.sess()).to_string_lossy()),
-                caller.line as u32,
-                caller.col_display as u32 + 1,
-            ));
+        self.mir.caller_location_span(source_info, self.caller_location, bx.tcx(), |span: Span| {
+            let const_loc = bx.tcx().span_as_caller_location(span);
             OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
-        };
-
-        // Walk up the `SourceScope`s, in case some of them are from MIR inlining.
-        // If so, the starting `source_info.span` is in the innermost inlined
-        // function, and will be replaced with outer callsite spans as long
-        // as the inlined functions were `#[track_caller]`.
-        loop {
-            let scope_data = &self.mir.source_scopes[source_info.scope];
-
-            if let Some((callee, callsite_span)) = scope_data.inlined {
-                // Stop inside the most nested non-`#[track_caller]` function,
-                // before ever reaching its caller (which is irrelevant).
-                if !callee.def.requires_caller_location(tcx) {
-                    return span_to_caller_location(source_info.span);
-                }
-                source_info.span = callsite_span;
-            }
-
-            // Skip past all of the parents with `inlined: None`.
-            match scope_data.inlined_parent_scope {
-                Some(parent) => source_info.scope = parent,
-                None => break,
-            }
-        }
-
-        // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
-        self.caller_location.unwrap_or_else(|| span_to_caller_location(source_info.span))
+        })
     }
 
     fn get_personality_slot(&mut self, bx: &mut Bx) -> PlaceRef<'tcx, Bx::Value> {
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 4e47fed8640..c4f8841d71c 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -3,25 +3,25 @@ name = "rustc_const_eval"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
-tracing = "0.1"
+# tidy-alphabetical-start
 either = "1"
 rustc_apfloat = "0.2.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_span = { path = "../rustc_span" }
 rustc_type_ir = { path = "../rustc_type_ir" }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 46e00d0f176..669838308a5 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -90,7 +90,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 /// that inform us about the generic bounds of the constant. E.g., using an associated constant
 /// of a function's generic parameter will require knowledge about the bounds on the generic
 /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
-pub(super) fn mk_eval_cx<'mir, 'tcx>(
+pub(crate) fn mk_eval_cx<'mir, 'tcx>(
     tcx: TyCtxt<'tcx>,
     root_span: Span,
     param_env: ty::ParamEnv<'tcx>,
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 0d0ebe6f390..4b447229c5f 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -4,6 +4,7 @@ use rustc_middle::mir;
 use rustc_middle::mir::interpret::PointerArithmetic;
 use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::Span;
 use std::borrow::Borrow;
 use std::hash::Hash;
 use std::ops::ControlFlow;
@@ -181,6 +182,24 @@ impl interpret::MayLeak for ! {
 }
 
 impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
+    fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
+        let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
+        let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
+
+        use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
+        (
+            Symbol::intern(
+                &caller
+                    .file
+                    .name
+                    .for_scope(&self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS)
+                    .to_string_lossy(),
+            ),
+            u32::try_from(caller.line).unwrap(),
+            u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),
+        )
+    }
+
     /// "Intercept" a function call, because we have something special to do for it.
     /// All `#[rustc_do_not_const_check]` functions should be hooked here.
     /// If this returns `Some` function, which may be `instance` or a different function with
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index bcbe996be7d..d6ee6975cdd 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -1,12 +1,12 @@
 // Not in interpret to make sure we do not use private implementation details
 
 use crate::errors::MaxNumNodesInConstErr;
-use crate::interpret::{intern_const_alloc_recursive, InternKind, InterpCx, Scalar};
+use crate::interpret::InterpCx;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
+use rustc_span::source_map::DUMMY_SP;
 
 mod error;
 mod eval_queries;
@@ -20,20 +20,6 @@ pub use fn_queries::*;
 pub use machine::*;
 pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
 
-pub(crate) fn const_caller_location(
-    tcx: TyCtxt<'_>,
-    (file, line, col): (Symbol, u32, u32),
-) -> mir::ConstValue<'_> {
-    trace!("const_caller_location: {}:{}:{}", file, line, col);
-    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
-
-    let loc_place = ecx.alloc_caller_location(file, line, col);
-    if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
-        bug!("intern_const_alloc_recursive should not error in this case")
-    }
-    mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
-}
-
 // We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
 const VALTREE_MAX_NODES: usize = 100000;
 
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index ec0af79459c..07cab5e3400 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -595,6 +595,50 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
+    /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
+    /// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
+    pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
+        for frame in self.stack().iter().rev() {
+            debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
+
+            // Assert that the frame we look at is actually executing code currently
+            // (`loc` is `Right` when we are unwinding and the frame does not require cleanup).
+            let loc = frame.loc.left().unwrap();
+
+            // This could be a non-`Call` terminator (such as `Drop`), or not a terminator at all
+            // (such as `box`). Use the normal span by default.
+            let mut source_info = *frame.body.source_info(loc);
+
+            // If this is a `Call` terminator, use the `fn_span` instead.
+            let block = &frame.body.basic_blocks[loc.block];
+            if loc.statement_index == block.statements.len() {
+                debug!(
+                    "find_closest_untracked_caller_location: got terminator {:?} ({:?})",
+                    block.terminator(),
+                    block.terminator().kind,
+                );
+                if let mir::TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
+                    source_info.span = fn_span;
+                }
+            }
+
+            let caller_location = if frame.instance.def.requires_caller_location(*self.tcx) {
+                // We use `Err(())` as indication that we should continue up the call stack since
+                // this is a `#[track_caller]` function.
+                Some(Err(()))
+            } else {
+                None
+            };
+            if let Ok(span) =
+                frame.body.caller_location_span(source_info, caller_location, *self.tcx, Ok)
+            {
+                return span;
+            }
+        }
+
+        span_bug!(self.cur_span(), "no non-`#[track_caller]` frame found")
+    }
+
     #[inline(always)]
     pub fn layout_of_local(
         &self,
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index c48857fcf3c..b23cafc193a 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -22,8 +22,6 @@ use super::{
 
 use crate::fluent_generated as fluent;
 
-mod caller_location;
-
 fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
     let size = match kind {
         Primitive::Int(integer, _) => integer.size(),
@@ -130,8 +128,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         match intrinsic_name {
             sym::caller_location => {
                 let span = self.find_closest_untracked_caller_location();
-                let location = self.alloc_caller_location_for_span(span);
-                self.write_immediate(location.to_ref(self), dest)?;
+                let val = self.tcx.span_as_caller_location(span);
+                let val =
+                    self.const_val_to_op(val, self.tcx.caller_location_ty(), Some(dest.layout))?;
+                self.copy_op(&val, dest, /* allow_transmute */ false)?;
             }
 
             sym::min_align_of_val | sym::size_of_val => {
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
deleted file mode 100644
index 16b7decf9c4..00000000000
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-use rustc_ast::Mutability;
-use rustc_hir::lang_items::LangItem;
-use rustc_middle::mir::TerminatorKind;
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_span::{Span, Symbol};
-
-use crate::interpret::{
-    intrinsics::{InterpCx, Machine},
-    MPlaceTy, MemoryKind, Scalar,
-};
-
-impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
-    /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
-    /// frame which is not `#[track_caller]`.
-    pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
-        for frame in self.stack().iter().rev() {
-            debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
-
-            // Assert that the frame we look at is actually executing code currently
-            // (`loc` is `Right` when we are unwinding and the frame does not require cleanup).
-            let loc = frame.loc.left().unwrap();
-
-            // This could be a non-`Call` terminator (such as `Drop`), or not a terminator at all
-            // (such as `box`). Use the normal span by default.
-            let mut source_info = *frame.body.source_info(loc);
-
-            // If this is a `Call` terminator, use the `fn_span` instead.
-            let block = &frame.body.basic_blocks[loc.block];
-            if loc.statement_index == block.statements.len() {
-                debug!(
-                    "find_closest_untracked_caller_location: got terminator {:?} ({:?})",
-                    block.terminator(),
-                    block.terminator().kind
-                );
-                if let TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
-                    source_info.span = fn_span;
-                }
-            }
-
-            // Walk up the `SourceScope`s, in case some of them are from MIR inlining.
-            // If so, the starting `source_info.span` is in the innermost inlined
-            // function, and will be replaced with outer callsite spans as long
-            // as the inlined functions were `#[track_caller]`.
-            loop {
-                let scope_data = &frame.body.source_scopes[source_info.scope];
-
-                if let Some((callee, callsite_span)) = scope_data.inlined {
-                    // Stop inside the most nested non-`#[track_caller]` function,
-                    // before ever reaching its caller (which is irrelevant).
-                    if !callee.def.requires_caller_location(*self.tcx) {
-                        return source_info.span;
-                    }
-                    source_info.span = callsite_span;
-                }
-
-                // Skip past all of the parents with `inlined: None`.
-                match scope_data.inlined_parent_scope {
-                    Some(parent) => source_info.scope = parent,
-                    None => break,
-                }
-            }
-
-            // Stop inside the most nested non-`#[track_caller]` function,
-            // before ever reaching its caller (which is irrelevant).
-            if !frame.instance.def.requires_caller_location(*self.tcx) {
-                return source_info.span;
-            }
-        }
-
-        span_bug!(self.cur_span(), "no non-`#[track_caller]` frame found")
-    }
-
-    /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
-    pub(crate) fn alloc_caller_location(
-        &mut self,
-        filename: Symbol,
-        line: u32,
-        col: u32,
-    ) -> MPlaceTy<'tcx, M::Provenance> {
-        let loc_details = self.tcx.sess.opts.unstable_opts.location_detail;
-        // This can fail if rustc runs out of memory right here. Trying to emit an error would be
-        // pointless, since that would require allocating more memory than these short strings.
-        let file = if loc_details.file {
-            self.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not)
-                .unwrap()
-        } else {
-            // FIXME: This creates a new allocation each time. It might be preferable to
-            // perform this allocation only once, and re-use the `MPlaceTy`.
-            // See https://github.com/rust-lang/rust/pull/89920#discussion_r730012398
-            self.allocate_str("<redacted>", MemoryKind::CallerLocation, Mutability::Not).unwrap()
-        };
-        let line = if loc_details.line { Scalar::from_u32(line) } else { Scalar::from_u32(0) };
-        let col = if loc_details.column { Scalar::from_u32(col) } else { Scalar::from_u32(0) };
-
-        // Allocate memory for `CallerLocation` struct.
-        let loc_ty = self
-            .tcx
-            .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
-            .instantiate(*self.tcx, self.tcx.mk_args(&[self.tcx.lifetimes.re_erased.into()]));
-        let loc_layout = self.layout_of(loc_ty).unwrap();
-        let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
-
-        // Initialize fields.
-        self.write_immediate(file.to_ref(self), &self.project_field(&location, 0).unwrap())
-            .expect("writing to memory we just allocated cannot fail");
-        self.write_scalar(line, &self.project_field(&location, 1).unwrap())
-            .expect("writing to memory we just allocated cannot fail");
-        self.write_scalar(col, &self.project_field(&location, 2).unwrap())
-            .expect("writing to memory we just allocated cannot fail");
-
-        location
-    }
-
-    pub(crate) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
-        let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
-        let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
-
-        use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
-        (
-            Symbol::intern(
-                &caller
-                    .file
-                    .name
-                    .for_scope(&self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS)
-                    .to_string_lossy(),
-            ),
-            u32::try_from(caller.line).unwrap(),
-            u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),
-        )
-    }
-
-    pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::Provenance> {
-        let (file, line, column) = self.location_triple_for_span(span);
-        self.alloc_caller_location(file, line, column)
-    }
-}
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 1fd5723f277..7fc87ed8881 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -49,7 +49,7 @@ pub fn provide(providers: &mut Providers) {
     const_eval::provide(providers);
     providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
     providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
-    providers.const_caller_location = const_eval::const_caller_location;
+    providers.const_caller_location = util::caller_location::const_caller_location_provider;
     providers.eval_to_valtree = |tcx, param_env_and_value| {
         let (param_env, raw) = param_env_and_value.into_parts();
         const_eval::eval_to_valtree(tcx, param_env, raw)
diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs
new file mode 100644
index 00000000000..d67863d75d6
--- /dev/null
+++ b/compiler/rustc_const_eval/src/util/caller_location.rs
@@ -0,0 +1,63 @@
+use rustc_hir::LangItem;
+use rustc_middle::mir;
+use rustc_middle::ty::layout::LayoutOf;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
+use rustc_type_ir::Mutability;
+
+use crate::const_eval::{mk_eval_cx, CanAccessStatics, CompileTimeEvalContext};
+use crate::interpret::*;
+
+/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
+fn alloc_caller_location<'mir, 'tcx>(
+    ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
+    filename: Symbol,
+    line: u32,
+    col: u32,
+) -> MPlaceTy<'tcx> {
+    let loc_details = ecx.tcx.sess.opts.unstable_opts.location_detail;
+    // This can fail if rustc runs out of memory right here. Trying to emit an error would be
+    // pointless, since that would require allocating more memory than these short strings.
+    let file = if loc_details.file {
+        ecx.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not).unwrap()
+    } else {
+        // FIXME: This creates a new allocation each time. It might be preferable to
+        // perform this allocation only once, and re-use the `MPlaceTy`.
+        // See https://github.com/rust-lang/rust/pull/89920#discussion_r730012398
+        ecx.allocate_str("<redacted>", MemoryKind::CallerLocation, Mutability::Not).unwrap()
+    };
+    let line = if loc_details.line { Scalar::from_u32(line) } else { Scalar::from_u32(0) };
+    let col = if loc_details.column { Scalar::from_u32(col) } else { Scalar::from_u32(0) };
+
+    // Allocate memory for `CallerLocation` struct.
+    let loc_ty = ecx
+        .tcx
+        .type_of(ecx.tcx.require_lang_item(LangItem::PanicLocation, None))
+        .instantiate(*ecx.tcx, ecx.tcx.mk_args(&[ecx.tcx.lifetimes.re_erased.into()]));
+    let loc_layout = ecx.layout_of(loc_ty).unwrap();
+    let location = ecx.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
+
+    // Initialize fields.
+    ecx.write_immediate(file.to_ref(ecx), &ecx.project_field(&location, 0).unwrap())
+        .expect("writing to memory we just allocated cannot fail");
+    ecx.write_scalar(line, &ecx.project_field(&location, 1).unwrap())
+        .expect("writing to memory we just allocated cannot fail");
+    ecx.write_scalar(col, &ecx.project_field(&location, 2).unwrap())
+        .expect("writing to memory we just allocated cannot fail");
+
+    location
+}
+
+pub(crate) fn const_caller_location_provider(
+    tcx: TyCtxt<'_>,
+    (file, line, col): (Symbol, u32, u32),
+) -> mir::ConstValue<'_> {
+    trace!("const_caller_location: {}:{}:{}", file, line, col);
+    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
+
+    let loc_place = alloc_caller_location(&mut ecx, file, line, col);
+    if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
+        bug!("intern_const_alloc_recursive should not error in this case")
+    }
+    mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
+}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 040b3071e6f..1e58bd645cd 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -1,6 +1,7 @@
 use rustc_middle::mir;
 
 mod alignment;
+pub(crate) mod caller_location;
 mod check_validity_requirement;
 mod compare_types;
 mod type_name;
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index dce4e199e17..2701fdbbd77 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -3,35 +3,31 @@ name = "rustc_data_structures"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 arrayvec = { version = "0.7", default-features = false }
 bitflags = "1.2.1"
+elsa = "=1.7.1"
 ena = "0.14.2"
 indexmap = { version = "2.0.0" }
+itertools = "0.10.1"
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 libc = "0.2"
 measureme = "10.0.0"
-rustc-rayon-core = { version = "0.5.0", optional = true }
+rustc-hash = "1.1.0"
 rustc-rayon = { version = "0.5.0", optional = true }
+rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_arena = { path = "../rustc_arena" }
 rustc_graphviz = { path = "../rustc_graphviz" }
-rustc-hash = "1.1.0"
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
-smallvec = { version = "1.8.1", features = [
-    "const_generics",
-    "union",
-    "may_dangle",
-] }
+smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
 stacker = "0.1.15"
 tempfile = "3.2"
 thin-vec = "0.2.12"
 tracing = "0.1"
-elsa = "=1.7.1"
-itertools = "0.10.1"
+# tidy-alphabetical-end
 
 [dependencies.parking_lot]
 version = "0.12"
@@ -47,7 +43,11 @@ features = [
 ]
 
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+# tidy-alphabetical-start
 memmap2 = "0.2.1"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon", "rustc-rayon-core"]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index d7c295418ba..ae9712ad66d 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -7,4 +7,6 @@ edition = "2021"
 crate-type = ["dylib"]
 
 [dependencies]
+# tidy-alphabetical-start
 rustc_driver_impl = { path = "../rustc_driver_impl" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index d931a8dab9b..252803e3cba 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -3,8 +3,6 @@ name = "rustc_driver_impl"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
 # tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
@@ -57,7 +55,9 @@ tracing = { version = "0.1.35" }
 # tidy-alphabetical-end
 
 [target.'cfg(unix)'.dependencies]
+# tidy-alphabetical-start
 libc = "0.2"
+# tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
 version = "0.48.0"
@@ -66,6 +66,7 @@ features = [
 ]
 
 [features]
+# tidy-alphabetical-start
 llvm = ['rustc_interface/llvm']
 max_level_info = ['rustc_log/max_level_info']
 rustc_use_parallel_compiler = [
@@ -73,3 +74,4 @@ rustc_use_parallel_compiler = [
     'rustc_interface/rustc_use_parallel_compiler',
     'rustc_middle/rustc_use_parallel_compiler'
 ]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 37897b8d702..e4cb3fd25cd 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -317,13 +317,11 @@ fn run_compiler(
         return Ok(());
     }
 
-    let cfg = interface::parse_cfg(&early_error_handler, matches.opt_strs("cfg"));
-    let check_cfg = interface::parse_check_cfg(&early_error_handler, matches.opt_strs("check-cfg"));
     let (odir, ofile) = make_output(&matches);
     let mut config = interface::Config {
         opts: sopts,
-        crate_cfg: cfg,
-        crate_check_cfg: check_cfg,
+        crate_cfg: matches.opt_strs("cfg"),
+        crate_check_cfg: matches.opt_strs("check-cfg"),
         input: Input::File(PathBuf::new()),
         output_file: ofile,
         output_dir: odir,
diff --git a/compiler/rustc_error_codes/Cargo.toml b/compiler/rustc_error_codes/Cargo.toml
index 7d5f3e4672a..de668b81b7e 100644
--- a/compiler/rustc_error_codes/Cargo.toml
+++ b/compiler/rustc_error_codes/Cargo.toml
@@ -2,3 +2,7 @@
 name = "rustc_error_codes"
 version = "0.0.0"
 edition = "2021"
+
+[dependencies]
+# tidy-alphabetical-start
+# tidy-alphabetical-end
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 4df5a8d48fd..1969feed48f 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -3,23 +3,25 @@ name = "rustc_error_messages"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
+icu_list = "1.2"
+icu_locid = "1.2"
+icu_provider_adapters = "1.2"
 intl-memoizer = "0.5.1"
 rustc_baked_icu_data = { path = "../rustc_baked_icu_data" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-rustc_macros = { path = "../rustc_macros" }
 tracing = "0.1"
 unic-langid = { version = "0.9.0", features = ["macros"] }
-icu_list = "1.2"
-icu_locid = "1.2"
-icu_provider_adapters = "1.2"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 rustc_use_parallel_compiler = ['rustc_baked_icu_data/rustc_use_parallel_compiler']
+# tidy-alphabetical-end
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index faab9f09da8..fc3ff835a81 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -3,29 +3,29 @@ name = "rustc_errors"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
-tracing = "0.1"
+# tidy-alphabetical-start
+annotate-snippets = "0.9"
+derive_setters = "0.1.6"
 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_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_lint_defs = { path = "../rustc_lint_defs" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_target = { path = "../rustc_target" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_type_ir = { path = "../rustc_type_ir" }
-unicode-width = "0.1.4"
-termcolor = "1.2.0"
-annotate-snippets = "0.9"
-termize = "0.1.1"
 serde = { version = "1.0.125", features = [ "derive" ] }
 serde_json = "1.0.59"
-derive_setters = "0.1.6"
+termcolor = "1.2.0"
+termize = "0.1.1"
+tracing = "0.1"
+unicode-width = "0.1.4"
+# tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
 version = "0.48.0"
@@ -36,4 +36,6 @@ features = [
 ]
 
 [features]
+# tidy-alphabetical-start
 rustc_use_parallel_compiler = ['rustc_error_messages/rustc_use_parallel_compiler']
+# tidy-alphabetical-end
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index 02da5b5dc53..9189a501aa5 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -8,9 +8,10 @@ build = false
 doctest = false
 
 [dependencies]
+# tidy-alphabetical-start
 crossbeam-channel = "0.5.0"
-rustc_ast_passes = { path = "../rustc_ast_passes" }
 rustc_ast = { path = "../rustc_ast" }
+rustc_ast_passes = { path = "../rustc_ast_passes" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -25,6 +26,7 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+termcolor = "1.2"
 thin-vec = "0.2.12"
 tracing = "0.1"
-termcolor = "1.2"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml
index 6f6468646fc..9df320e1279 100644
--- a/compiler/rustc_feature/Cargo.toml
+++ b/compiler/rustc_feature/Cargo.toml
@@ -3,8 +3,8 @@ name = "rustc_feature"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_span = { path = "../rustc_span" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index 60b8e1e3786..872dd29a7a8 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -7,10 +7,12 @@ edition = "2021"
 proc-macro = true
 
 [dependencies]
+# tidy-alphabetical-start
 annotate-snippets = "0.9"
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
-syn = { version = "2", features = ["full"] }
 proc-macro2 = "1"
 quote = "1"
+syn = { version = "2", features = ["full"] }
 unic-langid = { version = "0.9.0", features = ["macros"] }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml
index 34c3fe2a005..4b76200c06c 100644
--- a/compiler/rustc_fs_util/Cargo.toml
+++ b/compiler/rustc_fs_util/Cargo.toml
@@ -2,3 +2,7 @@
 name = "rustc_fs_util"
 version = "0.0.0"
 edition = "2021"
+
+[dependencies]
+# tidy-alphabetical-start
+# tidy-alphabetical-end
diff --git a/compiler/rustc_graphviz/Cargo.toml b/compiler/rustc_graphviz/Cargo.toml
index d657fdb1a77..780004ae3fb 100644
--- a/compiler/rustc_graphviz/Cargo.toml
+++ b/compiler/rustc_graphviz/Cargo.toml
@@ -2,3 +2,7 @@
 name = "rustc_graphviz"
 version = "0.0.0"
 edition = "2021"
+
+[dependencies]
+# tidy-alphabetical-start
+# tidy-alphabetical-end
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 129f8d235ad..a72c4d0f18b 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -3,18 +3,18 @@ name = "rustc_hir"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
+odht = { version = "0.3.1", features = ["nightly"] }
 rustc_arena = { path = "../rustc_arena" }
-rustc_target = { path = "../rustc_target" }
-rustc_macros = { path = "../rustc_macros" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_index = { path = "../rustc_index" }
-rustc_span = { path = "../rustc_span" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
-rustc_ast = { path = "../rustc_ast" }
-tracing = "0.1"
+rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-odht = { version = "0.3.1", features = ["nightly"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index 4eb94d5bc63..b671bebeb05 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -8,23 +8,25 @@ test = false
 doctest = false
 
 [dependencies]
+# tidy-alphabetical-start
 rustc_arena = { path = "../rustc_arena" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_middle = { path = "../rustc_middle" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
+rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_target = { path = "../rustc_target" }
-rustc_session = { path = "../rustc_session" }
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-rustc_ast = { path = "../rustc_ast" }
-rustc_span = { path = "../rustc_span" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
-rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
+rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_type_ir = { path = "../rustc_type_ir" }
-rustc_feature = { path = "../rustc_feature" }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml
index 1ea7be1ae7b..aacf41b6eb7 100644
--- a/compiler/rustc_hir_pretty/Cargo.toml
+++ b/compiler/rustc_hir_pretty/Cargo.toml
@@ -3,11 +3,11 @@ name = "rustc_hir_pretty"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
+rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_target = { path = "../rustc_target" }
 rustc_span = { path = "../rustc_span" }
-rustc_ast = { path = "../rustc_ast" }
+rustc_target = { path = "../rustc_target" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 0666eeee4d3..0062889d244 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -3,28 +3,28 @@ name = "rustc_hir_typeck"
 version = "0.0.0"
 edition = "2021"
 
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
 [dependencies]
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_index = { path = "../rustc_index" }
-rustc_infer = { path = "../rustc_infer" }
+rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
+rustc_index = { path = "../rustc_index" }
+rustc_infer = { path = "../rustc_infer" }
 rustc_lint = { path = "../rustc_lint" }
-rustc_middle = { path = "../rustc_middle" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_type_ir = { path = "../rustc_type_ir" }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml
index 59a0623c1e1..46a63b02e84 100644
--- a/compiler/rustc_incremental/Cargo.toml
+++ b/compiler/rustc_incremental/Cargo.toml
@@ -3,15 +3,14 @@ name = "rustc_incremental"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 rand = "0.8.4"
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_macros = { path = "../rustc_macros" }
@@ -21,3 +20,4 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml
index e1cda5a9edd..856f8a67dd6 100644
--- a/compiler/rustc_index/Cargo.toml
+++ b/compiler/rustc_index/Cargo.toml
@@ -3,14 +3,16 @@ name = "rustc_index"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 arrayvec = { version = "0.7", default-features = false }
-rustc_serialize = { path = "../rustc_serialize", optional = true }
 rustc_macros = { path = "../rustc_macros", optional = true }
+rustc_serialize = { path = "../rustc_serialize", optional = true }
 smallvec = "1.8.1"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 default = ["nightly"]
 nightly = ["rustc_serialize", "rustc_macros"]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 9dd5868adc7..00251a19226 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -7,15 +7,17 @@ edition = "2021"
 doctest = false
 
 [dependencies]
-tracing = "0.1"
-rustc_middle = { path = "../rustc_middle" }
+# tidy-alphabetical-start
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 7a335827f37..32966011932 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -5,7 +5,8 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
 use std::fmt;
 use std::iter;
@@ -108,5 +109,66 @@ pub fn report_object_safety_error<'tcx>(
             violation.solution(&mut err);
         }
     }
+
+    let impls_of = tcx.trait_impls_of(trait_def_id);
+    let impls = if impls_of.blanket_impls().is_empty() {
+        impls_of
+            .non_blanket_impls()
+            .values()
+            .flatten()
+            .filter(|def_id| {
+                !matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..))
+            })
+            .collect::<Vec<_>>()
+    } else {
+        vec![]
+    };
+    let externally_visible = if !impls.is_empty()
+        && let Some(def_id) = trait_def_id.as_local()
+        && tcx.effective_visibilities(()).is_exported(def_id)
+    {
+        true
+    } else {
+        false
+    };
+    match &impls[..] {
+        [] => {}
+        _ if impls.len() > 9 => {}
+        [only] if externally_visible => {
+            err.help(with_no_trimmed_paths!(format!(
+                "only type `{}` is seen to implement the trait in this crate, consider using it \
+                 directly instead",
+                tcx.type_of(*only).instantiate_identity(),
+            )));
+        }
+        [only] => {
+            err.help(with_no_trimmed_paths!(format!(
+                "only type `{}` implements the trait, consider using it directly instead",
+                tcx.type_of(*only).instantiate_identity(),
+            )));
+        }
+        impls => {
+            let types = impls
+                .iter()
+                .map(|t| {
+                    with_no_trimmed_paths!(format!("  {}", tcx.type_of(*t).instantiate_identity(),))
+                })
+                .collect::<Vec<_>>();
+            err.help(format!(
+                "the following types implement the trait, consider defining an enum where each \
+                 variant holds one of these types, implementing `{}` for this new enum and using \
+                 it instead:\n{}",
+                trait_str,
+                types.join("\n"),
+            ));
+        }
+    }
+    if externally_visible {
+        err.note(format!(
+            "`{trait_str}` can be implemented in other crates; if you want to support your users \
+             passing their own types here, you can't refer to a specific type",
+        ));
+    }
+
     err
 }
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index b280665057c..a73152601b3 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -3,54 +3,56 @@ name = "rustc_interface"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 libloading = "0.7.1"
-tracing = "0.1"
-rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc-rayon = { version = "0.5.0", optional = true }
+rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_ast = { path = "../rustc_ast" }
+rustc_ast_lowering = { path = "../rustc_ast_lowering" }
+rustc_ast_passes = { path = "../rustc_ast_passes" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_borrowck = { path = "../rustc_borrowck" }
 rustc_builtin_macros = { path = "../rustc_builtin_macros" }
+rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true }
+rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
+rustc_const_eval = { path = "../rustc_const_eval" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_fs_util = { path = "../rustc_fs_util" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_parse = { path = "../rustc_parse" }
-rustc_session = { path = "../rustc_session" }
-rustc_span = { path = "../rustc_span" }
-rustc_middle = { path = "../rustc_middle" }
-rustc_ast_lowering = { path = "../rustc_ast_lowering" }
-rustc_ast_passes = { path = "../rustc_ast_passes" }
-rustc_incremental = { path = "../rustc_incremental" }
-rustc_traits = { path = "../rustc_traits" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
-rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
-rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true }
 rustc_hir = { path = "../rustc_hir" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
+rustc_hir_typeck = { path = "../rustc_hir_typeck" }
+rustc_incremental = { path = "../rustc_incremental" }
+rustc_lint = { path = "../rustc_lint" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_metadata = { path = "../rustc_metadata" }
-rustc_const_eval = { path = "../rustc_const_eval" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_mir_build = { path = "../rustc_mir_build" }
 rustc_mir_transform = { path = "../rustc_mir_transform" }
 rustc_monomorphize = { path = "../rustc_monomorphize" }
+rustc_parse = { path = "../rustc_parse" }
 rustc_passes = { path = "../rustc_passes" }
-rustc_hir_analysis = { path = "../rustc_hir_analysis" }
-rustc_hir_typeck = { path = "../rustc_hir_typeck" }
-rustc_lint = { path = "../rustc_lint" }
-rustc_errors = { path = "../rustc_errors" }
 rustc_plugin_impl = { path = "../rustc_plugin_impl" }
 rustc_privacy = { path = "../rustc_privacy" }
-rustc_query_system = { path = "../rustc_query_system" }
 rustc_query_impl = { path = "../rustc_query_impl" }
+rustc_query_system = { path = "../rustc_query_system" }
 rustc_resolve = { path = "../rustc_resolve" }
+rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
+rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_traits = { path = "../rustc_traits" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
+tracing = "0.1"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 llvm = ['rustc_codegen_llvm']
 rustc_use_parallel_compiler = ['rustc-rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler', 'rustc_errors/rustc_use_parallel_compiler']
+# tidy-alphabetical-end
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs
index 6fa989bb96c..ef00ced67ff 100644
--- a/compiler/rustc_interface/src/callbacks.rs
+++ b/compiler/rustc_interface/src/callbacks.rs
@@ -33,9 +33,7 @@ fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnost
     tls::with_context_opt(|icx| {
         if let Some(icx) = icx {
             if let Some(diagnostics) = icx.diagnostics {
-                let mut diagnostics = diagnostics.lock();
-                diagnostics.extend(Some(diagnostic.clone()));
-                std::mem::drop(diagnostics);
+                diagnostics.lock().extend(Some(diagnostic.clone()));
             }
 
             // Diagnostics are tracked, we can ignore the dependency.
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index e703fe228c3..26034dbaf99 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -64,296 +64,266 @@ impl Compiler {
 }
 
 /// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`.
-pub fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg<String> {
-    // This creates a short-lived `SessionGlobals`, containing an interner. The
-    // parsed values are converted from symbols to strings before exiting
-    // because the symbols are meaningless once the interner is gone.
-    rustc_span::create_default_session_if_not_set_then(move |_| {
-        cfgs.into_iter()
-            .map(|s| {
-                let sess = ParseSess::with_silent_emitter(Some(format!(
-                    "this error occurred on the command line: `--cfg={s}`"
-                )));
-                let filename = FileName::cfg_spec_source_code(&s);
-
-                macro_rules! error {
-                    ($reason: expr) => {
-                        handler.early_error(format!(
-                            concat!("invalid `--cfg` argument: `{}` (", $reason, ")"),
-                            s
-                        ));
-                    };
-                }
-
-                match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
-                    Ok(mut parser) => match parser.parse_meta_item() {
-                        Ok(meta_item) if parser.token == token::Eof => {
-                            if meta_item.path.segments.len() != 1 {
-                                error!("argument key must be an identifier");
-                            }
-                            match &meta_item.kind {
-                                MetaItemKind::List(..) => {}
-                                MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
-                                    error!("argument value must be a string");
-                                }
-                                MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                                    let ident = meta_item.ident().expect("multi-segment cfg key");
-                                    return (
-                                        ident.name.to_string(),
-                                        meta_item.value_str().map(|sym| sym.to_string()),
-                                    );
-                                }
-                            }
-                        }
-                        Ok(..) => {}
-                        Err(err) => err.cancel(),
-                    },
-                    Err(errs) => drop(errs),
-                }
-
-                // If the user tried to use a key="value" flag, but is missing the quotes, provide
-                // a hint about how to resolve this.
-                if s.contains('=') && !s.contains("=\"") && !s.ends_with('"') {
-                    error!(concat!(
-                        r#"expected `key` or `key="value"`, ensure escaping is appropriate"#,
-                        r#" for your shell, try 'key="value"' or key=\"value\""#
-                    ));
-                } else {
-                    error!(r#"expected `key` or `key="value"`"#);
-                }
-            })
-            .collect::<Cfg<String>>()
-    })
-}
-
-/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
-pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg<String> {
-    // The comment about `SessionGlobals` and symbols in `parse_cfg` above
-    // applies here too.
-    rustc_span::create_default_session_if_not_set_then(move |_| {
-        // If any --check-cfg is passed then exhaustive_values and exhaustive_names
-        // are enabled by default.
-        let exhaustive_names = !specs.is_empty();
-        let exhaustive_values = !specs.is_empty();
-        let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };
-
-        let mut old_syntax = None;
-        for s in specs {
+pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg {
+    cfgs.into_iter()
+        .map(|s| {
             let sess = ParseSess::with_silent_emitter(Some(format!(
-                "this error occurred on the command line: `--check-cfg={s}`"
+                "this error occurred on the command line: `--cfg={s}`"
             )));
             let filename = FileName::cfg_spec_source_code(&s);
 
             macro_rules! error {
-                ($reason:expr) => {
+                ($reason: expr) => {
                     handler.early_error(format!(
-                        concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
+                        concat!("invalid `--cfg` argument: `{}` (", $reason, ")"),
                         s
-                    ))
+                    ));
                 };
             }
 
-            let expected_error = || -> ! {
-                error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
-            };
+            match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
+                Ok(mut parser) => match parser.parse_meta_item() {
+                    Ok(meta_item) if parser.token == token::Eof => {
+                        if meta_item.path.segments.len() != 1 {
+                            error!("argument key must be an identifier");
+                        }
+                        match &meta_item.kind {
+                            MetaItemKind::List(..) => {}
+                            MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
+                                error!("argument value must be a string");
+                            }
+                            MetaItemKind::NameValue(..) | MetaItemKind::Word => {
+                                let ident = meta_item.ident().expect("multi-segment cfg key");
+                                return (ident.name, meta_item.value_str());
+                            }
+                        }
+                    }
+                    Ok(..) => {}
+                    Err(err) => err.cancel(),
+                },
+                Err(errs) => drop(errs),
+            }
 
-            let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string())
-            else {
-                expected_error();
-            };
+            // If the user tried to use a key="value" flag, but is missing the quotes, provide
+            // a hint about how to resolve this.
+            if s.contains('=') && !s.contains("=\"") && !s.ends_with('"') {
+                error!(concat!(
+                    r#"expected `key` or `key="value"`, ensure escaping is appropriate"#,
+                    r#" for your shell, try 'key="value"' or key=\"value\""#
+                ));
+            } else {
+                error!(r#"expected `key` or `key="value"`"#);
+            }
+        })
+        .collect::<Cfg>()
+}
 
-            let meta_item = match parser.parse_meta_item() {
-                Ok(meta_item) if parser.token == token::Eof => meta_item,
-                Ok(..) => expected_error(),
-                Err(err) => {
-                    err.cancel();
-                    expected_error();
-                }
+/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
+pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg {
+    // If any --check-cfg is passed then exhaustive_values and exhaustive_names
+    // are enabled by default.
+    let exhaustive_names = !specs.is_empty();
+    let exhaustive_values = !specs.is_empty();
+    let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };
+
+    let mut old_syntax = None;
+    for s in specs {
+        let sess = ParseSess::with_silent_emitter(Some(format!(
+            "this error occurred on the command line: `--check-cfg={s}`"
+        )));
+        let filename = FileName::cfg_spec_source_code(&s);
+
+        macro_rules! error {
+            ($reason:expr) => {
+                handler.early_error(format!(
+                    concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
+                    s
+                ))
             };
+        }
+
+        let expected_error = || -> ! {
+            error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
+        };
+
+        let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string())
+        else {
+            expected_error();
+        };
 
-            let Some(args) = meta_item.meta_item_list() else {
+        let meta_item = match parser.parse_meta_item() {
+            Ok(meta_item) if parser.token == token::Eof => meta_item,
+            Ok(..) => expected_error(),
+            Err(err) => {
+                err.cancel();
                 expected_error();
-            };
+            }
+        };
 
-            if meta_item.has_name(sym::names) {
-                // defaults are flipped for the old syntax
-                if old_syntax == None {
-                    check_cfg.exhaustive_names = false;
-                    check_cfg.exhaustive_values = false;
-                }
-                old_syntax = Some(true);
-
-                check_cfg.exhaustive_names = true;
-                for arg in args {
-                    if arg.is_word() && arg.ident().is_some() {
-                        let ident = arg.ident().expect("multi-segment cfg key");
-                        check_cfg
-                            .expecteds
-                            .entry(ident.name.to_string())
-                            .or_insert(ExpectedValues::Any);
-                    } else {
-                        error!("`names()` arguments must be simple identifiers");
-                    }
-                }
-            } else if meta_item.has_name(sym::values) {
-                // defaults are flipped for the old syntax
-                if old_syntax == None {
-                    check_cfg.exhaustive_names = false;
-                    check_cfg.exhaustive_values = false;
+        let Some(args) = meta_item.meta_item_list() else {
+            expected_error();
+        };
+
+        let mut set_old_syntax = || {
+            // defaults are flipped for the old syntax
+            if old_syntax == None {
+                check_cfg.exhaustive_names = false;
+                check_cfg.exhaustive_values = false;
+            }
+            old_syntax = Some(true);
+        };
+
+        if meta_item.has_name(sym::names) {
+            set_old_syntax();
+
+            check_cfg.exhaustive_names = true;
+            for arg in args {
+                if arg.is_word() && let Some(ident) = arg.ident() {
+                    check_cfg.expecteds.entry(ident.name).or_insert(ExpectedValues::Any);
+                } else {
+                    error!("`names()` arguments must be simple identifiers");
                 }
-                old_syntax = Some(true);
-
-                if let Some((name, values)) = args.split_first() {
-                    if name.is_word() && name.ident().is_some() {
-                        let ident = name.ident().expect("multi-segment cfg key");
-                        let expected_values = check_cfg
-                            .expecteds
-                            .entry(ident.name.to_string())
-                            .and_modify(|expected_values| match expected_values {
-                                ExpectedValues::Some(_) => {}
-                                ExpectedValues::Any => {
-                                    // handle the case where names(...) was done
-                                    // before values by changing to a list
-                                    *expected_values = ExpectedValues::Some(FxHashSet::default());
-                                }
-                            })
-                            .or_insert_with(|| ExpectedValues::Some(FxHashSet::default()));
-
-                        let ExpectedValues::Some(expected_values) = expected_values else {
-                            bug!("`expected_values` should be a list a values")
-                        };
-
-                        for val in values {
-                            if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) {
-                                expected_values.insert(Some(s.to_string()));
-                            } else {
-                                error!("`values()` arguments must be string literals");
+            }
+        } else if meta_item.has_name(sym::values) {
+            set_old_syntax();
+
+            if let Some((name, values)) = args.split_first() {
+                if name.is_word() && let Some(ident) = name.ident() {
+                    let expected_values = check_cfg
+                        .expecteds
+                        .entry(ident.name)
+                        .and_modify(|expected_values| match expected_values {
+                            ExpectedValues::Some(_) => {}
+                            ExpectedValues::Any => {
+                                // handle the case where names(...) was done
+                                // before values by changing to a list
+                                *expected_values = ExpectedValues::Some(FxHashSet::default());
                             }
-                        }
+                        })
+                        .or_insert_with(|| ExpectedValues::Some(FxHashSet::default()));
 
-                        if values.is_empty() {
-                            expected_values.insert(None);
+                    let ExpectedValues::Some(expected_values) = expected_values else {
+                        bug!("`expected_values` should be a list a values")
+                    };
+
+                    for val in values {
+                        if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) {
+                            expected_values.insert(Some(*s));
+                        } else {
+                            error!("`values()` arguments must be string literals");
                         }
-                    } else {
-                        error!("`values()` first argument must be a simple identifier");
                     }
-                } else if args.is_empty() {
-                    check_cfg.exhaustive_values = true;
+
+                    if values.is_empty() {
+                        expected_values.insert(None);
+                    }
                 } else {
-                    expected_error();
+                    error!("`values()` first argument must be a simple identifier");
                 }
-            } else if meta_item.has_name(sym::cfg) {
-                old_syntax = Some(false);
+            } else if args.is_empty() {
+                check_cfg.exhaustive_values = true;
+            } else {
+                expected_error();
+            }
+        } else if meta_item.has_name(sym::cfg) {
+            old_syntax = Some(false);
 
-                let mut names = Vec::new();
-                let mut values: FxHashSet<_> = Default::default();
+            let mut names = Vec::new();
+            let mut values: FxHashSet<_> = Default::default();
 
-                let mut any_specified = false;
-                let mut values_specified = false;
-                let mut values_any_specified = false;
+            let mut any_specified = false;
+            let mut values_specified = false;
+            let mut values_any_specified = false;
 
-                for arg in args {
-                    if arg.is_word() && let Some(ident) = arg.ident() {
-                        if values_specified {
-                            error!("`cfg()` names cannot be after values");
-                        }
-                        names.push(ident);
-                    } else if arg.has_name(sym::any)
-                        && let Some(args) = arg.meta_item_list()
-                    {
-                        if any_specified {
-                            error!("`any()` cannot be specified multiple times");
-                        }
-                        any_specified = true;
-                        if !args.is_empty() {
-                            error!("`any()` must be empty");
-                        }
-                    } else if arg.has_name(sym::values)
-                        && let Some(args) = arg.meta_item_list()
-                    {
-                        if names.is_empty() {
-                            error!("`values()` cannot be specified before the names");
-                        } else if values_specified {
-                            error!("`values()` cannot be specified multiple times");
-                        }
-                        values_specified = true;
-
-                        for arg in args {
-                            if let Some(LitKind::Str(s, _)) =
-                                arg.lit().map(|lit| &lit.kind)
-                            {
-                                values.insert(Some(s.to_string()));
-                            } else if arg.has_name(sym::any)
-                                && let Some(args) = arg.meta_item_list()
-                            {
-                                if values_any_specified {
-                                    error!(
-                                        "`any()` in `values()` cannot be specified multiple times"
-                                    );
-                                }
-                                values_any_specified = true;
-                                if !args.is_empty() {
-                                    error!("`any()` must be empty");
-                                }
-                            } else {
-                                error!(
-                                    "`values()` arguments must be string literals or `any()`"
-                                );
+            for arg in args {
+                if arg.is_word() && let Some(ident) = arg.ident() {
+                    if values_specified {
+                        error!("`cfg()` names cannot be after values");
+                    }
+                    names.push(ident);
+                } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() {
+                    if any_specified {
+                        error!("`any()` cannot be specified multiple times");
+                    }
+                    any_specified = true;
+                    if !args.is_empty() {
+                        error!("`any()` must be empty");
+                    }
+                } else if arg.has_name(sym::values) && let Some(args) = arg.meta_item_list() {
+                    if names.is_empty() {
+                        error!("`values()` cannot be specified before the names");
+                    } else if values_specified {
+                        error!("`values()` cannot be specified multiple times");
+                    }
+                    values_specified = true;
+
+                    for arg in args {
+                        if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) {
+                            values.insert(Some(*s));
+                        } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() {
+                            if values_any_specified {
+                                error!("`any()` in `values()` cannot be specified multiple times");
                             }
+                            values_any_specified = true;
+                            if !args.is_empty() {
+                                error!("`any()` must be empty");
+                            }
+                        } else {
+                            error!("`values()` arguments must be string literals or `any()`");
                         }
-                    } else {
-                        error!(
-                            "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"
-                        );
                     }
-                }
-
-                if values.is_empty() && !values_any_specified && !any_specified {
-                    values.insert(None);
-                } else if !values.is_empty() && values_any_specified {
+                } else {
                     error!(
-                        "`values()` arguments cannot specify string literals and `any()` at the same time"
+                        "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"
                     );
                 }
+            }
 
-                if any_specified {
-                    if names.is_empty()
-                        && values.is_empty()
-                        && !values_specified
-                        && !values_any_specified
-                    {
-                        check_cfg.exhaustive_names = false;
-                    } else {
-                        error!("`cfg(any())` can only be provided in isolation");
-                    }
+            if values.is_empty() && !values_any_specified && !any_specified {
+                values.insert(None);
+            } else if !values.is_empty() && values_any_specified {
+                error!(
+                    "`values()` arguments cannot specify string literals and `any()` at the same time"
+                );
+            }
+
+            if any_specified {
+                if names.is_empty()
+                    && values.is_empty()
+                    && !values_specified
+                    && !values_any_specified
+                {
+                    check_cfg.exhaustive_names = false;
                 } else {
-                    for name in names {
-                        check_cfg
-                            .expecteds
-                            .entry(name.to_string())
-                            .and_modify(|v| match v {
-                                ExpectedValues::Some(v) if !values_any_specified => {
-                                    v.extend(values.clone())
-                                }
-                                ExpectedValues::Some(_) => *v = ExpectedValues::Any,
-                                ExpectedValues::Any => {}
-                            })
-                            .or_insert_with(|| {
-                                if values_any_specified {
-                                    ExpectedValues::Any
-                                } else {
-                                    ExpectedValues::Some(values.clone())
-                                }
-                            });
-                    }
+                    error!("`cfg(any())` can only be provided in isolation");
                 }
             } else {
-                expected_error();
+                for name in names {
+                    check_cfg
+                        .expecteds
+                        .entry(name.name)
+                        .and_modify(|v| match v {
+                            ExpectedValues::Some(v) if !values_any_specified => {
+                                v.extend(values.clone())
+                            }
+                            ExpectedValues::Some(_) => *v = ExpectedValues::Any,
+                            ExpectedValues::Any => {}
+                        })
+                        .or_insert_with(|| {
+                            if values_any_specified {
+                                ExpectedValues::Any
+                            } else {
+                                ExpectedValues::Some(values.clone())
+                            }
+                        });
+                }
             }
+        } else {
+            expected_error();
         }
+    }
 
-        check_cfg
-    })
+    check_cfg
 }
 
 /// The compiler configuration
@@ -361,9 +331,9 @@ pub struct Config {
     /// Command line options
     pub opts: config::Options,
 
-    /// cfg! configuration in addition to the default ones
-    pub crate_cfg: Cfg<String>,
-    pub crate_check_cfg: CheckCfg<String>,
+    /// Unparsed cfg! configuration in addition to the default ones.
+    pub crate_cfg: Vec<String>,
+    pub crate_check_cfg: Vec<String>,
 
     pub input: Input,
     pub output_dir: Option<PathBuf>,
@@ -436,8 +406,8 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             let (mut sess, codegen_backend) = util::create_session(
                 &handler,
                 config.opts,
-                config.crate_cfg,
-                config.crate_check_cfg,
+                parse_cfg(&handler, config.crate_cfg),
+                parse_check_cfg(&handler, config.crate_check_cfg),
                 config.locale_resources,
                 config.file_loader,
                 CompilerIO {
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 884afae23d8..2099a6d59cb 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -392,34 +392,16 @@ fn generated_output_paths(
     out_filenames
 }
 
-// Runs `f` on every output file path and returns the first non-None result, or None if `f`
-// returns None for every file path.
-fn check_output<F, T>(output_paths: &[PathBuf], f: F) -> Option<T>
-where
-    F: Fn(&PathBuf) -> Option<T>,
-{
-    for output_path in output_paths {
-        if let Some(result) = f(output_path) {
-            return Some(result);
-        }
-    }
-    None
-}
-
 fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool {
     let input_path = try_canonicalize(input_path).ok();
     if input_path.is_none() {
         return false;
     }
-    let check = |output_path: &PathBuf| {
-        if try_canonicalize(output_path).ok() == input_path { Some(()) } else { None }
-    };
-    check_output(output_paths, check).is_some()
+    output_paths.iter().any(|output_path| try_canonicalize(output_path).ok() == input_path)
 }
 
-fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
-    let check = |output_path: &PathBuf| output_path.is_dir().then(|| output_path.clone());
-    check_output(output_paths, check)
+fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<&PathBuf> {
+    output_paths.iter().find(|output_path| output_path.is_dir())
 }
 
 fn escape_dep_filename(filename: &str) -> String {
@@ -602,9 +584,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> {
     let (_, krate) = &*tcx.resolver_for_lowering(()).borrow();
     let crate_name = tcx.crate_name(LOCAL_CRATE);
 
-    // FIXME: rustdoc passes &[] instead of &krate.attrs here
     let outputs = util::build_output_filenames(&krate.attrs, sess);
-
     let output_paths =
         generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name);
 
@@ -882,16 +862,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
 
             let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr));
 
-            // A slightly edited version of the code in `rustc_trait_selection::traits::vtable::vtable_entries`,
-            // that works without self type and just counts number of entries.
+            // A slightly edited version of the code in
+            // `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self
+            // type and just counts number of entries.
             //
-            // Note that this is technically wrong, for traits which have associated types in supertraits:
+            // Note that this is technically wrong, for traits which have associated types in
+            // supertraits:
             //
             //   trait A: AsRef<Self::T> + AsRef<()> { type T; }
             //
-            // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>` and
-            // `AsRef<()>` are the same trait, thus we assume that those are different, and potentially
-            // over-estimate how many vtable entries there are.
+            // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>`
+            // and `AsRef<()>` are the same trait, thus we assume that those are different, and
+            // potentially over-estimate how many vtable entries there are.
             //
             // Similarly this is wrong for traits that have methods with possibly-impossible bounds.
             // For example:
@@ -918,10 +900,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                         let own_existential_entries =
                             tcx.own_existential_vtable_entries(trait_ref.def_id());
 
-                        // The original code here ignores the method if its predicates are impossible.
-                        // We can't really do that as, for example, all not trivial bounds on generic
-                        // parameters are impossible (since we don't know the parameters...),
-                        // see the comment above.
+                        // The original code here ignores the method if its predicates are
+                        // impossible. We can't really do that as, for example, all not trivial
+                        // bounds on generic parameters are impossible (since we don't know the
+                        // parameters...), see the comment above.
                         entries_ignoring_upcasting += own_existential_entries.len();
 
                         if emit_vptr {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 57ca709267a..594283168c9 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -2,32 +2,21 @@
 use crate::interface::parse_cfg;
 use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
-use rustc_session::config::rustc_optgroups;
-use rustc_session::config::Cfg;
-use rustc_session::config::DebugInfo;
-use rustc_session::config::Input;
-use rustc_session::config::InstrumentXRay;
-use rustc_session::config::LinkSelfContained;
-use rustc_session::config::Polonius;
-use rustc_session::config::TraitSolver;
-use rustc_session::config::{build_configuration, build_session_options};
 use rustc_session::config::{
-    BranchProtection, Externs, OomStrategy, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
-    ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel,
+    build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
+    DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, Input,
+    InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
+    MirSpanview, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
+    Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
+    TraitSolver, WasiExecModel,
 };
-use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
-use rustc_session::config::{DumpMonoStatsFormat, MirSpanview};
-use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip};
-use rustc_session::config::{InstrumentCoverage, Passes};
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
-use rustc_session::{build_session, getopts, Session};
-use rustc_session::{CompilerIO, EarlyErrorHandler};
+use rustc_session::{build_session, getopts, CompilerIO, EarlyErrorHandler, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
-use rustc_span::FileName;
-use rustc_span::SourceFileHashAlgorithm;
+use rustc_span::{FileName, SourceFileHashAlgorithm};
 use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
 use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
 use std::collections::{BTreeMap, BTreeSet};
@@ -35,10 +24,7 @@ use std::num::NonZeroUsize;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
-fn mk_session(
-    handler: &mut EarlyErrorHandler,
-    matches: getopts::Matches,
-) -> (Session, Cfg<String>) {
+fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, Cfg) {
     let registry = registry::Registry::new(&[]);
     let sessopts = build_session_options(handler, &matches);
     let cfg = parse_cfg(handler, matches.opt_strs("cfg"));
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 4d0be65697a..5fde98c7c06 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -36,11 +36,7 @@ pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
 ///
 /// This is performed by checking whether a set of permitted features
 /// is available on the target machine, by querying the codegen backend.
-pub fn add_configuration(
-    cfg: &mut Cfg<Symbol>,
-    sess: &mut Session,
-    codegen_backend: &dyn CodegenBackend,
-) {
+pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend) {
     let tf = sym::target_feature;
 
     let unstable_target_features = codegen_backend.target_features(sess, true);
@@ -59,8 +55,8 @@ pub fn add_configuration(
 pub fn create_session(
     handler: &EarlyErrorHandler,
     sopts: config::Options,
-    cfg: Cfg<String>,
-    check_cfg: CheckCfg<String>,
+    cfg: Cfg,
+    mut check_cfg: CheckCfg,
     locale_resources: &'static [&'static str],
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     io: CompilerIO,
@@ -123,7 +119,6 @@ pub fn create_session(
     let mut cfg = config::build_configuration(&sess, cfg);
     add_configuration(&mut cfg, &mut sess, &*codegen_backend);
 
-    let mut check_cfg = check_cfg.intern();
     check_cfg.fill_well_known(&sess.target);
 
     // These configs use symbols, rather than strings.
@@ -487,21 +482,6 @@ fn categorize_crate_type(s: Symbol) -> Option<CrateType> {
 }
 
 pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<CrateType> {
-    // Unconditionally collect crate types from attributes to make them used
-    let attr_types: Vec<CrateType> = attrs
-        .iter()
-        .filter_map(|a| {
-            if a.has_name(sym::crate_type) {
-                match a.value_str() {
-                    Some(s) => categorize_crate_type(s),
-                    _ => None,
-                }
-            } else {
-                None
-            }
-        })
-        .collect();
-
     // If we're generating a test executable, then ignore all other output
     // styles at all other locations
     if session.opts.test {
@@ -515,6 +495,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C
     #[allow(rustc::bad_opt_access)]
     let mut base = session.opts.crate_types.clone();
     if base.is_empty() {
+        let attr_types = attrs.iter().filter_map(|a| {
+            if a.has_name(sym::crate_type) && let Some(s) = a.value_str() {
+                categorize_crate_type(s)
+            } else {
+                None
+            }
+        });
         base.extend(attr_types);
         if base.is_empty() {
             base.push(output::default_output_for_target(session));
diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml
index 373a8970de8..84b9e292295 100644
--- a/compiler/rustc_lexer/Cargo.toml
+++ b/compiler/rustc_lexer/Cargo.toml
@@ -3,7 +3,6 @@ name = "rustc_lexer"
 version = "0.0.0"
 license = "MIT OR Apache-2.0"
 edition = "2021"
-
 repository = "https://github.com/rust-lang/rust/"
 description = """
 Rust lexer used by rustc. No stability guarantees are provided.
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index 539eea3d816..fa1133e7780 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -4,23 +4,25 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-tracing = "0.1"
-unicode-security = "0.1.0"
-rustc_middle = { path = "../rustc_middle" }
+# tidy-alphabetical-start
+rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_target = { path = "../rustc_target" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_span = { path = "../rustc_span" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
+rustc_infer = { path = "../rustc_infer" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_parse_format = { path = "../rustc_parse_format" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_parse_format = { path = "../rustc_parse_format" }
-rustc_infer = { path = "../rustc_infer" }
 rustc_type_ir = { path = "../rustc_type_ir" }
-rustc_macros = { path = "../rustc_macros" }
+tracing = "0.1"
+unicode-security = "0.1.0"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 6b31fb079e0..355855b8e2b 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1154,7 +1154,7 @@ impl EarlyLintPass for UnusedParens {
 
     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
         if let StmtKind::Local(ref local) = s.kind {
-            self.check_unused_parens_pat(cx, &local.pat, true, false, (false, false));
+            self.check_unused_parens_pat(cx, &local.pat, true, false, (true, false));
         }
 
         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml
index 2bf34d82f39..eb2a184ef84 100644
--- a/compiler/rustc_lint_defs/Cargo.toml
+++ b/compiler/rustc_lint_defs/Cargo.toml
@@ -4,12 +4,14 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-serde = { version = "1.0.125", features = ["derive"] }
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" }
-rustc_span = { path = "../rustc_span" }
-rustc_serialize = { path = "../rustc_serialize" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_serialize = { path = "../rustc_serialize" }
+rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-rustc_hir = { path = "../rustc_hir" }
+serde = { version = "1.0.125", features = ["derive"] }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
index 3880f25a9ba..58e219e5a46 100644
--- a/compiler/rustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -4,7 +4,11 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 libc = "0.2.73"
+# tidy-alphabetical-end
 
 [build-dependencies]
+# tidy-alphabetical-start
 cc = "1.0.69"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml
index aa6e46cd8de..6009a43e985 100644
--- a/compiler/rustc_log/Cargo.toml
+++ b/compiler/rustc_log/Cargo.toml
@@ -4,13 +4,19 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 tracing = "0.1.28"
+tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 tracing-tree = "0.2.0"
-tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635
+# tidy-alphabetical-end
 
 [dev-dependencies]
+# tidy-alphabetical-start
 rustc_span = { path = "../rustc_span" }
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 max_level_info = ['tracing/max_level_info']
+# tidy-alphabetical-end
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml
index 6e7e19a2402..d8d2bef4964 100644
--- a/compiler/rustc_macros/Cargo.toml
+++ b/compiler/rustc_macros/Cargo.toml
@@ -7,7 +7,9 @@ edition = "2021"
 proc-macro = true
 
 [dependencies]
-synstructure = "0.13.0"
-syn = { version = "2.0.9", features = ["full"] }
+# tidy-alphabetical-start
 proc-macro2 = "1"
 quote = "1"
+syn = { version = "2.0.9", features = ["full"] }
+synstructure = "0.13.0"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 840111c31b4..a4012592c09 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -3,30 +3,30 @@ name = "rustc_metadata"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
 libloading = "0.7.1"
 odht = { version = "0.3.1", features = ["nightly"] }
-snap = "1"
-tracing = "0.1"
-tempfile = "3.2"
-rustc_middle = { path = "../rustc_middle" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
-rustc_target = { path = "../rustc_target" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_expand = { path = "../rustc_expand" }
-rustc_span = { path = "../rustc_span" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
 rustc_type_ir = { path = "../rustc_type_ir" }
+snap = "1"
+tempfile = "3.2"
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index bb8e774cea3..d356984c1e9 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -3,24 +3,24 @@ name = "rustc_middle"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
 derive_more = "0.99.17"
 either = "1.5.0"
-gsgdt = "0.1.2"
 field-offset = "0.3.5"
+gsgdt = "0.1.2"
 measureme = "10.0.0"
 polonius-engine = "0.13.0"
+rustc-rayon = { version = "0.5.0", optional = true }
+rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_error_messages = { path = "../rustc_error_messages" } # Used for intra-doc links
 rustc_errors = { path = "../rustc_errors" }
-# Used for intra-doc links
-rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_graphviz = { path = "../rustc_graphviz" }
@@ -28,8 +28,6 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_query_system = { path = "../rustc_query_system" }
-rustc-rayon-core = { version = "0.5.0", optional = true }
-rustc-rayon = { version = "0.5.0", optional = true }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
@@ -38,6 +36,9 @@ rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 rustc_use_parallel_compiler = ["rustc-rayon", "rustc-rayon-core"]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 3cb2e349ce0..c3300753fd1 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -3,6 +3,7 @@ use std::fmt::{self, Debug, Display, Formatter};
 use rustc_hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir};
+use rustc_session::RemapFileNameExt;
 use rustc_span::Span;
 use rustc_target::abi::{HasDataLayout, Size};
 
@@ -579,3 +580,20 @@ impl<'tcx> Display for Const<'tcx> {
         }
     }
 }
+
+///////////////////////////////////////////////////////////////////////////
+/// Const-related utilities
+
+impl<'tcx> TyCtxt<'tcx> {
+    pub fn span_as_caller_location(self, span: Span) -> ConstValue<'tcx> {
+        let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
+        let caller = self.sess.source_map().lookup_char_pos(topmost.lo());
+        self.const_caller_location((
+            rustc_span::symbol::Symbol::intern(
+                &caller.file.name.for_codegen(&self.sess).to_string_lossy(),
+            ),
+            caller.line as u32,
+            caller.col_display as u32 + 1,
+        ))
+    }
+}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index a85af7c3fb5..7054cede2d8 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -578,6 +578,40 @@ impl<'tcx> Body<'tcx> {
     pub fn is_custom_mir(&self) -> bool {
         self.injection_phase.is_some()
     }
+
+    /// For a `Location` in this scope, determine what the "caller location" at that point is. This
+    /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions
+    /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions,
+    /// or the function's scope.
+    pub fn caller_location_span<T>(
+        &self,
+        mut source_info: SourceInfo,
+        caller_location: Option<T>,
+        tcx: TyCtxt<'tcx>,
+        from_span: impl FnOnce(Span) -> T,
+    ) -> T {
+        loop {
+            let scope_data = &self.source_scopes[source_info.scope];
+
+            if let Some((callee, callsite_span)) = scope_data.inlined {
+                // Stop inside the most nested non-`#[track_caller]` function,
+                // before ever reaching its caller (which is irrelevant).
+                if !callee.def.requires_caller_location(tcx) {
+                    return from_span(source_info.span);
+                }
+                source_info.span = callsite_span;
+            }
+
+            // Skip past all of the parents with `inlined: None`.
+            match scope_data.inlined_parent_scope {
+                Some(parent) => source_info.scope = parent,
+                None => break,
+            }
+        }
+
+        // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
+        caller_location.unwrap_or_else(|| from_span(source_info.span))
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 12057f5e1cb..5f4ff22bc49 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -785,7 +785,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             CoroutineDrop => write!(fmt, "coroutine_drop"),
             UnwindResume => write!(fmt, "resume"),
             UnwindTerminate(reason) => {
-                write!(fmt, "abort({})", reason.as_short_str())
+                write!(fmt, "terminate({})", reason.as_short_str())
             }
             Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
             Unreachable => write!(fmt, "unreachable"),
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index c7e2c625ce5..6dceacd75a5 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -3,25 +3,25 @@ name = "rustc_mir_build"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
-rustc_arena = { path = "../rustc_arena" }
-tracing = "0.1"
+# tidy-alphabetical-start
 either = "1"
-rustc_middle = { path = "../rustc_middle" }
 rustc_apfloat = "0.2.0"
+rustc_arena = { path = "../rustc_arena" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_index = { path = "../rustc_index" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_ast = { path = "../rustc_ast" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 4a296bb3367..61664eb2a6f 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -3,13 +3,10 @@ name = "rustc_mir_dataflow"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 polonius-engine = "0.13.0"
 regex = "1"
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
@@ -20,5 +17,8 @@ rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
-rustc_target = { path = "../rustc_target" }
 rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 9ec0bb4ab94..0448e9d276d 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -3,31 +3,33 @@ name = "rustc_mir_transform"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
-itertools = "0.10.1"
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+# tidy-alphabetical-start
 either = "1"
-rustc_ast = { path = "../rustc_ast" }
+itertools = "0.10.1"
 rustc_arena = { path = "../rustc_arena" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
+rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_mir_build = { path = "../rustc_mir_build" }
 rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_span = { path = "../rustc_span" }
-rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_macros = { path = "../rustc_macros" }
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
 
 [dev-dependencies]
+# tidy-alphabetical-start
 coverage_test_macros = { path = "src/coverage/test_macros" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index fe097424e8a..c7f1b9fa784 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -3,18 +3,18 @@ name = "rustc_monomorphize"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
-serde = "1"
-serde_json = "1"
-tracing = "0.1"
+# tidy-alphabetical-start
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
+serde = "1"
+serde_json = "1"
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index 1bd9f66290d..02f9f35f0f5 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -3,9 +3,8 @@ name = "rustc_parse"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -21,3 +20,4 @@ thin-vec = "0.2.12"
 tracing = "0.1"
 unicode-normalization = "0.1.11"
 unicode-width = "0.1.4"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml
index 14330353239..707c4e31847 100644
--- a/compiler/rustc_parse_format/Cargo.toml
+++ b/compiler/rustc_parse_format/Cargo.toml
@@ -4,5 +4,7 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-rustc_lexer = { path = "../rustc_lexer" }
+# tidy-alphabetical-start
 rustc_index = { path = "../rustc_index", default-features = false }
+rustc_lexer = { path = "../rustc_lexer" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index 0413b5b4fb9..40c3811e054 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -4,23 +4,25 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-tracing = "0.1"
+# tidy-alphabetical-start
 itertools = "0.10.1"
-rustc_middle = { path = "../rustc_middle" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
-rustc_hir = { path = "../rustc_hir" }
+rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
-rustc_session = { path = "../rustc_session" }
-rustc_target = { path = "../rustc_target" }
+rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
-rustc_ast = { path = "../rustc_ast" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
+rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_lexer = { path = "../rustc_lexer" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_feature = { path = "../rustc_feature" }
+rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 026186cbe6c..a0a98dd8536 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -778,6 +778,8 @@ passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
 passes_unused_var_remove_field = unused variable: `{$name}`
 passes_unused_var_remove_field_suggestion = try removing the field
 
+passes_unused_variable_args_in_macro = `{$name}` is captured in macro and introduced a unused variable
+
 passes_unused_variable_try_ignore = unused variable: `{$name}`
     .suggestion = try ignoring the field
 
@@ -785,6 +787,7 @@ passes_unused_variable_try_prefix = unused variable: `{$name}`
     .label = unused variable
     .suggestion = if this is intentional, prefix it with an underscore
 
+
 passes_used_compiler_linker =
     `used(compiler)` and `used(linker)` can't be used together
 
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index eca0fb7748b..bc31b5db021 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1768,15 +1768,24 @@ pub struct UnusedVariableTryPrefix {
     #[subdiagnostic]
     pub string_interp: Vec<UnusedVariableStringInterp>,
     #[subdiagnostic]
-    pub sugg: UnusedVariableTryPrefixSugg,
+    pub sugg: UnusedVariableSugg,
+    pub name: String,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
-pub struct UnusedVariableTryPrefixSugg {
-    #[suggestion_part(code = "_{name}")]
-    pub spans: Vec<Span>,
-    pub name: String,
+pub enum UnusedVariableSugg {
+    #[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
+    TryPrefixSugg {
+        #[suggestion_part(code = "_{name}")]
+        spans: Vec<Span>,
+        name: String,
+    },
+    #[help(passes_unused_variable_args_in_macro)]
+    NoSugg {
+        #[primary_span]
+        span: Span,
+        name: String,
+    },
 }
 
 pub struct UnusedVariableStringInterp {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index d068fe62473..b73fb984c0e 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1580,7 +1580,6 @@ impl<'tcx> Liveness<'_, 'tcx> {
         opt_body: Option<&hir::Body<'_>>,
     ) {
         let first_hir_id = hir_ids_and_spans[0].0;
-
         if let Some(name) = self.should_warn(var).filter(|name| name != "self") {
             // annoying: for parameters in funcs like `fn(x: i32)
             // {ret}`, there is only one node, so asking about
@@ -1652,11 +1651,29 @@ impl<'tcx> Liveness<'_, 'tcx> {
                         },
                     );
                 } else {
+                    // #117284, when `pat_span` and `ident_span` have different contexts
+                    // we can't provide a good suggestion, instead we pointed out the spans from macro
+                    let from_macro = non_shorthands
+                        .iter()
+                        .find(|(_, pat_span, ident_span)| {
+                            pat_span.ctxt() != ident_span.ctxt() && pat_span.from_expansion()
+                        })
+                        .map(|(_, pat_span, _)| *pat_span);
                     let non_shorthands = non_shorthands
                         .into_iter()
                         .map(|(_, _, ident_span)| ident_span)
                         .collect::<Vec<_>>();
+
                     let suggestions = self.string_interp_suggestions(&name, opt_body);
+                    let sugg = if let Some(span) = from_macro {
+                        errors::UnusedVariableSugg::NoSugg { span, name: name.clone() }
+                    } else {
+                        errors::UnusedVariableSugg::TryPrefixSugg {
+                            spans: non_shorthands,
+                            name: name.clone(),
+                        }
+                    };
+
                     self.ir.tcx.emit_spanned_lint(
                         lint::builtin::UNUSED_VARIABLES,
                         first_hir_id,
@@ -1666,10 +1683,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
                             .collect::<Vec<_>>(),
                         errors::UnusedVariableTryPrefix {
                             label: if !suggestions.is_empty() { Some(pat.span) } else { None },
-                            sugg: errors::UnusedVariableTryPrefixSugg {
-                                spans: non_shorthands,
-                                name,
-                            },
+                            name,
+                            sugg,
                             string_interp: suggestions,
                         },
                     );
diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml
index c930b3365fd..a0762e815e3 100644
--- a/compiler/rustc_plugin_impl/Cargo.toml
+++ b/compiler/rustc_plugin_impl/Cargo.toml
@@ -4,15 +4,15 @@ version = "0.0.0"
 build = false
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 libloading = "0.7.1"
+rustc_ast = { path = "../rustc_ast" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_lint = { path = "../rustc_lint" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_metadata = { path = "../rustc_metadata" }
-rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_ast = { path = "../rustc_ast" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index 08c4067705c..90803c20d43 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -4,15 +4,17 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index a350e8b2e3a..88eb4603069 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -3,27 +3,25 @@ name = "rustc_query_impl"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
-
 [dependencies]
+# tidy-alphabetical-start
 field-offset = "0.3.5"
 measureme = "10.0.0"
+rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_query_system = { path = "../rustc_query_system" }
-rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 thin-vec = "0.2.12"
 tracing = "0.1"
-
-# Not used directly, but included to enable the unstable_offset_of feature
-memoffset = { version = "0.9.0", features = ["unstable_offset_of"] }
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 rustc_use_parallel_compiler = ["rustc-rayon-core", "rustc_query_system/rustc_use_parallel_compiler"]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 584355df802..6ea87a4a633 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -3,10 +3,10 @@ name = "rustc_query_system"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 parking_lot = "0.12"
+rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
@@ -15,7 +15,6 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
-rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
@@ -24,6 +23,9 @@ rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
 
 [features]
+# tidy-alphabetical-start
 rustc_use_parallel_compiler = ["rustc-rayon-core"]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 46da0aa2853..ff9d6d8739f 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -3,9 +3,8 @@ name = "rustc_resolve"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
 pulldown-cmark = { version = "0.9.3", default-features = false }
 rustc_arena = { path = "../rustc_arena" }
@@ -28,3 +27,4 @@ rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml
index 46b923e8c7b..8bf98c16361 100644
--- a/compiler/rustc_serialize/Cargo.toml
+++ b/compiler/rustc_serialize/Cargo.toml
@@ -4,10 +4,14 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 indexmap = "2.0.0"
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
+# tidy-alphabetical-end
 
 [dev-dependencies]
+# tidy-alphabetical-start
 rustc_macros = { path = "../rustc_macros" }
 tempfile = "3.2"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index e26d25d9a41..1f51dd6c975 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -4,26 +4,30 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
 getopts = "0.2"
-rustc_macros = { path = "../rustc_macros" }
-tracing = "0.1"
+rustc_ast = { path = "../rustc_ast" }
+rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_target = { path = "../rustc_target" }
-rustc_serialize = { path = "../rustc_serialize" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_span = { path = "../rustc_span" }
 rustc_fs_util = { path = "../rustc_fs_util" }
-rustc_ast = { path = "../rustc_ast" }
+rustc_hir = { path = "../rustc_hir" }
 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" }
 smallvec = "1.8.1"
 termize = "0.1.1"
+tracing = "0.1"
+# tidy-alphabetical-end
 
 [target.'cfg(unix)'.dependencies]
+# tidy-alphabetical-start
 libc = "0.2"
+# tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
 version = "0.48.0"
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 854e2b77993..a8ebab4ae33 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1247,8 +1247,8 @@ pub const fn default_lib_output() -> CrateType {
     CrateType::Rlib
 }
 
-fn default_configuration(sess: &Session) -> Cfg<Symbol> {
-    // NOTE: This should be kept in sync with `CheckCfg::<Symbol>::fill_well_known` below.
+fn default_configuration(sess: &Session) -> Cfg {
+    // NOTE: This should be kept in sync with `CheckCfg::fill_well_known` below.
     let end = &sess.target.endian;
     let arch = &sess.target.arch;
     let wordsz = sess.target.pointer_width.to_string();
@@ -1358,56 +1358,21 @@ fn default_configuration(sess: &Session) -> Cfg<Symbol> {
 }
 
 /// The parsed `--cfg` options that define the compilation environment of the
-/// crate, used to drive conditional compilation. `T` is always `String` or
-/// `Symbol`. Strings are used temporarily very early on. Once the the main
-/// symbol interner is running, they are converted to symbols.
+/// crate, used to drive conditional compilation.
 ///
 /// An `FxIndexSet` is used to ensure deterministic ordering of error messages
 /// relating to `--cfg`.
-pub type Cfg<T> = FxIndexSet<(T, Option<T>)>;
+pub type Cfg = FxIndexSet<(Symbol, Option<Symbol>)>;
 
-/// The parsed `--check-cfg` options. The `<T>` structure is similar to `Cfg`.
-pub struct CheckCfg<T> {
+/// The parsed `--check-cfg` options.
+#[derive(Default)]
+pub struct CheckCfg {
     /// Is well known names activated
     pub exhaustive_names: bool,
     /// Is well known values activated
     pub exhaustive_values: bool,
     /// All the expected values for a config name
-    pub expecteds: FxHashMap<T, ExpectedValues<T>>,
-}
-
-impl<T> Default for CheckCfg<T> {
-    fn default() -> Self {
-        CheckCfg {
-            exhaustive_names: false,
-            exhaustive_values: false,
-            expecteds: FxHashMap::default(),
-        }
-    }
-}
-
-impl CheckCfg<String> {
-    pub fn intern(self) -> CheckCfg<Symbol> {
-        CheckCfg {
-            exhaustive_names: self.exhaustive_names,
-            exhaustive_values: self.exhaustive_values,
-            expecteds: self
-                .expecteds
-                .into_iter()
-                .map(|(name, values)| {
-                    (
-                        Symbol::intern(&name),
-                        match values {
-                            ExpectedValues::Some(values) => ExpectedValues::Some(
-                                values.into_iter().map(|b| b.map(|b| Symbol::intern(&b))).collect(),
-                            ),
-                            ExpectedValues::Any => ExpectedValues::Any,
-                        },
-                    )
-                })
-                .collect(),
-        }
-    }
+    pub expecteds: FxHashMap<Symbol, ExpectedValues<Symbol>>,
 }
 
 pub enum ExpectedValues<T> {
@@ -1442,7 +1407,7 @@ impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues<T> {
     }
 }
 
-impl CheckCfg<Symbol> {
+impl CheckCfg {
     pub fn fill_well_known(&mut self, current_target: &Target) {
         if !self.exhaustive_values && !self.exhaustive_names {
             return;
@@ -1582,13 +1547,7 @@ impl CheckCfg<Symbol> {
     }
 }
 
-pub fn build_configuration(sess: &Session, user_cfg: Cfg<String>) -> Cfg<Symbol> {
-    // We can now intern these strings.
-    let mut user_cfg: Cfg<Symbol> = user_cfg
-        .into_iter()
-        .map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b))))
-        .collect();
-
+pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
     // Combine the configuration requested by the session (command line) with
     // some default and generated configuration items.
     let default_cfg = default_configuration(sess);
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 5b98ee5d992..4d20d6d4187 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -188,8 +188,8 @@ pub fn add_feature_diagnostics_for_issue(
 pub struct ParseSess {
     pub span_diagnostic: Handler,
     pub unstable_features: UnstableFeatures,
-    pub config: Cfg<Symbol>,
-    pub check_config: CheckCfg<Symbol>,
+    pub config: Cfg,
+    pub check_config: CheckCfg,
     pub edition: Edition,
     /// Places where raw identifiers were used. This is used to avoid complaining about idents
     /// clashing with keywords in new editions.
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index 47dd7372f3d..836ea046ffe 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_middle = { path = "../rustc_middle" }
@@ -12,5 +13,4 @@ rustc_target = { path = "../rustc_target" }
 scoped-tls = "1.0"
 stable_mir = {path = "../stable_mir" }
 tracing = "0.1"
-
-[features]
+# tidy-alphabetical-end
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 31c2a56faa5..99de91a068a 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -3,18 +3,18 @@ name = "rustc_span"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
-rustc_serialize = { path = "../rustc_serialize" }
-rustc_macros = { path = "../rustc_macros" }
+# tidy-alphabetical-start
+indexmap = { version = "2.0.0" }
+md5 = { package = "md-5", version = "0.10.0" }
+rustc_arena = { path = "../rustc_arena" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_index = { path = "../rustc_index" }
-rustc_arena = { path = "../rustc_arena" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_serialize = { path = "../rustc_serialize" }
 scoped-tls = "1.0"
-unicode-width = "0.1.4"
-tracing = "0.1"
 sha1 = "0.10.0"
 sha2 = "0.10.1"
-md5 = { package = "md-5", version = "0.10.0" }
-indexmap = { version = "2.0.0" }
+tracing = "0.1"
+unicode-width = "0.1.4"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index d53bc5b6a8e..ff3f1ad646f 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -3,19 +3,18 @@ name = "rustc_symbol_mangling"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
-tracing = "0.1"
 punycode = "0.4.0"
 rustc-demangle = "0.1.21"
-twox-hash = "1.6.3"
-
-rustc_span = { path = "../rustc_span" }
-rustc_middle = { path = "../rustc_middle" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_target = { path = "../rustc_target" }
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_session = { path = "../rustc_session" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
+tracing = "0.1"
+twox-hash = "1.6.3"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index 779d03cd094..94dfeb12dc9 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -4,19 +4,23 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
-tracing = "0.1"
-serde_json = "1.0.59"
-rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-rustc_index = { path = "../rustc_index" }
+serde_json = "1.0.59"
+tracing = "0.1"
+# tidy-alphabetical-end
 
 [dependencies.object]
-version = "0.32.0"
+# tidy-alphabetical-start
 default-features = false
 features = ["elf", "macho"]
+version = "0.32.0"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs
new file mode 100644
index 00000000000..651358d6422
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs
@@ -0,0 +1,21 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::netbsd_base::opts();
+    base.max_atomic_width = Some(32);
+    base.cpu = "mips32".into();
+
+    Target {
+        llvm_target: "mipsel-unknown-netbsd".into(),
+        pointer_width: 32,
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
+        options: TargetOptions {
+            features: "+soft-float".into(),
+            mcount: "__mcount".into(),
+            endian: Endian::Little,
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index ccf29761552..48ca5fcf3ad 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1566,6 +1566,7 @@ supported_targets! {
     ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
     ("i586-unknown-netbsd", i586_unknown_netbsd),
     ("i686-unknown-netbsd", i686_unknown_netbsd),
+    ("mipsel-unknown-netbsd", mipsel_unknown_netbsd),
     ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
     ("riscv64gc-unknown-netbsd", riscv64gc_unknown_netbsd),
     ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 83605627d6f..667ee3d4e1c 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -3,21 +3,19 @@ name = "rustc_trait_selection"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
-rustc_parse_format = { path = "../rustc_parse_format" }
-tracing = "0.1"
-rustc_attr = { path = "../rustc_attr" }
-rustc_middle = { path = "../rustc_middle" }
+# tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
+rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_parse_format = { path = "../rustc_parse_format" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
@@ -25,3 +23,5 @@ rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml
index 0cdc978a3d0..9c788116d98 100644
--- a/compiler/rustc_traits/Cargo.toml
+++ b/compiler/rustc_traits/Cargo.toml
@@ -4,10 +4,12 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-tracing = "0.1"
-rustc_middle = { path = "../rustc_middle" }
+# tidy-alphabetical-start
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_span = { path = "../rustc_span" }
 rustc_infer = { path = "../rustc_infer" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_span = { path = "../rustc_span" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index c2b2730c328..07420985a85 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -3,10 +3,8 @@ name = "rustc_transmute"
 version = "0.0.0"
 edition = "2021"
 
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
 [dependencies]
-tracing = "0.1"
+# tidy-alphabetical-start
 rustc_data_structures = { path = "../rustc_data_structures"}
 rustc_hir = { path = "../rustc_hir", optional = true}
 rustc_infer = { path = "../rustc_infer", optional = true}
@@ -14,16 +12,20 @@ rustc_macros = { path = "../rustc_macros", optional = true}
 rustc_middle = { path = "../rustc_middle", optional = true}
 rustc_span = { path = "../rustc_span", optional = true}
 rustc_target = { path = "../rustc_target", optional = true}
+tracing = "0.1"
+# tidy-alphabetical-end
 
 [features]
 rustc = [
-    "rustc_middle",
     "rustc_hir",
     "rustc_infer",
     "rustc_macros",
+    "rustc_middle",
     "rustc_span",
     "rustc_target",
 ]
 
 [dev-dependencies]
-itertools = "0.10.1"
\ No newline at end of file
+# tidy-alphabetical-start
+itertools = "0.10.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 50dac3a37a4..7e00f1e0c42 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -4,18 +4,20 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-tracing = "0.1"
+# tidy-alphabetical-start
 itertools = "0.10.1"
-rustc_middle = { path = "../rustc_middle" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_macros = { path = "../rustc_macros" }
-rustc_span = { path = "../rustc_span" }
+rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_type_ir = { path = "../rustc_type_ir" }
-rustc_index = { path = "../rustc_index" }
+tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index c4008e9b612..484757e2fc1 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -3,12 +3,12 @@ name = "rustc_type_ir"
 version = "0.0.0"
 edition = "2021"
 
-[lib]
-
 [dependencies]
+# tidy-alphabetical-start
 bitflags = "1.2.1"
-rustc_index = { path = "../rustc_index" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_serialize = { path = "../rustc_serialize" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+# tidy-alphabetical-end
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 75d263d7794..9d03350c723 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -72,16 +72,27 @@ fn install_sh(
 
     let prefix = default_path(&builder.config.prefix, "/usr/local");
     let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
+    let destdir_env = env::var_os("DESTDIR").map(PathBuf::from);
 
-    // Sanity check for the user write access on prefix and sysconfdir
-    assert!(
-        is_dir_writable_for_user(&prefix),
-        "User doesn't have write access on `install.prefix` path in the `config.toml`.",
-    );
-    assert!(
-        is_dir_writable_for_user(&sysconfdir),
-        "User doesn't have write access on `install.sysconfdir` path in `config.toml`."
-    );
+    // Sanity checks on the write access of user.
+    //
+    // When the `DESTDIR` environment variable is present, there is no point to
+    // check write access for `prefix` and `sysconfdir` individually, as they
+    // are combined with the path from the `DESTDIR` environment variable. In
+    // this case, we only need to check the `DESTDIR` path, disregarding the
+    // `prefix` and `sysconfdir` paths.
+    if let Some(destdir) = &destdir_env {
+        assert!(is_dir_writable_for_user(destdir), "User doesn't have write access on DESTDIR.");
+    } else {
+        assert!(
+            is_dir_writable_for_user(&prefix),
+            "User doesn't have write access on `install.prefix` path in the `config.toml`.",
+        );
+        assert!(
+            is_dir_writable_for_user(&sysconfdir),
+            "User doesn't have write access on `install.sysconfdir` path in `config.toml`."
+        );
+    }
 
     let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
     let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust"));
@@ -95,13 +106,13 @@ fn install_sh(
     let mut cmd = Command::new(SHELL);
     cmd.current_dir(&empty_dir)
         .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
-        .arg(format!("--prefix={}", prepare_dir(prefix)))
-        .arg(format!("--sysconfdir={}", prepare_dir(sysconfdir)))
-        .arg(format!("--datadir={}", prepare_dir(datadir)))
-        .arg(format!("--docdir={}", prepare_dir(docdir)))
-        .arg(format!("--bindir={}", prepare_dir(bindir)))
-        .arg(format!("--libdir={}", prepare_dir(libdir)))
-        .arg(format!("--mandir={}", prepare_dir(mandir)))
+        .arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix)))
+        .arg(format!("--sysconfdir={}", prepare_dir(&destdir_env, sysconfdir)))
+        .arg(format!("--datadir={}", prepare_dir(&destdir_env, datadir)))
+        .arg(format!("--docdir={}", prepare_dir(&destdir_env, docdir)))
+        .arg(format!("--bindir={}", prepare_dir(&destdir_env, bindir)))
+        .arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir)))
+        .arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir)))
         .arg("--disable-ldconfig");
     builder.run(&mut cmd);
     t!(fs::remove_dir_all(&empty_dir));
@@ -111,19 +122,16 @@ fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
     config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))
 }
 
-fn prepare_dir(mut path: PathBuf) -> String {
+fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf) -> String {
     // The DESTDIR environment variable is a standard way to install software in a subdirectory
     // while keeping the original directory structure, even if the prefix or other directories
     // contain absolute paths.
     //
     // More information on the environment variable is available here:
     // https://www.gnu.org/prep/standards/html_node/DESTDIR.html
-    if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
-        // Sanity check for the user write access on DESTDIR
-        assert!(is_dir_writable_for_user(&destdir), "User doesn't have write access on DESTDIR.");
-
+    if let Some(destdir) = destdir_env {
         let without_destdir = path.clone();
-        path = destdir;
+        path = destdir.clone();
         // Custom .join() which ignores disk roots.
         for part in without_destdir.components() {
             if let Component::Normal(s) = part {
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 24351118a5a..5b454307721 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -396,6 +396,12 @@ impl Step for Llvm {
             ldflags.shared.push(" -latomic");
         }
 
+        if target.starts_with("mips") && target.contains("netbsd") {
+            // LLVM wants 64-bit atomics, while mipsel is 32-bit only, so needs -latomic
+            ldflags.exe.push(" -latomic");
+            ldflags.shared.push(" -latomic");
+        }
+
         if target.contains("msvc") {
             cfg.define("LLVM_USE_CRT_DEBUG", "MT");
             cfg.define("LLVM_USE_CRT_RELEASE", "MT");
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 68ec0f348dc..6a979869a59 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -287,6 +287,7 @@ target | std | host | notes
 `mips64el-unknown-linux-muslabi64` | ✓ |  | MIPS64 (little endian) Linux, N64 ABI, musl libc
 `mipsel-unknown-linux-gnu` | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23)
 `mipsel-unknown-linux-musl` | ✓ |  | MIPS (little endian) Linux with musl libc
+[`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support
 `mipsel-sony-psp` | * |  | MIPS (LE) Sony PlayStation Portable (PSP)
 [`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * |  | MIPS (LE) Sony PlayStation 1 (PSX)
 `mipsel-unknown-linux-uclibc` | ✓ |  | MIPS (LE) Linux with uClibc
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4d4c102e69e..e6e2d60f2e5 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -475,8 +475,9 @@ fn projection_to_path_segment<'tcx>(
     ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> PathSegment {
-    let item = cx.tcx.associated_item(ty.skip_binder().def_id);
-    let generics = cx.tcx.generics_of(ty.skip_binder().def_id);
+    let def_id = ty.skip_binder().def_id;
+    let item = cx.tcx.associated_item(def_id);
+    let generics = cx.tcx.generics_of(def_id);
     PathSegment {
         name: item.name,
         args: GenericArgs::AngleBracketed {
@@ -484,7 +485,7 @@ fn projection_to_path_segment<'tcx>(
                 cx,
                 ty.map_bound(|ty| &ty.args[generics.parent_count..]),
                 false,
-                None,
+                def_id,
             )
             .into(),
             bindings: Default::default(),
@@ -2200,18 +2201,19 @@ pub(crate) fn clean_middle_ty<'tcx>(
         }
 
         ty::Alias(ty::Inherent, alias_ty) => {
+            let def_id = alias_ty.def_id;
             let alias_ty = bound_ty.rebind(alias_ty);
             let self_type = clean_middle_ty(alias_ty.map_bound(|ty| ty.self_ty()), cx, None, None);
 
             Type::QPath(Box::new(QPathData {
                 assoc: PathSegment {
-                    name: cx.tcx.associated_item(alias_ty.skip_binder().def_id).name,
+                    name: cx.tcx.associated_item(def_id).name,
                     args: GenericArgs::AngleBracketed {
                         args: ty_args_to_args(
                             cx,
                             alias_ty.map_bound(|ty| ty.args.as_slice()),
                             true,
-                            None,
+                            def_id,
                         )
                         .into(),
                         bindings: Default::default(),
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index c5302570489..dea7bfaf7e2 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -17,6 +17,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_metadata::rendered_const;
 use rustc_middle::mir;
 use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
+use rustc_middle::ty::{TypeVisitable, TypeVisitableExt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::fmt::Write as _;
 use std::mem;
@@ -76,44 +77,123 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
 
 pub(crate) fn ty_args_to_args<'tcx>(
     cx: &mut DocContext<'tcx>,
-    args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
+    ty_args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
     has_self: bool,
-    container: Option<DefId>,
+    owner: DefId,
 ) -> Vec<GenericArg> {
-    let mut skip_first = has_self;
-    let mut ret_val =
-        Vec::with_capacity(args.skip_binder().len().saturating_sub(if skip_first { 1 } else { 0 }));
-
-    ret_val.extend(args.iter().enumerate().filter_map(|(index, kind)| {
-        match kind.skip_binder().unpack() {
-            GenericArgKind::Lifetime(lt) => {
-                Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
-            }
-            GenericArgKind::Type(_) if skip_first => {
-                skip_first = false;
-                None
+    if ty_args.skip_binder().is_empty() {
+        // Fast path which avoids executing the query `generics_of`.
+        return Vec::new();
+    }
+
+    let params = &cx.tcx.generics_of(owner).params;
+    let mut elision_has_failed_once_before = false;
+
+    let offset = if has_self { 1 } else { 0 };
+    let mut args = Vec::with_capacity(ty_args.skip_binder().len().saturating_sub(offset));
+
+    let ty_arg_to_arg = |(index, arg): (usize, &ty::GenericArg<'tcx>)| match arg.unpack() {
+        GenericArgKind::Lifetime(lt) => {
+            Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
+        }
+        GenericArgKind::Type(_) if has_self && index == 0 => None,
+        GenericArgKind::Type(ty) => {
+            if !elision_has_failed_once_before
+                && let Some(default) = params[index].default_value(cx.tcx)
+            {
+                let default =
+                    ty_args.map_bound(|args| default.instantiate(cx.tcx, args).expect_ty());
+
+                if can_elide_generic_arg(ty_args.rebind(ty), default) {
+                    return None;
+                }
+
+                elision_has_failed_once_before = true;
             }
-            GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(
-                kind.rebind(ty),
+
+            Some(GenericArg::Type(clean_middle_ty(
+                ty_args.rebind(ty),
                 cx,
                 None,
-                container.map(|container| crate::clean::ContainerTy::Regular {
-                    ty: container,
-                    args,
+                Some(crate::clean::ContainerTy::Regular {
+                    ty: owner,
+                    args: ty_args,
                     has_self,
                     arg: index,
                 }),
-            ))),
+            )))
+        }
+        GenericArgKind::Const(ct) => {
             // FIXME(effects): this relies on the host effect being called `host`, which users could also name
             // their const generics.
             // FIXME(effects): this causes `host = true` and `host = false` generics to also be emitted.
-            GenericArgKind::Const(ct) if let ty::ConstKind::Param(p) = ct.kind() && p.name == sym::host => None,
-            GenericArgKind::Const(ct) => {
-                Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+            if let ty::ConstKind::Param(p) = ct.kind()
+                && p.name == sym::host
+            {
+                return None;
             }
+
+            if !elision_has_failed_once_before
+                && let Some(default) = params[index].default_value(cx.tcx)
+            {
+                let default =
+                    ty_args.map_bound(|args| default.instantiate(cx.tcx, args).expect_const());
+
+                if can_elide_generic_arg(ty_args.rebind(ct), default) {
+                    return None;
+                }
+
+                elision_has_failed_once_before = true;
+            }
+
+            Some(GenericArg::Const(Box::new(clean_middle_const(ty_args.rebind(ct), cx))))
         }
-    }));
-    ret_val
+    };
+
+    args.extend(ty_args.skip_binder().iter().enumerate().rev().filter_map(ty_arg_to_arg));
+    args.reverse();
+    args
+}
+
+/// Check if the generic argument `actual` coincides with the `default` and can therefore be elided.
+///
+/// This uses a very conservative approach for performance and correctness reasons, meaning for
+/// several classes of terms it claims that they cannot be elided even if they theoretically could.
+/// This is absolutely fine since it mostly concerns edge cases.
+fn can_elide_generic_arg<'tcx, Term>(
+    actual: ty::Binder<'tcx, Term>,
+    default: ty::Binder<'tcx, Term>,
+) -> bool
+where
+    Term: Eq + TypeVisitable<TyCtxt<'tcx>>,
+{
+    // In practice, we shouldn't have any inference variables at this point.
+    // However to be safe, we bail out if we do happen to stumble upon them.
+    if actual.has_infer() || default.has_infer() {
+        return false;
+    }
+
+    // Since we don't properly keep track of bound variables in rustdoc (yet), we don't attempt to
+    // make any sense out of escaping bound variables. We simply don't have enough context and it
+    // would be incorrect to try to do so anyway.
+    if actual.has_escaping_bound_vars() || default.has_escaping_bound_vars() {
+        return false;
+    }
+
+    // Theoretically we could now check if either term contains (non-escaping) late-bound regions or
+    // projections, relate the two using an `InferCtxt` and check if the resulting obligations hold.
+    // Having projections means that the terms can potentially be further normalized thereby possibly
+    // revealing that they are equal after all. Regarding late-bound regions, they could to be
+    // liberated allowing us to consider more types to be equal by ignoring the names of binders
+    // (e.g., `for<'a> TYPE<'a>` and `for<'b> TYPE<'b>`).
+    //
+    // However, we are mostly interested in “reeliding” generic args, i.e., eliding generic args that
+    // were originally elided by the user and later filled in by the compiler contrary to eliding
+    // arbitrary generic arguments if they happen to semantically coincide with the default (of course,
+    // we cannot possibly distinguish these two cases). Therefore and for performance reasons, it
+    // suffices to only perform a syntactic / structural check by comparing the memory addresses of
+    // the interned arguments.
+    actual.skip_binder() == default.skip_binder()
 }
 
 fn external_generic_args<'tcx>(
@@ -123,7 +203,7 @@ fn external_generic_args<'tcx>(
     bindings: ThinVec<TypeBinding>,
     ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
 ) -> GenericArgs {
-    let args = ty_args_to_args(cx, ty_args.map_bound(|args| &args[..]), has_self, Some(did));
+    let args = ty_args_to_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did);
 
     if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
         let ty = ty_args
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index bcc61df7c4d..17b117de5d4 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -14,8 +14,8 @@ use rustc_lint::{late_lint_mod, MissingDoc};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
+use rustc_session::lint;
 use rustc_session::Session;
-use rustc_session::{lint, EarlyErrorHandler};
 use rustc_span::symbol::sym;
 use rustc_span::{source_map, Span};
 
@@ -175,7 +175,6 @@ pub(crate) fn new_handler(
 
 /// Parse, resolve, and typecheck the given crate.
 pub(crate) fn create_config(
-    handler: &EarlyErrorHandler,
     RustdocOptions {
         input,
         crate_name,
@@ -255,8 +254,8 @@ pub(crate) fn create_config(
 
     interface::Config {
         opts: sessopts,
-        crate_cfg: interface::parse_cfg(handler, cfgs),
-        crate_check_cfg: interface::parse_check_cfg(handler, check_cfgs),
+        crate_cfg: cfgs,
+        crate_check_cfg: check_cfgs,
         input,
         output_file: None,
         output_dir: None,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index c61c98e4de9..2412865801d 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -13,7 +13,7 @@ use rustc_parse::parser::attr::InnerAttrPolicy;
 use rustc_resolve::rustdoc::span_of_fragments;
 use rustc_session::config::{self, CrateType, ErrorOutputType};
 use rustc_session::parse::ParseSess;
-use rustc_session::{lint, EarlyErrorHandler, Session};
+use rustc_session::{lint, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
@@ -85,18 +85,13 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
         ..config::Options::default()
     };
 
-    let early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default());
-
     let mut cfgs = options.cfgs.clone();
     cfgs.push("doc".to_owned());
     cfgs.push("doctest".to_owned());
     let config = interface::Config {
         opts: sessopts,
-        crate_cfg: interface::parse_cfg(&early_error_handler, cfgs),
-        crate_check_cfg: interface::parse_check_cfg(
-            &early_error_handler,
-            options.check_cfgs.clone(),
-        ),
+        crate_cfg: cfgs,
+        crate_check_cfg: options.check_cfgs.clone(),
         input,
         output_file: None,
         output_dir: None,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 41aee06c8d2..dda06d4c9c1 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -757,8 +757,7 @@ fn main_args(
         (false, true) => {
             let input = options.input.clone();
             let edition = options.edition;
-            let config =
-                core::create_config(handler, options, &render_options, using_internal_features);
+            let config = core::create_config(options, &render_options, using_internal_features);
 
             // `markdown::render` can invoke `doctest::make_test`, which
             // requires session globals and a thread pool, so we use
@@ -791,7 +790,7 @@ fn main_args(
     let scrape_examples_options = options.scrape_examples_options.clone();
     let bin_crate = options.bin_crate;
 
-    let config = core::create_config(handler, options, &render_options, using_internal_features);
+    let config = core::create_config(options, &render_options, using_internal_features);
 
     interface::run_compiler(config, |compiler| {
         let sess = compiler.session();
diff --git a/tests/rustdoc/const-generics/add-impl.rs b/tests/rustdoc/const-generics/add-impl.rs
index 195e47bc8ba..df490d2c636 100644
--- a/tests/rustdoc/const-generics/add-impl.rs
+++ b/tests/rustdoc/const-generics/add-impl.rs
@@ -7,7 +7,7 @@ pub struct Simd<T, const WIDTH: usize> {
     inner: T,
 }
 
-// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
+// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl Add for Simd<u8, 16>'
 impl Add for Simd<u8, 16> {
     type Output = Self;
 
diff --git a/tests/rustdoc/inline_cross/auxiliary/default-generic-args.rs b/tests/rustdoc/inline_cross/auxiliary/default-generic-args.rs
new file mode 100644
index 00000000000..1e31f18927e
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/default-generic-args.rs
@@ -0,0 +1,45 @@
+pub type BoxedStr = Box<str>;
+pub type IntMap = std::collections::HashMap<i64, u64>;
+
+pub struct TyPair<T, U = T>(T, U);
+
+pub type T0 = TyPair<i32>;
+pub type T1 = TyPair<i32, u32>;
+pub type T2<K> = TyPair<i32, K>;
+pub type T3<Q> = TyPair<Q, Q>;
+
+pub struct CtPair<const C: u32, const D: u32 = C>;
+
+pub type C0 = CtPair<43, 43>;
+pub type C1 = CtPair<0, 1>;
+pub type C2 = CtPair<{1 + 2}, 3>;
+
+pub struct Re<'a, U = &'a ()>(&'a (), U);
+
+pub type R0<'q> = Re<'q>;
+pub type R1<'q> = Re<'q, &'q ()>;
+pub type R2<'q> = Re<'q, &'static ()>;
+pub type H0 = fn(for<'a> fn(Re<'a>));
+pub type H1 = for<'b> fn(for<'a> fn(Re<'a, &'b ()>));
+pub type H2 = for<'a> fn(for<'b> fn(Re<'a, &'b ()>));
+
+pub struct Proj<T: Basis, U = <T as Basis>::Assoc>(T, U);
+pub trait Basis { type Assoc; }
+impl Basis for () { type Assoc = bool; }
+
+pub type P0 = Proj<()>;
+pub type P1 = Proj<(), bool>;
+pub type P2 = Proj<(), ()>;
+
+pub struct Alpha<T = for<'any> fn(&'any ())>(T);
+
+pub type A0 = Alpha;
+pub type A1 = Alpha<for<'arbitrary> fn(&'arbitrary ())>;
+
+pub struct Multi<A = u64, B = u64>(A, B);
+
+pub type M0 = Multi<u64, ()>;
+
+pub trait Trait<'a, T = &'a ()> {}
+
+pub type F = dyn for<'a> Trait<'a>;
diff --git a/tests/rustdoc/inline_cross/default-generic-args.rs b/tests/rustdoc/inline_cross/default-generic-args.rs
new file mode 100644
index 00000000000..c9a87a19901
--- /dev/null
+++ b/tests/rustdoc/inline_cross/default-generic-args.rs
@@ -0,0 +1,104 @@
+#![crate_name = "user"]
+// aux-crate:default_generic_args=default-generic-args.rs
+// edition:2021
+
+// @has user/type.BoxedStr.html
+// @has - '//*[@class="rust item-decl"]//code' "Box<str>"
+pub use default_generic_args::BoxedStr;
+
+// @has user/type.IntMap.html
+// @has - '//*[@class="rust item-decl"]//code' "HashMap<i64, u64>"
+pub use default_generic_args::IntMap;
+
+// @has user/type.T0.html
+// @has - '//*[@class="rust item-decl"]//code' "TyPair<i32>"
+pub use default_generic_args::T0;
+
+// @has user/type.T1.html
+// @has - '//*[@class="rust item-decl"]//code' "TyPair<i32, u32>"
+pub use default_generic_args::T1;
+
+// @has user/type.T2.html
+// @has - '//*[@class="rust item-decl"]//code' "TyPair<i32, K>"
+pub use default_generic_args::T2;
+
+// @has user/type.T3.html
+// @has - '//*[@class="rust item-decl"]//code' "TyPair<Q>"
+pub use default_generic_args::T3;
+
+// @has user/type.C0.html
+// @has - '//*[@class="rust item-decl"]//code' "CtPair<43>"
+pub use default_generic_args::C0;
+
+// @has user/type.C1.html
+// @has - '//*[@class="rust item-decl"]//code' "CtPair<0, 1>"
+pub use default_generic_args::C1;
+
+// @has user/type.C2.html
+// @has - '//*[@class="rust item-decl"]//code' "CtPair<default_generic_args::::C2::{constant#0}, 3>"
+pub use default_generic_args::C2;
+
+// @has user/type.R0.html
+// @has - '//*[@class="rust item-decl"]//code' "Re<'q>"
+pub use default_generic_args::R0;
+
+// @has user/type.R1.html
+// @has - '//*[@class="rust item-decl"]//code' "Re<'q>"
+pub use default_generic_args::R1;
+
+// @has user/type.R2.html
+// Check that we consider regions:
+// @has - '//*[@class="rust item-decl"]//code' "Re<'q, &'static ()>"
+pub use default_generic_args::R2;
+
+// @has user/type.H0.html
+// Check that we handle higher-ranked regions correctly:
+// @has - '//*[@class="rust item-decl"]//code' "fn(_: for<'a> fn(_: Re<'a>))"
+pub use default_generic_args::H0;
+
+// @has user/type.H1.html
+// Check that we don't conflate distinct universially quantified regions (#1):
+// @has - '//*[@class="rust item-decl"]//code' "for<'b> fn(_: for<'a> fn(_: Re<'a, &'b ()>))"
+pub use default_generic_args::H1;
+
+// @has user/type.H2.html
+// Check that we don't conflate distinct universially quantified regions (#2):
+// @has - '//*[@class="rust item-decl"]//code' "for<'a> fn(_: for<'b> fn(_: Re<'a, &'b ()>))"
+pub use default_generic_args::H2;
+
+// @has user/type.P0.html
+// @has - '//*[@class="rust item-decl"]//code' "Proj<()>"
+pub use default_generic_args::P0;
+
+// @has user/type.P1.html
+// @has - '//*[@class="rust item-decl"]//code' "Proj<(), bool>"
+pub use default_generic_args::P1;
+
+// @has user/type.P2.html
+// @has - '//*[@class="rust item-decl"]//code' "Proj<(), ()>"
+pub use default_generic_args::P2;
+
+// @has user/type.A0.html
+// Ensure that we elide generic arguments that are alpha-equivalent to their respective
+// generic parameter (modulo substs) (#1):
+// @has - '//*[@class="rust item-decl"]//code' "Alpha"
+pub use default_generic_args::A0;
+
+// @has user/type.A1.html
+// Ensure that we elide generic arguments that are alpha-equivalent to their respective
+// generic parameter (modulo substs) (#1):
+// @has - '//*[@class="rust item-decl"]//code' "Alpha"
+pub use default_generic_args::A1;
+
+// @has user/type.M0.html
+// Test that we don't elide `u64` even if it coincides with `A`'s default precisely because
+// `()` is not the default of `B`. Mindlessly eliding `u64` would lead to `M<()>` which is a
+// different type (`M<(), u64>` versus `M<u64, ()>`).
+// @has - '//*[@class="rust item-decl"]//code' "Multi<u64, ()>"
+pub use default_generic_args::M0;
+
+// @has user/type.F.html
+// FIXME: Ideally, we would elide `&'a ()` but `'a` is an escaping bound var which we can't reason
+//        about at the moment since we don't keep track of bound vars.
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'a> Trait<'a, &'a ()>"
+pub use default_generic_args::F;
diff --git a/tests/rustdoc/inline_cross/dyn_trait.rs b/tests/rustdoc/inline_cross/dyn_trait.rs
index 679972f035a..9871be79ca3 100644
--- a/tests/rustdoc/inline_cross/dyn_trait.rs
+++ b/tests/rustdoc/inline_cross/dyn_trait.rs
@@ -75,16 +75,16 @@ pub use dyn_trait::AmbiguousBoundWrappedEarly1;
 pub use dyn_trait::AmbiguousBoundWrappedStatic;
 
 // @has user/type.NoBoundsWrappedDefaulted.html
-// @has - '//*[@class="rust item-decl"]//code' "Box<dyn Trait, Global>;"
+// @has - '//*[@class="rust item-decl"]//code' "Box<dyn Trait>;"
 pub use dyn_trait::NoBoundsWrappedDefaulted;
 // @has user/type.NoBoundsWrappedEarly.html
-// @has - '//*[@class="rust item-decl"]//code' "Box<dyn Trait + 'e, Global>;"
+// @has - '//*[@class="rust item-decl"]//code' "Box<dyn Trait + 'e>;"
 pub use dyn_trait::NoBoundsWrappedEarly;
 // @has user/fn.nbwl.html
-// @has - '//pre[@class="rust item-decl"]' "nbwl<'l>(_: Box<dyn Trait + 'l, Global>)"
+// @has - '//pre[@class="rust item-decl"]' "nbwl<'l>(_: Box<dyn Trait + 'l>)"
 pub use dyn_trait::no_bounds_wrapped_late as nbwl;
 // @has user/fn.nbwel.html
-// @has - '//pre[@class="rust item-decl"]' "nbwel(_: Box<dyn Trait + '_, Global>)"
+// @has - '//pre[@class="rust item-decl"]' "nbwel(_: Box<dyn Trait + '_>)"
 // NB: It might seem counterintuitive to display the explicitly elided lifetime `'_` here instead of
 // eliding it but this behavior is correct: The default is `'static` here which != `'_`.
 pub use dyn_trait::no_bounds_wrapped_elided as nbwel;
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
index 9b22026e490..3a2f5d16004 100644
--- a/tests/rustdoc/inline_cross/impl_trait.rs
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -4,7 +4,7 @@
 extern crate impl_trait_aux;
 
 // @has impl_trait/fn.func.html
-// @has - '//pre[@class="rust item-decl"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @has - '//pre[@class="rust item-decl"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
 // @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func;
 
@@ -34,6 +34,6 @@ pub use impl_trait_aux::func4;
 pub use impl_trait_aux::func5;
 
 // @has impl_trait/struct.Foo.html
-// @has - '//*[@id="method.method"]//h4[@class="code-header"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @has - '//*[@id="method.method"]//h4[@class="code-header"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
 // @!has - '//*[@id="method.method"]//h4[@class="code-header"]' 'where'
 pub use impl_trait_aux::Foo;
diff --git a/tests/rustdoc/normalize-assoc-item.rs b/tests/rustdoc/normalize-assoc-item.rs
index c6fd5e1101e..d39e1b15a4c 100644
--- a/tests/rustdoc/normalize-assoc-item.rs
+++ b/tests/rustdoc/normalize-assoc-item.rs
@@ -30,7 +30,7 @@ pub fn f2() -> <isize as Trait>::X {
 }
 
 pub struct S {
-    // @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.box_me_up"]' 'box_me_up: Box<S, Global>'
+    // @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.box_me_up"]' 'box_me_up: Box<S>'
     pub box_me_up: <S as Trait>::X,
     // @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.generic"]' 'generic: (usize, isize)'
     pub generic: <Generic<usize> as Trait>::X,
@@ -76,7 +76,7 @@ extern crate inner;
 // @has 'normalize_assoc_item/fn.foo.html' '//pre[@class="rust item-decl"]' "pub fn foo() -> i32"
 pub use inner::foo;
 
-// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust item-decl"]' "pub fn h<T>() -> IntoIter<T, Global>"
+// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust item-decl"]' "pub fn h<T>() -> IntoIter<T>"
 pub fn h<T>() -> <Vec<T> as IntoIterator>::IntoIter {
     vec![].into_iter()
 }
diff --git a/tests/rustdoc/where-clause-order.rs b/tests/rustdoc/where-clause-order.rs
index 7261dfa7dd9..e3184b646bf 100644
--- a/tests/rustdoc/where-clause-order.rs
+++ b/tests/rustdoc/where-clause-order.rs
@@ -7,7 +7,7 @@ where
 }
 
 // @has 'foo/trait.SomeTrait.html'
-// @has - "//*[@id='impl-SomeTrait-for-(A,+B,+C,+D,+E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
+// @has - "//*[@id='impl-SomeTrait-for-(A,+B,+C,+D,+E)']/h3" "impl<A, B, C, D, E> SomeTrait for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
 impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)
 where
     A: PartialOrd<A> + PartialEq<A>,
diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr
index 5a02f4aa93a..69e19e1d4d2 100644
--- a/tests/ui/c-variadic/issue-86053-1.stderr
+++ b/tests/ui/c-variadic/issue-86053-1.stderr
@@ -50,13 +50,7 @@ error: only foreign or `unsafe extern "C"` functions may be C-variadic
   --> $DIR/issue-86053-1.rs:11:12
    |
 LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
-   |            ^^^
-
-error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/issue-86053-1.rs:11:36
-   |
-LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
-   |                                    ^^^
+   |            ^^^                     ^^^
 
 error[E0412]: cannot find type `F` in this scope
   --> $DIR/issue-86053-1.rs:11:48
@@ -76,6 +70,6 @@ help: you might be missing a type parameter
 LL | fn ordering4 < 'a , 'b, F     > ( a :            ,   self , self ,   self ,
    |                       +++
 
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
index 7ce2b9ac95a..b7ec657120c 100644
--- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
@@ -15,6 +15,7 @@ LL |     fn test(&self) -> [u8; bar::<Self>()];
    |        ...because method `test` references the `Self` type in its `where` clause
    = help: consider moving `test` to another trait
    = help: consider moving `test` to another trait
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error: aborting due to previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
index 303700c7ab4..00b8c0eef98 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
@@ -14,6 +14,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     fn ptr(self: Ptr<Self>);
    |                  ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
+   = help: only type `i32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:5
@@ -31,6 +32,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     fn ptr(self: Ptr<Self>);
    |                  ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
+   = help: only type `i32` implements the trait, consider using it directly instead
    = note: required for the cast from `Ptr<{integer}>` to `Ptr<dyn Trait>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
index fd54faaf37c..9013d429530 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
@@ -12,6 +12,9 @@ LL | trait Foo {
 LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
    = help: consider moving `A` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
+             Fooy
+             Fooer<T>
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr
index 370329b9f83..bb14e297174 100644
--- a/tests/ui/generic-associated-types/issue-76535.base.stderr
+++ b/tests/ui/generic-associated-types/issue-76535.base.stderr
@@ -28,6 +28,8 @@ LL | pub trait SuperTrait {
 LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
+   = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
+   = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
 
 error[E0038]: the trait `SuperTrait` cannot be made into an object
   --> $DIR/issue-76535.rs:39:57
@@ -43,6 +45,8 @@ LL | pub trait SuperTrait {
 LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
+   = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
+   = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
    = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr
index ad704f5e9f0..bcc6382cf7c 100644
--- a/tests/ui/generic-associated-types/issue-79422.base.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.base.stderr
@@ -28,6 +28,9 @@ LL | trait MapLike<K, V> {
 LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
+             std::collections::BTreeMap<K, V>
+             Source
 
 error[E0038]: the trait `MapLike` cannot be made into an object
   --> $DIR/issue-79422.rs:44:13
@@ -43,6 +46,9 @@ LL | trait MapLike<K, V> {
 LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
+             std::collections::BTreeMap<K, V>
+             Source
    = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
index bfb2be8cbc1..f29ec95d594 100644
--- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
+++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
@@ -9,6 +9,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL |     fn bar(self) -> impl Deref<Target = impl Sized>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type
+   = help: only type `rpitit::Foreign` implements the trait, consider using it directly instead
 
 error: aborting due to previous error
 
diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr
index 3271cb18d9f..a7be0516cd3 100644
--- a/tests/ui/impl-trait/in-trait/object-safety.stderr
+++ b/tests/ui/impl-trait/in-trait/object-safety.stderr
@@ -12,6 +12,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/object-safety.rs:17:15
@@ -27,6 +28,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/object-safety.rs:17:13
@@ -42,6 +44,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/object-safety.rs:14:13
@@ -57,6 +60,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
index 687dbe65e6c..37c96d9bc4e 100644
--- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
+++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
@@ -11,6 +11,9 @@ LL | trait NotObjectSafe {
    |       ------------- this trait cannot be made into an object...
 LL |     fn foo() -> Self;
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead:
+             A
+             B
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) -> Self;
@@ -33,6 +36,9 @@ LL | trait NotObjectSafe {
    |       ------------- this trait cannot be made into an object...
 LL |     fn foo() -> Self;
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead:
+             A
+             B
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) -> Self;
diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr
index 37e280fbcc7..f6244d9d44f 100644
--- a/tests/ui/issues/issue-19380.stderr
+++ b/tests/ui/issues/issue-19380.stderr
@@ -11,6 +11,7 @@ LL | trait Qiz {
    |       --- this trait cannot be made into an object...
 LL |   fn qiz();
    |      ^^^ ...because associated function `qiz` has no `self` parameter
+   = help: only type `Foo` implements the trait, consider using it directly instead
 help: consider turning `qiz` into a method by giving it a `&self` argument
    |
 LL |   fn qiz(&self);
@@ -33,6 +34,7 @@ LL | trait Qiz {
    |       --- this trait cannot be made into an object...
 LL |   fn qiz();
    |      ^^^ ...because associated function `qiz` has no `self` parameter
+   = help: only type `Foo` implements the trait, consider using it directly instead
    = note: required for the cast from `&Foo` to `&'static (dyn Qiz + 'static)`
 help: consider turning `qiz` into a method by giving it a `&self` argument
    |
diff --git a/tests/ui/lint/lint-unnecessary-parens.fixed b/tests/ui/lint/lint-unnecessary-parens.fixed
index bafac05d8da..b17914da6e6 100644
--- a/tests/ui/lint/lint-unnecessary-parens.fixed
+++ b/tests/ui/lint/lint-unnecessary-parens.fixed
@@ -84,6 +84,14 @@ fn main() {
     _a = 0; //~ ERROR unnecessary parentheses around assigned value
     _a += 1; //~ ERROR unnecessary parentheses around assigned value
 
+    let mut _a = 3; //~ ERROR unnecessary parentheses around pattern
+    let mut _a = 3; //~ ERROR unnecessary parentheses around pattern
+    let mut _a = 3; //~ ERROR unnecessary parentheses around pattern
+
+    let _a = 3; //~ ERROR unnecessary parentheses around pattern
+    let _a = 3; //~ ERROR unnecessary parentheses around pattern
+    let _a = 3; //~ ERROR unnecessary parentheses around pattern
+
     let _a = baz!(3, 4);
     let _b = baz!(3);
 }
diff --git a/tests/ui/lint/lint-unnecessary-parens.rs b/tests/ui/lint/lint-unnecessary-parens.rs
index ce537a4dc1d..4cbd6562cd3 100644
--- a/tests/ui/lint/lint-unnecessary-parens.rs
+++ b/tests/ui/lint/lint-unnecessary-parens.rs
@@ -84,6 +84,14 @@ fn main() {
     _a = (0); //~ ERROR unnecessary parentheses around assigned value
     _a += (1); //~ ERROR unnecessary parentheses around assigned value
 
+    let(mut _a) = 3; //~ ERROR unnecessary parentheses around pattern
+    let (mut _a) = 3; //~ ERROR unnecessary parentheses around pattern
+    let( mut _a) = 3; //~ ERROR unnecessary parentheses around pattern
+
+    let(_a) = 3; //~ ERROR unnecessary parentheses around pattern
+    let (_a) = 3; //~ ERROR unnecessary parentheses around pattern
+    let( _a) = 3; //~ ERROR unnecessary parentheses around pattern
+
     let _a = baz!(3, 4);
     let _b = baz!(3);
 }
diff --git a/tests/ui/lint/lint-unnecessary-parens.stderr b/tests/ui/lint/lint-unnecessary-parens.stderr
index 2ad07530f8c..ba7a78b8da1 100644
--- a/tests/ui/lint/lint-unnecessary-parens.stderr
+++ b/tests/ui/lint/lint-unnecessary-parens.stderr
@@ -267,5 +267,77 @@ LL -     _a += (1);
 LL +     _a += 1;
    |
 
-error: aborting due to 22 previous errors
+error: unnecessary parentheses around pattern
+  --> $DIR/lint-unnecessary-parens.rs:87:8
+   |
+LL |     let(mut _a) = 3;
+   |        ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     let(mut _a) = 3;
+LL +     let mut _a = 3;
+   |
+
+error: unnecessary parentheses around pattern
+  --> $DIR/lint-unnecessary-parens.rs:88:9
+   |
+LL |     let (mut _a) = 3;
+   |         ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     let (mut _a) = 3;
+LL +     let mut _a = 3;
+   |
+
+error: unnecessary parentheses around pattern
+  --> $DIR/lint-unnecessary-parens.rs:89:8
+   |
+LL |     let( mut _a) = 3;
+   |        ^^      ^
+   |
+help: remove these parentheses
+   |
+LL -     let( mut _a) = 3;
+LL +     let mut _a = 3;
+   |
+
+error: unnecessary parentheses around pattern
+  --> $DIR/lint-unnecessary-parens.rs:91:8
+   |
+LL |     let(_a) = 3;
+   |        ^  ^
+   |
+help: remove these parentheses
+   |
+LL -     let(_a) = 3;
+LL +     let _a = 3;
+   |
+
+error: unnecessary parentheses around pattern
+  --> $DIR/lint-unnecessary-parens.rs:92:9
+   |
+LL |     let (_a) = 3;
+   |         ^  ^
+   |
+help: remove these parentheses
+   |
+LL -     let (_a) = 3;
+LL +     let _a = 3;
+   |
+
+error: unnecessary parentheses around pattern
+  --> $DIR/lint-unnecessary-parens.rs:93:8
+   |
+LL |     let( _a) = 3;
+   |        ^^  ^
+   |
+help: remove these parentheses
+   |
+LL -     let( _a) = 3;
+LL +     let _a = 3;
+   |
+
+error: aborting due to 28 previous errors
 
diff --git a/tests/ui/lint/unused/issue-117284-arg-in-macro.rs b/tests/ui/lint/unused/issue-117284-arg-in-macro.rs
new file mode 100644
index 00000000000..eea0f4c594d
--- /dev/null
+++ b/tests/ui/lint/unused/issue-117284-arg-in-macro.rs
@@ -0,0 +1,17 @@
+#![deny(unused_variables)]
+macro_rules! make_var {
+    ($struct:ident, $var:ident) => {
+        let $var = $struct.$var;
+    };
+}
+
+#[allow(unused)]
+struct MyStruct {
+    var: i32,
+}
+
+fn main() {
+    let s = MyStruct { var: 42 };
+    make_var!(s, var); //~ ERROR unused variable: `var`
+    let a = 1; //~ ERROR unused variable: `a`
+}
diff --git a/tests/ui/lint/unused/issue-117284-arg-in-macro.stderr b/tests/ui/lint/unused/issue-117284-arg-in-macro.stderr
new file mode 100644
index 00000000000..84efaa4f368
--- /dev/null
+++ b/tests/ui/lint/unused/issue-117284-arg-in-macro.stderr
@@ -0,0 +1,29 @@
+error: unused variable: `var`
+  --> $DIR/issue-117284-arg-in-macro.rs:15:18
+   |
+LL |     make_var!(s, var);
+   |                  ^^^
+   |
+help: `var` is captured in macro and introduced a unused variable
+  --> $DIR/issue-117284-arg-in-macro.rs:4:13
+   |
+LL |         let $var = $struct.$var;
+   |             ^^^^
+...
+LL |     make_var!(s, var);
+   |     ----------------- in this macro invocation
+note: the lint level is defined here
+  --> $DIR/issue-117284-arg-in-macro.rs:1:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `make_var` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unused variable: `a`
+  --> $DIR/issue-117284-arg-in-macro.rs:16:9
+   |
+LL |     let a = 1;
+   |         ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/object-safety/issue-19538.stderr
index 183245b2322..31657501e25 100644
--- a/tests/ui/object-safety/issue-19538.stderr
+++ b/tests/ui/object-safety/issue-19538.stderr
@@ -13,6 +13,7 @@ LL |     fn foo<T>(&self, val: T);
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
    = help: consider moving `foo` to another trait
+   = help: only type `Thing` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-19538.rs:17:30
@@ -29,6 +30,7 @@ LL |     fn foo<T>(&self, val: T);
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
    = help: consider moving `foo` to another trait
+   = help: only type `Thing` implements the trait, consider using it directly instead
    = note: required for the cast from `&mut Thing` to `&mut dyn Bar`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/object-safety/object-safety-issue-22040.stderr b/tests/ui/object-safety/object-safety-issue-22040.stderr
index 0262d536246..2e59d88bdaf 100644
--- a/tests/ui/object-safety/object-safety-issue-22040.stderr
+++ b/tests/ui/object-safety/object-safety-issue-22040.stderr
@@ -11,6 +11,7 @@ LL | trait Expr: Debug + PartialEq {
    |       ----          ^^^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `SExpr<'x>` implements the trait, consider using it directly instead
 
 error: aborting due to previous error
 
diff --git a/tests/ui/object-safety/object-safety-no-static.curr.stderr b/tests/ui/object-safety/object-safety-no-static.curr.stderr
index 1b025229e54..b40470b457b 100644
--- a/tests/ui/object-safety/object-safety-no-static.curr.stderr
+++ b/tests/ui/object-safety/object-safety-no-static.curr.stderr
@@ -11,6 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo() {}
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) {}
diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
index befcef952a8..1eae9a9b9da 100644
--- a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
@@ -11,6 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo() {}
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
index 0b61e267da8..b173e23e7a1 100644
--- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
+++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
@@ -32,6 +32,18 @@ extern "C" fn f3_3(..., x: isize) {}
 //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
 //~| ERROR `...` must be the last argument of a C-variadic function
 
+const unsafe extern "C" fn f4_1(x: isize, ...) {}
+//~^ ERROR functions cannot be both `const` and C-variadic
+
+const extern "C" fn f4_2(x: isize, ...) {}
+//~^ ERROR functions cannot be both `const` and C-variadic
+//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+
+const extern "C" fn f4_3(..., x: isize, ...) {}
+//~^ ERROR functions cannot be both `const` and C-variadic
+//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+//~| ERROR `...` must be the last argument of a C-variadic function
+
 extern "C" {
     fn e_f1(...);
     //~^ ERROR C-variadic function must be declared with at least one named argument
@@ -49,12 +61,13 @@ impl X {
     //~| ERROR C-variadic function must be declared with at least one named argument
     fn i_f3(..., x: isize, ...) {}
     //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
-    //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR `...` must be the last argument of a C-variadic function
     fn i_f4(..., x: isize, ...) {}
     //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
-    //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
     //~| ERROR `...` must be the last argument of a C-variadic function
+    const fn i_f5(x: isize, ...) {}
+    //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
+    //~| ERROR functions cannot be both `const` and C-variadic
 }
 
 trait T {
diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
index f1cbbb279c8..18526080e4c 100644
--- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
+++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
@@ -76,131 +76,172 @@ error: only foreign or `unsafe extern "C"` functions may be C-variadic
 LL | extern "C" fn f3_3(..., x: isize) {}
    |                    ^^^
 
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:35:1
+   |
+LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
+   | ^^^^^ `const` because of this             ^^^ C-variadic because of this
+
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:38:1
+   |
+LL | const extern "C" fn f4_2(x: isize, ...) {}
+   | ^^^^^ `const` because of this      ^^^ C-variadic because of this
+
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:38:36
+   |
+LL | const extern "C" fn f4_2(x: isize, ...) {}
+   |                                    ^^^
+
+error: `...` must be the last argument of a C-variadic function
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
+   |
+LL | const extern "C" fn f4_3(..., x: isize, ...) {}
+   |                          ^^^
+
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
+   |
+LL | const extern "C" fn f4_3(..., x: isize, ...) {}
+   | ^^^^^                    ^^^            ^^^ C-variadic because of this
+   | |                        |
+   | |                        C-variadic because of this
+   | `const` because of this
+
+error: only foreign or `unsafe extern "C"` functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
+   |
+LL | const extern "C" fn f4_3(..., x: isize, ...) {}
+   |                          ^^^            ^^^
+
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:36:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
    |
 LL |     fn e_f1(...);
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:38:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
    |
 LL |     fn e_f2(..., x: isize);
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:45:23
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:57:23
    |
 LL |     fn i_f1(x: isize, ...) {}
    |                       ^^^
 
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
    |
 LL |     fn i_f2(...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
    |
 LL |     fn i_f2(...) {}
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
-   |
-LL |     fn i_f3(..., x: isize, ...) {}
-   |             ^^^
-
-error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
    |
 LL |     fn i_f3(..., x: isize, ...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:50:28
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
    |
 LL |     fn i_f3(..., x: isize, ...) {}
-   |                            ^^^
+   |             ^^^            ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
    |
 LL |     fn i_f4(..., x: isize, ...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
    |
 LL |     fn i_f4(..., x: isize, ...) {}
-   |             ^^^
+   |             ^^^            ^^^
+
+error: functions cannot be both `const` and C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:68:5
+   |
+LL |     const fn i_f5(x: isize, ...) {}
+   |     ^^^^^                   ^^^ C-variadic because of this
+   |     |
+   |     `const` because of this
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:54:28
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:68:29
    |
-LL |     fn i_f4(..., x: isize, ...) {}
-   |                            ^^^
+LL |     const fn i_f5(x: isize, ...) {}
+   |                             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:61:23
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
    |
 LL |     fn t_f1(x: isize, ...) {}
    |                       ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:63:23
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:76:23
    |
 LL |     fn t_f2(x: isize, ...);
    |                       ^^^
 
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
    |
 LL |     fn t_f3(...) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
    |
 LL |     fn t_f3(...) {}
    |             ^^^
 
 error: C-variadic function must be declared with at least one named argument
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
    |
 LL |     fn t_f4(...);
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13
    |
 LL |     fn t_f4(...);
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
    |
 LL |     fn t_f5(..., x: isize) {}
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13
    |
 LL |     fn t_f5(..., x: isize) {}
    |             ^^^
 
 error: `...` must be the last argument of a C-variadic function
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
    |
 LL |     fn t_f6(..., x: isize);
    |             ^^^
 
 error: only foreign or `unsafe extern "C"` functions may be C-variadic
-  --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13
    |
 LL |     fn t_f6(..., x: isize);
    |             ^^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 40 previous errors
 
diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
index 13591f5b635..fdd18c6b37b 100644
--- a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
+++ b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
@@ -14,6 +14,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
+   = help: only type `usize` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
@@ -31,6 +32,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
+   = help: only type `usize` implements the trait, consider using it directly instead
    = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
index 593f705353a..0a567ddcc2e 100644
--- a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
+++ b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
@@ -14,6 +14,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
+   = help: only type `usize` implements the trait, consider using it directly instead
    = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>`
 
 error: aborting due to previous error
diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr
index d5327602430..3ab9af21bc4 100644
--- a/tests/ui/traits/issue-38604.stderr
+++ b/tests/ui/traits/issue-38604.stderr
@@ -11,6 +11,7 @@ LL | trait Foo where u32: Q<Self> {
    |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/issue-38604.rs:15:9
@@ -25,6 +26,7 @@ LL | trait Foo where u32: Q<Self> {
    |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<()>` to `Box<dyn Foo>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index af2e0763212..d74be772660 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -143,6 +143,7 @@ LL |         const C: u8 = 0;
    = help: consider moving `C` to another trait
    = help: consider moving `A` to another trait
    = help: consider moving `B` to another trait
+   = help: only type `S` implements the trait, consider using it directly instead
 
 error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:115:12
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
index d56519223f4..b6e540c5ffc 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
@@ -20,6 +20,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
    = note: required for the cast from `&()` to `&dyn Foo`
 
 error[E0038]: the trait `Foo` cannot be made into an object
@@ -35,6 +36,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/supertrait-object-safety.rs:22:5
@@ -49,6 +51,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr
index a51b6975938..19a46a502c2 100644
--- a/tests/ui/traits/object/safety.stderr
+++ b/tests/ui/traits/object/safety.stderr
@@ -11,6 +11,7 @@ LL | trait Tr {
    |       -- this trait cannot be made into an object...
 LL |     fn foo();
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `St` implements the trait, consider using it directly instead
    = note: required for the cast from `&St` to `&dyn Tr`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
@@ -34,6 +35,7 @@ LL | trait Tr {
    |       -- this trait cannot be made into an object...
 LL |     fn foo();
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `St` implements the trait, consider using it directly instead
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self);
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
index 74a0fc42708..3972e539776 100644
--- a/tests/ui/traits/test-2.stderr
+++ b/tests/ui/traits/test-2.stderr
@@ -42,6 +42,9 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead:
+             i32
+             u32
 
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/test-2.rs:13:5
@@ -59,6 +62,9 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead:
+             i32
+             u32
 
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/test-2.rs:13:6
@@ -76,6 +82,9 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead:
+             i32
+             u32
    = note: required for the cast from `Box<{integer}>` to `Box<dyn bar>`
 
 error: aborting due to 5 previous errors
diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
index 8a296dc7ee6..4412c49eadd 100644
--- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
+++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
@@ -24,6 +24,7 @@ LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
    |       |
    |       this trait cannot be made into an object...
    = help: consider moving `add` to another trait
+   = help: only type `i32` implements the trait, consider using it directly instead
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
index 40a25c7df6b..85f5073364f 100644
--- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
+++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
@@ -11,6 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<S>` to `Box<dyn Trait>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -26,6 +27,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<S>` to `Box<(dyn Trait + 'static)>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -41,6 +43,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<S>` to `Box<dyn Trait>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
index e2c71df2feb..a2a19631649 100644
--- a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
+++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
@@ -11,6 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -26,6 +27,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -41,6 +43,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
index d5b23572ff5..a0279774abe 100644
--- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -29,6 +29,9 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
+             S
+             R
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -48,6 +51,9 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
+             S
+             R
    = note: required for the cast from `&R` to `&dyn Trait`
 
 error: aborting due to 3 previous errors