about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-29 20:45:00 +0000
committerbors <bors@rust-lang.org>2024-08-29 20:45:00 +0000
commit0d634185dfddefe09047881175f35c65d68dcff1 (patch)
treec85fc78596b0d89063efefc1e1f3437e51c7e15e
parent784d444733d65c3d305ce5edcbb41e3d0d0aee2e (diff)
parent9c7ae1d4d88b5212eabff72441b7d316e52df164 (diff)
downloadrust-0d634185dfddefe09047881175f35c65d68dcff1.tar.gz
rust-0d634185dfddefe09047881175f35c65d68dcff1.zip
Auto merge of #129750 - GuillaumeGomez:rollup-gphsb7y, r=GuillaumeGomez
Rollup of 7 pull requests

Successful merges:

 - #123940 (debug-fmt-detail option)
 - #128166 (Improved `checked_isqrt` and `isqrt` methods)
 - #128970 (Add `-Zlint-llvm-ir`)
 - #129316 (riscv64imac: allow shadow call stack sanitizer)
 - #129690 (Add `needs-unwind` compiletest directive to `libtest-thread-limit` and replace some `Path` with `path` in `run-make`)
 - #129732 (Add `unreachable_pub`, round 3)
 - #129743 (Fix rustdoc clippy lints)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs12
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp9
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs6
-rw-r--r--compiler/rustc_macros/src/lib.rs1
-rw-r--r--compiler/rustc_macros/src/lift.rs2
-rw-r--r--compiler/rustc_macros/src/query.rs2
-rw-r--r--compiler/rustc_macros/src/serialize.rs28
-rw-r--r--compiler/rustc_macros/src/symbols.rs2
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs2
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs4
-rw-r--r--compiler/rustc_metadata/src/lib.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs5
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs4
-rw-r--r--compiler/rustc_middle/src/mir/generic_graph.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_build/src/lib.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs8
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs16
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs18
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs1
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs2
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/lib.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/inspect/build.rs49
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs4
-rw-r--r--compiler/rustc_parse/src/errors.rs70
-rw-r--r--compiler/rustc_parse/src/lib.rs1
-rw-r--r--compiler/rustc_parse_format/src/lib.rs1
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs2
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs366
-rw-r--r--compiler/rustc_passes/src/lang_items.rs2
-rw-r--r--compiler/rustc_passes/src/lib.rs1
-rw-r--r--compiler/rustc_passes/src/lib_features.rs4
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs2
-rw-r--r--compiler/rustc_passes/src/upvars.rs2
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs6
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_privacy/src/errors.rs18
-rw-r--r--compiler/rustc_privacy/src/lib.rs3
-rw-r--r--compiler/rustc_query_impl/src/lib.rs1
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs44
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs6
-rw-r--r--compiler/rustc_query_system/src/error.rs14
-rw-r--r--compiler/rustc_query_system/src/lib.rs1
-rw-r--r--compiler/rustc_resolve/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/config.rs24
-rw-r--r--compiler/rustc_session/src/config/cfg.rs19
-rw-r--r--compiler/rustc_session/src/options.rs16
-rw-r--r--compiler/rustc_span/src/symbol.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs2
-rw-r--r--library/core/benches/lib.rs1
-rw-r--r--library/core/benches/num/int_sqrt/mod.rs62
-rw-r--r--library/core/benches/num/mod.rs1
-rw-r--r--library/core/src/fmt/rt.rs4
-rw-r--r--library/core/src/num/int_macros.rs36
-rw-r--r--library/core/src/num/int_sqrt.rs316
-rw-r--r--library/core/src/num/mod.rs1
-rw-r--r--library/core/src/num/nonzero.rs33
-rw-r--r--library/core/src/num/uint_macros.rs20
-rw-r--r--library/core/tests/num/int_macros.rs32
-rw-r--r--library/core/tests/num/int_sqrt.rs248
-rw-r--r--library/core/tests/num/mod.rs1
-rw-r--r--src/doc/rustc/src/check-cfg.md3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/fmt-debug.md15
-rw-r--r--src/doc/unstable-book/src/compiler-flags/lint-llvm-ir.md7
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md40
-rw-r--r--src/librustdoc/clean/auto_trait.rs2
-rw-r--r--src/librustdoc/clean/blanket_impl.rs2
-rw-r--r--src/librustdoc/clean/inline.rs28
-rw-r--r--src/librustdoc/clean/mod.rs55
-rw-r--r--src/librustdoc/clean/simplify.rs2
-rw-r--r--src/librustdoc/clean/types.rs31
-rw-r--r--src/librustdoc/clean/utils.rs12
-rw-r--r--src/librustdoc/config.rs6
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/doctest.rs16
-rw-r--r--src/librustdoc/doctest/make.rs2
-rw-r--r--src/librustdoc/doctest/markdown.rs2
-rw-r--r--src/librustdoc/doctest/runner.rs6
-rw-r--r--src/librustdoc/error.rs2
-rw-r--r--src/librustdoc/formats/cache.rs12
-rw-r--r--src/librustdoc/html/format.rs19
-rw-r--r--tests/codegen/cast-target-abi.rs4
-rw-r--r--tests/codegen/cffi/ffi-out-of-bounds-loads.rs3
-rw-r--r--tests/codegen/sanitizer/riscv64-shadow-call-stack.rs17
-rw-r--r--tests/run-make/dos-device-input/rmake.rs6
-rw-r--r--tests/run-make/emit-shared-files/rmake.rs44
-rw-r--r--tests/run-make/libtest-thread-limit/rmake.rs3
-rw-r--r--tests/run-make/manual-crate-name/rmake.rs6
-rw-r--r--tests/run-make/pretty-print-with-dep-file/rmake.rs6
-rw-r--r--tests/run-make/profile/rmake.rs10
-rw-r--r--tests/run-make/reset-codegen-1/rmake.rs10
-rw-r--r--tests/run-make/rustdoc-determinism/rmake.rs8
-rw-r--r--tests/run-make/rustdoc-output-path/rmake.rs6
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.fmt_debug_.stderr8
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.rs2
-rw-r--r--tests/ui/check-cfg/allow-same-level.stderr2
-rw-r--r--tests/ui/check-cfg/cargo-build-script.stderr2
-rw-r--r--tests/ui/check-cfg/cargo-feature.none.stderr2
-rw-r--r--tests/ui/check-cfg/cargo-feature.some.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name.stderr2
-rw-r--r--tests/ui/check-cfg/compact-names.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.feature.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.full.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names.stderr2
-rw-r--r--tests/ui/check-cfg/mix.stderr2
-rw-r--r--tests/ui/check-cfg/stmt-no-ice.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-names.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.rs3
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr69
-rw-r--r--tests/ui/feature-gates/feature-gate-fmt-debug.rs5
-rw-r--r--tests/ui/feature-gates/feature-gate-fmt-debug.stderr13
-rw-r--r--tests/ui/fmt/fmt_debug/full.rs15
-rw-r--r--tests/ui/fmt/fmt_debug/invalid.rs4
-rw-r--r--tests/ui/fmt/fmt_debug/invalid.stderr2
-rw-r--r--tests/ui/fmt/fmt_debug/none.rs37
-rw-r--r--tests/ui/fmt/fmt_debug/shallow.rs33
141 files changed, 1587 insertions, 644 deletions
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index bf40c9b66c6..8c742d2aaf4 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -4,9 +4,10 @@ use std::borrow::Cow;
 use rustc_ast::visit::Visitor;
 use rustc_ast::*;
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_hir as hir;
+use rustc_session::config::FmtDebug;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{sym, Span, Symbol};
-use {rustc_ast as ast, rustc_hir as hir};
 
 use super::LoweringContext;
 
@@ -243,7 +244,10 @@ fn make_argument<'hir>(
         hir::LangItem::FormatArgument,
         match ty {
             Format(Display) => sym::new_display,
-            Format(Debug) => sym::new_debug,
+            Format(Debug) => match ctx.tcx.sess.opts.unstable_opts.fmt_debug {
+                FmtDebug::Full | FmtDebug::Shallow => sym::new_debug,
+                FmtDebug::None => sym::new_debug_noop,
+            },
             Format(LowerExp) => sym::new_lower_exp,
             Format(UpperExp) => sym::new_upper_exp,
             Format(Octal) => sym::new_octal,
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 755e6ee0d3e..57d9c076150 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -1,5 +1,6 @@
 use rustc_ast::{self as ast, EnumDef, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
+use rustc_session::config::FmtDebug;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
 use thin_vec::{thin_vec, ThinVec};
@@ -49,6 +50,11 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) ->
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = cx.with_def_site_ctxt(span);
 
+    let fmt_detail = cx.sess.opts.unstable_opts.fmt_debug;
+    if fmt_detail == FmtDebug::None {
+        return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new())));
+    }
+
     let (ident, vdata, fields) = match substr.fields {
         Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
         EnumMatching(_, v, fields) => (v.ident, &v.data, fields),
@@ -61,6 +67,13 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) ->
     let name = cx.expr_str(span, ident.name);
     let fmt = substr.nonselflike_args[0].clone();
 
+    // Fieldless enums have been special-cased earlier
+    if fmt_detail == FmtDebug::Shallow {
+        let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
+        let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]);
+        return BlockOrExpr::new_expr(expr);
+    }
+
     // Struct and tuples are similar enough that we use the same code for both,
     // with some extra pieces for structs due to the field names.
     let (is_struct, args_per_field) = match vdata {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index adf7e933f43..a5c27d2282e 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -571,6 +571,7 @@ pub(crate) unsafe fn llvm_optimize(
             cgcx.opts.cg.linker_plugin_lto.enabled(),
             config.no_prepopulate_passes,
             config.verify_llvm_ir,
+            config.lint_llvm_ir,
             using_thin_buffers,
             config.merge_functions,
             unroll_loops,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 5e0d7418993..138cc3219aa 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2225,6 +2225,7 @@ unsafe extern "C" {
         IsLinkerPluginLTO: bool,
         NoPrepopulatePasses: bool,
         VerifyIR: bool,
+        LintIR: bool,
         UseThinLTOBuffers: bool,
         MergeFunctions: bool,
         UnrollLoops: bool,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 7ad31802454..feb27c148a1 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -112,6 +112,7 @@ pub struct ModuleConfig {
     // Miscellaneous flags. These are mostly copied from command-line
     // options.
     pub verify_llvm_ir: bool,
+    pub lint_llvm_ir: bool,
     pub no_prepopulate_passes: bool,
     pub no_builtins: bool,
     pub time_module: bool,
@@ -237,6 +238,7 @@ impl ModuleConfig {
             bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(),
 
             verify_llvm_ir: sess.verify_llvm_ir(),
+            lint_llvm_ir: sess.opts.unstable_opts.lint_llvm_ir,
             no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes,
             no_builtins: no_builtins || sess.target.no_builtins,
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 2747a14d60a..e2491922b8d 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -37,6 +37,8 @@ const GATED_CFGS: &[GatedCfg] = &[
     (sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)),
     (sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)),
     (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)),
+    // this is consistent with naming of the compiler flag it's for
+    (sym::fmt_debug, sym::fmt_debug, cfg_fn!(fmt_debug)),
 ];
 
 /// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index f7ddc3e2c56..7ea037ca8b2 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -471,6 +471,8 @@ declare_features! (
     (unstable, ffi_const, "1.45.0", Some(58328)),
     /// Allows the use of `#[ffi_pure]` on foreign functions.
     (unstable, ffi_pure, "1.45.0", Some(58329)),
+    /// Controlling the behavior of fmt::Debug
+    (unstable, fmt_debug, "CURRENT_RUSTC_VERSION", Some(129709)),
     /// Allows using `#[repr(align(...))]` on function items
     (unstable, fn_align, "1.53.0", Some(82232)),
     /// Support delegating implementation of functions to other already implemented functions.
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 486136a2bcc..844d8ef02e0 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -10,11 +10,11 @@ use rustc_errors::{registry, ColorConfig};
 use rustc_session::config::{
     build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
     CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat,
-    ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
-    Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
-    LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
-    PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
-    SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
+    ErrorOutputType, ExternEntry, ExternLocation, Externs, FmtDebug, FunctionReturn,
+    InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained,
+    LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName,
+    OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius,
+    ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
@@ -780,6 +780,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(fewer_names, Some(true));
     tracked!(fixed_x18, true);
     tracked!(flatten_format_args, false);
+    tracked!(fmt_debug, FmtDebug::Shallow);
     tracked!(force_unstable_if_unmarked, true);
     tracked!(fuel, Some(("abc".to_string(), 99)));
     tracked!(function_return, FunctionReturn::ThunkExtern);
@@ -794,6 +795,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(instrument_xray, Some(InstrumentXRay::default()));
     tracked!(link_directives, false);
     tracked!(link_only, true);
+    tracked!(lint_llvm_ir, true);
     tracked!(llvm_module_flag, vec![("bar".to_string(), 123, "max".to_string())]);
     tracked!(llvm_plugins, vec![String::from("plugin_name")]);
     tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 9884ed15b8a..c7306b0516f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -713,7 +713,7 @@ extern "C" LLVMRustResult LLVMRustOptimize(
     LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef,
     LLVMRustPassBuilderOptLevel OptLevelRust, LLVMRustOptStage OptStage,
     bool IsLinkerPluginLTO, bool NoPrepopulatePasses, bool VerifyIR,
-    bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops,
+    bool LintIR, bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops,
     bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls,
     bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions,
     const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage,
@@ -842,6 +842,13 @@ extern "C" LLVMRustResult LLVMRustOptimize(
         });
   }
 
+  if (LintIR) {
+    PipelineStartEPCallbacks.push_back(
+        [](ModulePassManager &MPM, OptimizationLevel Level) {
+          MPM.addPass(createModuleToFunctionPassAdaptor(LintPass()));
+        });
+  }
+
   if (InstrumentGCOV) {
     PipelineStartEPCallbacks.push_back(
         [](ModulePassManager &MPM, OptimizationLevel Level) {
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 134045d0644..0f7b8921509 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -55,7 +55,7 @@ use synstructure::Structure;
 ///
 /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
-pub fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
+pub(super) fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
     s.underscore_const(true);
     DiagnosticDerive::new(s).into_tokens()
 }
@@ -102,7 +102,7 @@ pub fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
 ///
 /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
-pub fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
+pub(super) fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
     s.underscore_const(true);
     LintDiagnosticDerive::new(s).into_tokens()
 }
@@ -153,7 +153,7 @@ pub fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
 ///
 /// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
 /// ```
-pub fn subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream {
+pub(super) fn subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream {
     s.underscore_const(true);
     SubdiagnosticDerive::new().into_tokens(s)
 }
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 929bc2df6f6..f46c795b956 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]
 #![feature(proc_macro_tracked_env)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use proc_macro::TokenStream;
diff --git a/compiler/rustc_macros/src/lift.rs b/compiler/rustc_macros/src/lift.rs
index 627f4088d5f..bf4a7665ceb 100644
--- a/compiler/rustc_macros/src/lift.rs
+++ b/compiler/rustc_macros/src/lift.rs
@@ -1,7 +1,7 @@
 use quote::quote;
 use syn::parse_quote;
 
-pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     s.add_bounds(synstructure::AddBounds::Generics);
     s.bind_with(|_| synstructure::BindStyle::Move);
     s.underscore_const(true);
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index ceff1da9763..886a38c8ff2 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -307,7 +307,7 @@ fn add_query_desc_cached_impl(
     });
 }
 
-pub fn rustc_queries(input: TokenStream) -> TokenStream {
+pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
     let queries = parse_macro_input!(input as List<Query>);
 
     let mut query_stream = quote! {};
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index 7b5dd1601c1..2c33a0ac0aa 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -3,7 +3,9 @@ use quote::{quote, quote_spanned};
 use syn::parse_quote;
 use syn::spanned::Spanned;
 
-pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn type_decodable_derive(
+    mut s: synstructure::Structure<'_>,
+) -> proc_macro2::TokenStream {
     let decoder_ty = quote! { __D };
     let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
         quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
@@ -20,7 +22,9 @@ pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
     decodable_body(s, decoder_ty)
 }
 
-pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn meta_decodable_derive(
+    mut s: synstructure::Structure<'_>,
+) -> proc_macro2::TokenStream {
     if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
         s.add_impl_generic(parse_quote! { 'tcx });
     }
@@ -32,7 +36,7 @@ pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
     decodable_body(s, decoder_ty)
 }
 
-pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     let decoder_ty = quote! { __D };
     s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_span::SpanDecoder });
     s.add_bounds(synstructure::AddBounds::Generics);
@@ -41,7 +45,9 @@ pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke
     decodable_body(s, decoder_ty)
 }
 
-pub fn decodable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn decodable_generic_derive(
+    mut s: synstructure::Structure<'_>,
+) -> proc_macro2::TokenStream {
     let decoder_ty = quote! { __D };
     s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_serialize::Decoder });
     s.add_bounds(synstructure::AddBounds::Generics);
@@ -123,7 +129,9 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream {
     quote_spanned! { field_span=> #decode_inner_method(#__decoder) }
 }
 
-pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn type_encodable_derive(
+    mut s: synstructure::Structure<'_>,
+) -> proc_macro2::TokenStream {
     let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
         quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
     } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") {
@@ -140,7 +148,9 @@ pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
     encodable_body(s, encoder_ty, false)
 }
 
-pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn meta_encodable_derive(
+    mut s: synstructure::Structure<'_>,
+) -> proc_macro2::TokenStream {
     if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
         s.add_impl_generic(parse_quote! { 'tcx });
     }
@@ -152,7 +162,7 @@ pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
     encodable_body(s, encoder_ty, true)
 }
 
-pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     let encoder_ty = quote! { __E };
     s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_span::SpanEncoder });
     s.add_bounds(synstructure::AddBounds::Generics);
@@ -161,7 +171,9 @@ pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke
     encodable_body(s, encoder_ty, false)
 }
 
-pub fn encodable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn encodable_generic_derive(
+    mut s: synstructure::Structure<'_>,
+) -> proc_macro2::TokenStream {
     let encoder_ty = quote! { __E };
     s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder });
     s.add_bounds(synstructure::AddBounds::Generics);
diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs
index 6074c93d59c..341186ac1ca 100644
--- a/compiler/rustc_macros/src/symbols.rs
+++ b/compiler/rustc_macros/src/symbols.rs
@@ -131,7 +131,7 @@ impl Errors {
     }
 }
 
-pub fn symbols(input: TokenStream) -> TokenStream {
+pub(super) fn symbols(input: TokenStream) -> TokenStream {
     let (mut output, errors) = symbols_with_errors(input);
 
     // If we generated any errors, then report them as compiler_error!() macro calls.
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index 5617c53b119..8ddfa96e095 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -1,7 +1,7 @@
 use quote::{quote, ToTokens};
 use syn::parse_quote;
 
-pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
         panic!("cannot derive on union")
     }
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index 94e86e0e246..527ca26c0eb 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -1,7 +1,9 @@
 use quote::quote;
 use syn::parse_quote;
 
-pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+pub(super) fn type_visitable_derive(
+    mut s: synstructure::Structure<'_>,
+) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
         panic!("cannot derive on union")
     }
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index acaf9fb0fc3..c798ca00bcc 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -16,6 +16,7 @@
 #![feature(proc_macro_internals)]
 #![feature(rustdoc_internals)]
 #![feature(trusted_len)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 extern crate proc_macro;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 7321e2c760c..09aea233718 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -56,13 +56,13 @@ impl std::ops::Deref for MetadataBlob {
 
 impl MetadataBlob {
     /// Runs the [`MemDecoder`] validation and if it passes, constructs a new [`MetadataBlob`].
-    pub fn new(slice: OwnedSlice) -> Result<Self, ()> {
+    pub(crate) fn new(slice: OwnedSlice) -> Result<Self, ()> {
         if MemDecoder::new(&slice, 0).is_ok() { Ok(Self(slice)) } else { Err(()) }
     }
 
     /// Since this has passed the validation of [`MetadataBlob::new`], this returns bytes which are
     /// known to pass the [`MemDecoder`] validation.
-    pub fn bytes(&self) -> &OwnedSlice {
+    pub(crate) fn bytes(&self) -> &OwnedSlice {
         &self.0
     }
 }
@@ -332,12 +332,12 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
     }
 
     #[inline]
-    pub fn blob(&self) -> &'a MetadataBlob {
+    pub(crate) fn blob(&self) -> &'a MetadataBlob {
         self.blob
     }
 
     #[inline]
-    pub fn cdata(&self) -> CrateMetadataRef<'a> {
+    fn cdata(&self) -> CrateMetadataRef<'a> {
         debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext");
         self.cdata.unwrap()
     }
@@ -377,7 +377,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
     }
 
     #[inline]
-    pub fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
+    fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
         self.opaque.read_raw_bytes(len)
     }
 }
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 01fbf37788f..19369425f81 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -17,7 +17,7 @@ parameterized_over_tcx! {
 
 impl DefPathHashMapRef<'_> {
     #[inline]
-    pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex {
+    pub(crate) fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex {
         match *self {
             DefPathHashMapRef::OwnedFromMetadata(ref map) => {
                 map.get(&def_path_hash.local_hash()).unwrap()
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index fbcfbd3befa..d9a844ad837 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2309,7 +2309,7 @@ fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Erro
     Ok(())
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         doc_link_resolutions: |tcx, def_id| {
             tcx.resolutions(())
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 9ebe4a57b02..2d47d1d19af 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -61,8 +61,9 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LO
 use rustc_hir::definitions::DefPathHash;
 use rustc_hir::{HirId, ItemLocalId, OwnerId};
 pub use rustc_query_system::dep_graph::dep_node::DepKind;
+pub use rustc_query_system::dep_graph::DepNode;
 use rustc_query_system::dep_graph::FingerprintStyle;
-pub use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams};
+pub(crate) use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
 use rustc_span::symbol::Symbol;
 
 use crate::mir::mono::MonoItem;
@@ -101,7 +102,7 @@ macro_rules! define_dep_nodes {
 
         // This checks that the discriminants of the variants have been assigned consecutively
         // from 0 so that they can be used as a dense index.
-        pub const DEP_KIND_VARIANTS: u16 = {
+        pub(crate) const DEP_KIND_VARIANTS: u16 = {
             let deps = &[$(dep_kinds::$variant,)*];
             let mut i = 0;
             while i < deps.len() {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 32f79ff7234..2a85f85a9f4 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -62,6 +62,7 @@
 #![feature(try_blocks)]
 #![feature(type_alias_impl_trait)]
 #![feature(yeet_expr)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 #[cfg(test)]
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index c08bfc1fa95..183b898253e 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -18,9 +18,9 @@ pub struct BasicBlocks<'tcx> {
 }
 
 // Typically 95%+ of basic blocks have 4 or fewer predecessors.
-pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
+type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
 
-pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
+type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
 
 #[derive(Clone, Default, Debug)]
 struct Cache {
diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs
index 51e26ab7984..a52ec58a1ee 100644
--- a/compiler/rustc_middle/src/mir/generic_graph.rs
+++ b/compiler/rustc_middle/src/mir/generic_graph.rs
@@ -2,7 +2,7 @@ use gsgdt::{Edge, Graph, Node, NodeStyle};
 use rustc_middle::mir::*;
 
 /// Convert an MIR function into a gsgdt Graph
-pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph {
+pub(crate) fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph {
     let def_id = body.source.def_id();
     let def_name = graphviz_safe_def_name(def_id);
     let graph_name = format!("Mir_{def_name}");
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index 1d2a82c575a..dfaf96e14f6 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -243,7 +243,7 @@ impl hash::Hash for InitMaskMaterialized {
 }
 
 impl InitMaskMaterialized {
-    pub const BLOCK_SIZE: u64 = 64;
+    const BLOCK_SIZE: u64 = 64;
 
     fn new(size: Size, state: bool) -> Self {
         let mut m = InitMaskMaterialized { blocks: vec![] };
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1d94c364ae3..69b5e0a79c7 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -396,7 +396,7 @@ impl<'tcx> CodegenUnit<'tcx> {
         // The codegen tests rely on items being process in the same order as
         // they appear in the file, so for local items, we sort by node_id first
         #[derive(PartialEq, Eq, PartialOrd, Ord)]
-        pub struct ItemSortKey<'tcx>(Option<usize>, SymbolName<'tcx>);
+        struct ItemSortKey<'tcx>(Option<usize>, SymbolName<'tcx>);
 
         fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> {
             ItemSortKey(
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8effb67a1f6..70df205d893 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2190,7 +2190,7 @@ macro_rules! sty_debug_print {
                 all_infer: usize,
             }
 
-            pub fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
+            pub(crate) fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
                 let mut total = DebugStat {
                     total: 0,
                     lt_infer: 0,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 60cd49b88b4..4ce796cea7a 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -1027,7 +1027,7 @@ impl UnsafeOpKind {
     }
 }
 
-pub fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
+pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
     // Closures and inline consts are handled by their owner, if it has a body
     // Also, don't safety check custom MIR
     if tcx.is_typeck_child(def.to_def_id()) || tcx.has_attr(def, sym::custom_mir) {
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 66004179b10..3dbb552cdbb 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -8,6 +8,7 @@
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(try_blocks)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod build;
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index 364a416480f..0bab03b0271 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -24,7 +24,7 @@ use crate::errors::{
 };
 use crate::framework::BitSetExt;
 
-pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>;
+type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>;
 
 /// A dataflow analysis that has converged to fixpoint.
 #[derive(Clone)]
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 6eaed0f7753..6da3a20dc02 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -510,7 +510,7 @@ impl<T: Idx> GenKill<T> for lattice::Dual<BitSet<T>> {
 
 // NOTE: DO NOT CHANGE VARIANT ORDER. The derived `Ord` impls rely on the current order.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub enum Effect {
+enum Effect {
     /// The "before" effect (e.g., `apply_before_statement_effect`) for a statement (or
     /// terminator).
     Before,
@@ -520,7 +520,7 @@ pub enum Effect {
 }
 
 impl Effect {
-    pub const fn at_index(self, statement_index: usize) -> EffectIndex {
+    const fn at_index(self, statement_index: usize) -> EffectIndex {
         EffectIndex { effect: self, statement_index }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 8708bebeeb0..9385b52103f 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(exact_size_is_empty)]
 #![feature(let_chains)]
 #![feature(try_blocks)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_middle::ty;
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
index 2a7f23ef6d2..df4c0593246 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
@@ -15,12 +15,12 @@ use rustc_middle::mir::{Local, Operand, PlaceElem, ProjectionElem};
 use rustc_middle::ty::Ty;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub struct AbstractOperand;
+pub(crate) struct AbstractOperand;
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub struct AbstractType;
-pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
+pub(crate) struct AbstractType;
+pub(crate) type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
 
-pub trait Lift {
+pub(crate) trait Lift {
     type Abstract;
     fn lift(&self) -> Self::Abstract;
 }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 36fb2e89af1..9c820b888d9 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -242,12 +242,12 @@ use tracing::{debug, instrument, trace};
 use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit};
 
 #[derive(PartialEq)]
-pub enum MonoItemCollectionStrategy {
+pub(crate) enum MonoItemCollectionStrategy {
     Eager,
     Lazy,
 }
 
-pub struct UsageMap<'tcx> {
+pub(crate) struct UsageMap<'tcx> {
     // Maps every mono item to the mono items used by it.
     used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
 
@@ -306,13 +306,17 @@ impl<'tcx> UsageMap<'tcx> {
         assert!(self.used_map.insert(user_item, used_items).is_none());
     }
 
-    pub fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] {
+    pub(crate) fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] {
         self.user_map.get(&item).map(|items| items.as_slice()).unwrap_or(&[])
     }
 
     /// Internally iterate over all inlined items used by `item`.
-    pub fn for_each_inlined_used_item<F>(&self, tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>, mut f: F)
-    where
+    pub(crate) fn for_each_inlined_used_item<F>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        item: MonoItem<'tcx>,
+        mut f: F,
+    ) where
         F: FnMut(MonoItem<'tcx>),
     {
         let used_items = self.used_map.get(&item).unwrap();
@@ -1615,6 +1619,6 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
     (mono_items, state.usage_map.into_inner())
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.hooks.should_codegen_locally = should_codegen_locally;
 }
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index c97e07ee3ba..d5fae6e23cb 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -8,7 +8,7 @@ use crate::fluent_generated as fluent;
 
 #[derive(Diagnostic)]
 #[diag(monomorphize_recursion_limit)]
-pub struct RecursionLimit {
+pub(crate) struct RecursionLimit {
     #[primary_span]
     pub span: Span,
     pub shrunk: String,
@@ -22,13 +22,13 @@ pub struct RecursionLimit {
 
 #[derive(Diagnostic)]
 #[diag(monomorphize_no_optimized_mir)]
-pub struct NoOptimizedMir {
+pub(crate) struct NoOptimizedMir {
     #[note]
     pub span: Span,
     pub crate_name: Symbol,
 }
 
-pub struct UnusedGenericParamsHint {
+pub(crate) struct UnusedGenericParamsHint {
     pub span: Span,
     pub param_spans: Vec<Span>,
     pub param_names: Vec<String>,
@@ -53,7 +53,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for UnusedGenericParamsHint {
 #[derive(LintDiagnostic)]
 #[diag(monomorphize_large_assignments)]
 #[note]
-pub struct LargeAssignmentsLint {
+pub(crate) struct LargeAssignmentsLint {
     #[label]
     pub span: Span,
     pub size: u64,
@@ -62,7 +62,7 @@ pub struct LargeAssignmentsLint {
 
 #[derive(Diagnostic)]
 #[diag(monomorphize_symbol_already_defined)]
-pub struct SymbolAlreadyDefined {
+pub(crate) struct SymbolAlreadyDefined {
     #[primary_span]
     pub span: Option<Span>,
     pub symbol: String,
@@ -70,13 +70,13 @@ pub struct SymbolAlreadyDefined {
 
 #[derive(Diagnostic)]
 #[diag(monomorphize_couldnt_dump_mono_stats)]
-pub struct CouldntDumpMonoStats {
+pub(crate) struct CouldntDumpMonoStats {
     pub error: String,
 }
 
 #[derive(Diagnostic)]
 #[diag(monomorphize_encountered_error_while_instantiating)]
-pub struct EncounteredErrorWhileInstantiating {
+pub(crate) struct EncounteredErrorWhileInstantiating {
     #[primary_span]
     pub span: Span,
     pub formatted_item: String,
@@ -85,10 +85,10 @@ pub struct EncounteredErrorWhileInstantiating {
 #[derive(Diagnostic)]
 #[diag(monomorphize_start_not_found)]
 #[help]
-pub struct StartNotFound;
+pub(crate) struct StartNotFound;
 
 #[derive(Diagnostic)]
 #[diag(monomorphize_unknown_cgu_collection_mode)]
-pub struct UnknownCguCollectionMode<'a> {
+pub(crate) struct UnknownCguCollectionMode<'a> {
     pub mode: &'a str,
 }
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index d6b0f9c4d28..b22e8e30465 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,5 +1,6 @@
 // tidy-alphabetical-start
 #![feature(array_windows)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_hir::lang_items::LangItem;
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 2f0088fb34f..0d295b8f280 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -1300,7 +1300,7 @@ fn dump_mono_items_stats<'tcx>(
     Ok(())
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
 
     providers.is_codegened_item = |tcx, def_id| {
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index b59c7bcffa9..c65ad9fa67e 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -19,7 +19,7 @@ use tracing::{debug, instrument};
 use crate::errors::UnusedGenericParamsHint;
 
 /// Provide implementations of queries relating to polymorphization analysis.
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.unused_generic_params = unused_generic_params;
 }
 
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index 0a5b4278058..ea244b5107a 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -4,6 +4,10 @@
 //! but were uplifted in the process of making the new trait solver generic.
 //! So if you got to this crate from the old solver, it's totally normal.
 
+// tidy-alphabetical-start
+#![warn(unreachable_pub)]
+// tidy-alphabetical-end
+
 pub mod canonicalizer;
 pub mod coherence;
 pub mod delegate;
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index e328284c001..3f2f34d3255 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -92,7 +92,7 @@ where
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 // FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate.
-pub struct NestedGoals<I: Interner> {
+struct NestedGoals<I: Interner> {
     /// These normalizes-to goals are treated specially during the evaluation
     /// loop. In each iteration we take the RHS of the projection, replace it with
     /// a fresh inference variable, and only after evaluating that goal do we
@@ -109,11 +109,11 @@ pub struct NestedGoals<I: Interner> {
 }
 
 impl<I: Interner> NestedGoals<I> {
-    pub fn new() -> Self {
+    fn new() -> Self {
         Self { normalizes_to_goals: Vec::new(), goals: Vec::new() }
     }
 
-    pub fn is_empty(&self) -> bool {
+    fn is_empty(&self) -> bool {
         self.normalizes_to_goals.is_empty() && self.goals.is_empty()
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
index 86fb036cd3d..742d45de7d3 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -222,13 +222,13 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         self.state.as_deref_mut()
     }
 
-    pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<D> {
+    pub(crate) fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<D> {
         let mut nested = ProofTreeBuilder { state: self.state.take(), _infcx: PhantomData };
         nested.enter_probe();
         nested
     }
 
-    pub fn finalize(self) -> Option<inspect::GoalEvaluation<I>> {
+    pub(crate) fn finalize(self) -> Option<inspect::GoalEvaluation<I>> {
         match *self.state? {
             DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
                 Some(wip_goal_evaluation.finalize())
@@ -237,22 +237,22 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<D> {
+    pub(crate) fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<D> {
         match generate_proof_tree {
             GenerateProofTree::No => ProofTreeBuilder::new_noop(),
             GenerateProofTree::Yes => ProofTreeBuilder::new_root(),
         }
     }
 
-    pub fn new_root() -> ProofTreeBuilder<D> {
+    fn new_root() -> ProofTreeBuilder<D> {
         ProofTreeBuilder::new(DebugSolver::Root)
     }
 
-    pub fn new_noop() -> ProofTreeBuilder<D> {
+    fn new_noop() -> ProofTreeBuilder<D> {
         ProofTreeBuilder { state: None, _infcx: PhantomData }
     }
 
-    pub fn is_noop(&self) -> bool {
+    pub(crate) fn is_noop(&self) -> bool {
         self.state.is_none()
     }
 
@@ -272,7 +272,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         })
     }
 
-    pub fn new_canonical_goal_evaluation(
+    pub(crate) fn new_canonical_goal_evaluation(
         &mut self,
         goal: CanonicalInput<I>,
     ) -> ProofTreeBuilder<D> {
@@ -284,7 +284,10 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         })
     }
 
-    pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<D>) {
+    pub(crate) fn canonical_goal_evaluation(
+        &mut self,
+        canonical_goal_evaluation: ProofTreeBuilder<D>,
+    ) {
         if let Some(this) = self.as_mut() {
             match (this, *canonical_goal_evaluation.state.unwrap()) {
                 (
@@ -299,7 +302,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn canonical_goal_evaluation_overflow(&mut self) {
+    pub(crate) fn canonical_goal_evaluation_overflow(&mut self) {
         if let Some(this) = self.as_mut() {
             match this {
                 DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
@@ -310,7 +313,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<D>) {
+    pub(crate) fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<D>) {
         if let Some(this) = self.as_mut() {
             match this {
                 DebugSolver::Root => *this = *goal_evaluation.state.unwrap(),
@@ -322,7 +325,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn new_goal_evaluation_step(
+    pub(crate) fn new_goal_evaluation_step(
         &mut self,
         var_values: ty::CanonicalVarValues<I>,
         instantiated_goal: QueryInput<I, I::Predicate>,
@@ -340,7 +343,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         })
     }
 
-    pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<D>) {
+    pub(crate) fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<D>) {
         if let Some(this) = self.as_mut() {
             match (this, *goal_evaluation_step.state.unwrap()) {
                 (
@@ -354,7 +357,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) {
+    pub(crate) fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) {
         match self.as_mut() {
             None => {}
             Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
@@ -364,7 +367,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn enter_probe(&mut self) {
+    fn enter_probe(&mut self) {
         match self.as_mut() {
             None => {}
             Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
@@ -381,7 +384,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<I>) {
+    pub(crate) fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<I>) {
         match self.as_mut() {
             None => {}
             Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
@@ -392,7 +395,11 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn probe_final_state(&mut self, delegate: &D, max_input_universe: ty::UniverseIndex) {
+    pub(crate) fn probe_final_state(
+        &mut self,
+        delegate: &D,
+        max_input_universe: ty::UniverseIndex,
+    ) {
         match self.as_mut() {
             None => {}
             Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
@@ -409,7 +416,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn add_normalizes_to_goal(
+    pub(crate) fn add_normalizes_to_goal(
         &mut self,
         delegate: &D,
         max_input_universe: ty::UniverseIndex,
@@ -423,7 +430,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         );
     }
 
-    pub fn add_goal(
+    pub(crate) fn add_goal(
         &mut self,
         delegate: &D,
         max_input_universe: ty::UniverseIndex,
@@ -469,7 +476,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
+    pub(crate) fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
         match self.as_mut() {
             Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
                 state
@@ -482,7 +489,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         }
     }
 
-    pub fn finish_probe(mut self) -> ProofTreeBuilder<D> {
+    pub(crate) fn finish_probe(mut self) -> ProofTreeBuilder<D> {
         match self.as_mut() {
             None => {}
             Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
@@ -497,7 +504,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         self
     }
 
-    pub fn query_result(&mut self, result: QueryResult<I>) {
+    pub(crate) fn query_result(&mut self, result: QueryResult<I>) {
         if let Some(this) = self.as_mut() {
             match this {
                 DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index 120f96d24bd..6a0703c5313 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -97,7 +97,7 @@ where
 /// Checks whether each generic argument is simply a unique generic placeholder.
 ///
 /// FIXME: Interner argument is needed to constrain the `I` parameter.
-pub fn uses_unique_placeholders_ignoring_regions<I: Interner>(
+fn uses_unique_placeholders_ignoring_regions<I: Interner>(
     _cx: I,
     args: I::GenericArgs,
 ) -> Result<(), NotUniqueParam<I>> {
@@ -130,7 +130,7 @@ pub fn uses_unique_placeholders_ignoring_regions<I: Interner>(
 }
 
 // FIXME: This should check for dupes and non-params first, then infer vars.
-pub enum NotUniqueParam<I: Interner> {
+enum NotUniqueParam<I: Interner> {
     DuplicateParam(I::GenericArg),
     NotParam(I::GenericArg),
 }
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index abaff7d9c19..da1103a4fe5 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -260,7 +260,7 @@ pub(crate) struct NotAsNegationOperator {
 }
 
 #[derive(Subdiagnostic)]
-pub enum NotAsNegationOperatorSub {
+pub(crate) enum NotAsNegationOperatorSub {
     #[suggestion(
         parse_unexpected_token_after_not_default,
         style = "verbose",
@@ -424,7 +424,7 @@ pub(crate) enum IfExpressionMissingThenBlockSub {
 #[derive(Diagnostic)]
 #[diag(parse_ternary_operator)]
 #[help]
-pub struct TernaryOperator {
+pub(crate) struct TernaryOperator {
     #[primary_span]
     pub span: Span,
 }
@@ -1088,7 +1088,7 @@ pub(crate) enum ExpectedIdentifierFound {
 }
 
 impl ExpectedIdentifierFound {
-    pub fn new(token_descr: Option<TokenDescription>, span: Span) -> Self {
+    pub(crate) fn new(token_descr: Option<TokenDescription>, span: Span) -> Self {
         (match token_descr {
             Some(TokenDescription::ReservedIdentifier) => {
                 ExpectedIdentifierFound::ReservedIdentifier
@@ -1659,7 +1659,7 @@ pub(crate) struct SelfArgumentPointer {
 
 #[derive(Diagnostic)]
 #[diag(parse_unexpected_token_after_dot)]
-pub struct UnexpectedTokenAfterDot<'a> {
+pub(crate) struct UnexpectedTokenAfterDot<'a> {
     #[primary_span]
     pub span: Span,
     pub actual: Cow<'a, str>,
@@ -1928,7 +1928,7 @@ pub(crate) enum UnexpectedTokenAfterStructName {
 }
 
 impl UnexpectedTokenAfterStructName {
-    pub fn new(span: Span, token: Token) -> Self {
+    pub(crate) fn new(span: Span, token: Token) -> Self {
         match TokenDescription::from_token(&token) {
             Some(TokenDescription::ReservedIdentifier) => Self::ReservedIdentifier { span, token },
             Some(TokenDescription::Keyword) => Self::Keyword { span, token },
@@ -2006,7 +2006,7 @@ pub(crate) enum TopLevelOrPatternNotAllowed {
 
 #[derive(Diagnostic)]
 #[diag(parse_cannot_be_raw_ident)]
-pub struct CannotBeRawIdent {
+pub(crate) struct CannotBeRawIdent {
     #[primary_span]
     pub span: Span,
     pub ident: Symbol,
@@ -2014,14 +2014,14 @@ pub struct CannotBeRawIdent {
 
 #[derive(Diagnostic)]
 #[diag(parse_keyword_lifetime)]
-pub struct KeywordLifetime {
+pub(crate) struct KeywordLifetime {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(parse_invalid_label)]
-pub struct InvalidLabel {
+pub(crate) struct InvalidLabel {
     #[primary_span]
     pub span: Span,
     pub name: Symbol,
@@ -2029,7 +2029,7 @@ pub struct InvalidLabel {
 
 #[derive(Diagnostic)]
 #[diag(parse_cr_doc_comment)]
-pub struct CrDocComment {
+pub(crate) struct CrDocComment {
     #[primary_span]
     pub span: Span,
     pub block: bool,
@@ -2037,14 +2037,14 @@ pub struct CrDocComment {
 
 #[derive(Diagnostic)]
 #[diag(parse_no_digits_literal, code = E0768)]
-pub struct NoDigitsLiteral {
+pub(crate) struct NoDigitsLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(parse_invalid_digit_literal)]
-pub struct InvalidDigitLiteral {
+pub(crate) struct InvalidDigitLiteral {
     #[primary_span]
     pub span: Span,
     pub base: u32,
@@ -2052,14 +2052,14 @@ pub struct InvalidDigitLiteral {
 
 #[derive(Diagnostic)]
 #[diag(parse_empty_exponent_float)]
-pub struct EmptyExponentFloat {
+pub(crate) struct EmptyExponentFloat {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(parse_float_literal_unsupported_base)]
-pub struct FloatLiteralUnsupportedBase {
+pub(crate) struct FloatLiteralUnsupportedBase {
     #[primary_span]
     pub span: Span,
     pub base: &'static str,
@@ -2068,7 +2068,7 @@ pub struct FloatLiteralUnsupportedBase {
 #[derive(Diagnostic)]
 #[diag(parse_unknown_prefix)]
 #[note]
-pub struct UnknownPrefix<'a> {
+pub(crate) struct UnknownPrefix<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -2079,12 +2079,12 @@ pub struct UnknownPrefix<'a> {
 
 #[derive(Subdiagnostic)]
 #[note(parse_macro_expands_to_adt_field)]
-pub struct MacroExpandsToAdtField<'a> {
+pub(crate) struct MacroExpandsToAdtField<'a> {
     pub adt_ty: &'a str,
 }
 
 #[derive(Subdiagnostic)]
-pub enum UnknownPrefixSugg {
+pub(crate) enum UnknownPrefixSugg {
     #[suggestion(
         parse_suggestion_br,
         code = "br",
@@ -2114,7 +2114,7 @@ pub enum UnknownPrefixSugg {
 
 #[derive(Diagnostic)]
 #[diag(parse_too_many_hashes)]
-pub struct TooManyHashes {
+pub(crate) struct TooManyHashes {
     #[primary_span]
     pub span: Span,
     pub num: u32,
@@ -2122,7 +2122,7 @@ pub struct TooManyHashes {
 
 #[derive(Diagnostic)]
 #[diag(parse_unknown_start_of_token)]
-pub struct UnknownTokenStart {
+pub(crate) struct UnknownTokenStart {
     #[primary_span]
     pub span: Span,
     pub escaped: String,
@@ -2135,7 +2135,7 @@ pub struct UnknownTokenStart {
 }
 
 #[derive(Subdiagnostic)]
-pub enum TokenSubstitution {
+pub(crate) enum TokenSubstitution {
     #[suggestion(
         parse_sugg_quotes,
         code = "{suggestion}",
@@ -2168,16 +2168,16 @@ pub enum TokenSubstitution {
 
 #[derive(Subdiagnostic)]
 #[note(parse_note_repeats)]
-pub struct UnknownTokenRepeat {
+pub(crate) struct UnknownTokenRepeat {
     pub repeats: usize,
 }
 
 #[derive(Subdiagnostic)]
 #[help(parse_help_null)]
-pub struct UnknownTokenNull;
+pub(crate) struct UnknownTokenNull;
 
 #[derive(Diagnostic)]
-pub enum UnescapeError {
+pub(crate) enum UnescapeError {
     #[diag(parse_invalid_unicode_escape)]
     #[help]
     InvalidUnicodeEscape {
@@ -2322,7 +2322,7 @@ pub enum UnescapeError {
 }
 
 #[derive(Subdiagnostic)]
-pub enum MoreThanOneCharSugg {
+pub(crate) enum MoreThanOneCharSugg {
     #[suggestion(
         parse_consider_normalized,
         code = "{normalized}",
@@ -2370,7 +2370,7 @@ pub enum MoreThanOneCharSugg {
 }
 
 #[derive(Subdiagnostic)]
-pub enum MoreThanOneCharNote {
+pub(crate) enum MoreThanOneCharNote {
     #[note(parse_followed_by)]
     AllCombining {
         #[primary_span]
@@ -2388,7 +2388,7 @@ pub enum MoreThanOneCharNote {
 }
 
 #[derive(Subdiagnostic)]
-pub enum NoBraceUnicodeSub {
+pub(crate) enum NoBraceUnicodeSub {
     #[suggestion(
         parse_use_braces,
         code = "{suggestion}",
@@ -2703,7 +2703,7 @@ pub(crate) struct InvalidDynKeyword {
 }
 
 #[derive(Subdiagnostic)]
-pub enum HelpUseLatestEdition {
+pub(crate) enum HelpUseLatestEdition {
     #[help(parse_help_set_edition_cargo)]
     #[note(parse_note_edition_guide)]
     Cargo { edition: Edition },
@@ -2713,7 +2713,7 @@ pub enum HelpUseLatestEdition {
 }
 
 impl HelpUseLatestEdition {
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         let edition = LATEST_STABLE_EDITION;
         if rustc_session::utils::was_invoked_from_cargo() {
             Self::Cargo { edition }
@@ -2725,7 +2725,7 @@ impl HelpUseLatestEdition {
 
 #[derive(Diagnostic)]
 #[diag(parse_box_syntax_removed)]
-pub struct BoxSyntaxRemoved {
+pub(crate) struct BoxSyntaxRemoved {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
@@ -2738,7 +2738,7 @@ pub struct BoxSyntaxRemoved {
     applicability = "machine-applicable",
     style = "verbose"
 )]
-pub struct AddBoxNew {
+pub(crate) struct AddBoxNew {
     #[suggestion_part(code = "Box::new(")]
     pub box_kw_and_lo: Span,
     #[suggestion_part(code = ")")]
@@ -3190,7 +3190,7 @@ pub(crate) struct DotDotRangeAttribute {
 #[derive(Diagnostic)]
 #[diag(parse_invalid_attr_unsafe)]
 #[note]
-pub struct InvalidAttrUnsafe {
+pub(crate) struct InvalidAttrUnsafe {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -3199,7 +3199,7 @@ pub struct InvalidAttrUnsafe {
 
 #[derive(Diagnostic)]
 #[diag(parse_unsafe_attr_outside_unsafe)]
-pub struct UnsafeAttrOutsideUnsafe {
+pub(crate) struct UnsafeAttrOutsideUnsafe {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -3212,7 +3212,7 @@ pub struct UnsafeAttrOutsideUnsafe {
     parse_unsafe_attr_outside_unsafe_suggestion,
     applicability = "machine-applicable"
 )]
-pub struct UnsafeAttrOutsideUnsafeSuggestion {
+pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
     #[suggestion_part(code = "unsafe(")]
     pub left: Span,
     #[suggestion_part(code = ")")]
@@ -3221,7 +3221,7 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion {
 
 #[derive(Diagnostic)]
 #[diag(parse_binder_before_modifiers)]
-pub struct BinderBeforeModifiers {
+pub(crate) struct BinderBeforeModifiers {
     #[primary_span]
     pub binder_span: Span,
     #[label]
@@ -3230,7 +3230,7 @@ pub struct BinderBeforeModifiers {
 
 #[derive(Diagnostic)]
 #[diag(parse_binder_and_polarity)]
-pub struct BinderAndPolarity {
+pub(crate) struct BinderAndPolarity {
     #[primary_span]
     pub polarity_span: Span,
     #[label]
@@ -3240,7 +3240,7 @@ pub struct BinderAndPolarity {
 
 #[derive(Diagnostic)]
 #[diag(parse_modifiers_and_polarity)]
-pub struct PolarityAndModifiers {
+pub(crate) struct PolarityAndModifiers {
     #[primary_span]
     pub polarity_span: Span,
     #[label]
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 37079271493..788bb732ef7 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -11,6 +11,7 @@
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::path::Path;
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index cb758150789..51084ef4441 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -13,6 +13,7 @@
     html_playground_url = "https://play.rust-lang.org/",
     test(attr(deny(warnings)))
 )]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::{iter, str, string};
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 5d871bacb1d..fec149c8c43 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -95,6 +95,6 @@ fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualize
     visitor.visualizers
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.debugger_visualizers = debugger_visualizers;
 }
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 624ebb2f9f2..425e203f2b0 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -90,7 +90,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems {
     items
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.diagnostic_items = diagnostic_items;
     providers.all_diagnostic_items = all_diagnostic_items;
 }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 32db0823cf7..1e9ab7af9be 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -18,41 +18,41 @@ use crate::lang_items::Duplicate;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_incorrect_do_not_recommend_location)]
-pub struct IncorrectDoNotRecommendLocation;
+pub(crate) struct IncorrectDoNotRecommendLocation;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_outer_crate_level_attr)]
-pub struct OuterCrateLevelAttr;
+pub(crate) struct OuterCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_inner_crate_level_attr)]
-pub struct InnerCrateLevelAttr;
+pub(crate) struct InnerCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_ignored_attr_with_macro)]
-pub struct IgnoredAttrWithMacro<'a> {
+pub(crate) struct IgnoredAttrWithMacro<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_ignored_attr)]
-pub struct IgnoredAttr<'a> {
+pub(crate) struct IgnoredAttr<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_inline_ignored_function_prototype)]
-pub struct IgnoredInlineAttrFnProto;
+pub(crate) struct IgnoredInlineAttrFnProto;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_inline_ignored_constants)]
 #[warning]
 #[note]
-pub struct IgnoredInlineAttrConstants;
+pub(crate) struct IgnoredInlineAttrConstants;
 
 #[derive(Diagnostic)]
 #[diag(passes_inline_not_fn_or_closure, code = E0518)]
-pub struct InlineNotFnOrClosure {
+pub(crate) struct InlineNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -61,7 +61,7 @@ pub struct InlineNotFnOrClosure {
 
 #[derive(Diagnostic)]
 #[diag(passes_coverage_not_fn_or_closure, code = E0788)]
-pub struct CoverageNotFnOrClosure {
+pub(crate) struct CoverageNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -70,11 +70,11 @@ pub struct CoverageNotFnOrClosure {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_optimize_not_fn_or_closure)]
-pub struct OptimizeNotFnOrClosure;
+pub(crate) struct OptimizeNotFnOrClosure;
 
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_fn)]
-pub struct AttrShouldBeAppliedToFn {
+pub(crate) struct AttrShouldBeAppliedToFn {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -84,7 +84,7 @@ pub struct AttrShouldBeAppliedToFn {
 
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_fn_or_unit_struct)]
-pub struct AttrShouldBeAppliedToFnOrUnitStruct {
+pub(crate) struct AttrShouldBeAppliedToFnOrUnitStruct {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -93,7 +93,7 @@ pub struct AttrShouldBeAppliedToFnOrUnitStruct {
 
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_fn, code = E0739)]
-pub struct TrackedCallerWrongLocation {
+pub(crate) struct TrackedCallerWrongLocation {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -103,7 +103,7 @@ pub struct TrackedCallerWrongLocation {
 
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_struct_enum, code = E0701)]
-pub struct NonExhaustiveWrongLocation {
+pub(crate) struct NonExhaustiveWrongLocation {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -112,7 +112,7 @@ pub struct NonExhaustiveWrongLocation {
 
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_trait)]
-pub struct AttrShouldBeAppliedToTrait {
+pub(crate) struct AttrShouldBeAppliedToTrait {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -121,11 +121,11 @@ pub struct AttrShouldBeAppliedToTrait {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_target_feature_on_statement)]
-pub struct TargetFeatureOnStatement;
+pub(crate) struct TargetFeatureOnStatement;
 
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_static)]
-pub struct AttrShouldBeAppliedToStatic {
+pub(crate) struct AttrShouldBeAppliedToStatic {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -134,7 +134,7 @@ pub struct AttrShouldBeAppliedToStatic {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_expect_str)]
-pub struct DocExpectStr<'a> {
+pub(crate) struct DocExpectStr<'a> {
     #[primary_span]
     pub attr_span: Span,
     pub attr_name: &'a str,
@@ -142,7 +142,7 @@ pub struct DocExpectStr<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_alias_empty)]
-pub struct DocAliasEmpty<'a> {
+pub(crate) struct DocAliasEmpty<'a> {
     #[primary_span]
     pub span: Span,
     pub attr_str: &'a str,
@@ -150,7 +150,7 @@ pub struct DocAliasEmpty<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_alias_bad_char)]
-pub struct DocAliasBadChar<'a> {
+pub(crate) struct DocAliasBadChar<'a> {
     #[primary_span]
     pub span: Span,
     pub attr_str: &'a str,
@@ -159,7 +159,7 @@ pub struct DocAliasBadChar<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_alias_start_end)]
-pub struct DocAliasStartEnd<'a> {
+pub(crate) struct DocAliasStartEnd<'a> {
     #[primary_span]
     pub span: Span,
     pub attr_str: &'a str,
@@ -167,7 +167,7 @@ pub struct DocAliasStartEnd<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_alias_bad_location)]
-pub struct DocAliasBadLocation<'a> {
+pub(crate) struct DocAliasBadLocation<'a> {
     #[primary_span]
     pub span: Span,
     pub attr_str: &'a str,
@@ -176,7 +176,7 @@ pub struct DocAliasBadLocation<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_alias_not_an_alias)]
-pub struct DocAliasNotAnAlias<'a> {
+pub(crate) struct DocAliasNotAnAlias<'a> {
     #[primary_span]
     pub span: Span,
     pub attr_str: &'a str,
@@ -184,42 +184,42 @@ pub struct DocAliasNotAnAlias<'a> {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_alias_duplicated)]
-pub struct DocAliasDuplicated {
+pub(crate) struct DocAliasDuplicated {
     #[label]
     pub first_defn: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_alias_not_string_literal)]
-pub struct DocAliasNotStringLiteral {
+pub(crate) struct DocAliasNotStringLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_alias_malformed)]
-pub struct DocAliasMalformed {
+pub(crate) struct DocAliasMalformed {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_keyword_empty_mod)]
-pub struct DocKeywordEmptyMod {
+pub(crate) struct DocKeywordEmptyMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_keyword_not_mod)]
-pub struct DocKeywordNotMod {
+pub(crate) struct DocKeywordNotMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_keyword_invalid_ident)]
-pub struct DocKeywordInvalidIdent {
+pub(crate) struct DocKeywordInvalidIdent {
     #[primary_span]
     pub span: Span,
     pub doc_keyword: Symbol,
@@ -227,14 +227,14 @@ pub struct DocKeywordInvalidIdent {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_fake_variadic_not_valid)]
-pub struct DocFakeVariadicNotValid {
+pub(crate) struct DocFakeVariadicNotValid {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_keyword_only_impl)]
-pub struct DocKeywordOnlyImpl {
+pub(crate) struct DocKeywordOnlyImpl {
     #[primary_span]
     pub span: Span,
 }
@@ -242,7 +242,7 @@ pub struct DocKeywordOnlyImpl {
 #[derive(Diagnostic)]
 #[diag(passes_doc_inline_conflict)]
 #[help]
-pub struct DocKeywordConflict {
+pub(crate) struct DocKeywordConflict {
     #[primary_span]
     pub spans: MultiSpan,
 }
@@ -250,7 +250,7 @@ pub struct DocKeywordConflict {
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_inline_only_use)]
 #[note]
-pub struct DocInlineOnlyUse {
+pub(crate) struct DocInlineOnlyUse {
     #[label]
     pub attr_span: Span,
     #[label(passes_not_a_use_item_label)]
@@ -260,7 +260,7 @@ pub struct DocInlineOnlyUse {
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_masked_only_extern_crate)]
 #[note]
-pub struct DocMaskedOnlyExternCrate {
+pub(crate) struct DocMaskedOnlyExternCrate {
     #[label]
     pub attr_span: Span,
     #[label(passes_not_an_extern_crate_label)]
@@ -269,7 +269,7 @@ pub struct DocMaskedOnlyExternCrate {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_masked_not_extern_crate_self)]
-pub struct DocMaskedNotExternCrateSelf {
+pub(crate) struct DocMaskedNotExternCrateSelf {
     #[label]
     pub attr_span: Span,
     #[label(passes_extern_crate_self_label)]
@@ -278,7 +278,7 @@ pub struct DocMaskedNotExternCrateSelf {
 
 #[derive(Diagnostic)]
 #[diag(passes_doc_attr_not_crate_level)]
-pub struct DocAttrNotCrateLevel<'a> {
+pub(crate) struct DocAttrNotCrateLevel<'a> {
     #[primary_span]
     pub span: Span,
     pub attr_name: &'a str,
@@ -286,25 +286,25 @@ pub struct DocAttrNotCrateLevel<'a> {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_test_unknown)]
-pub struct DocTestUnknown {
+pub(crate) struct DocTestUnknown {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_test_literal)]
-pub struct DocTestLiteral;
+pub(crate) struct DocTestLiteral;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_test_takes_list)]
-pub struct DocTestTakesList;
+pub(crate) struct DocTestTakesList;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_cfg_hide_takes_list)]
-pub struct DocCfgHideTakesList;
+pub(crate) struct DocCfgHideTakesList;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_test_unknown_any)]
-pub struct DocTestUnknownAny {
+pub(crate) struct DocTestUnknownAny {
     pub path: String,
 }
 
@@ -312,7 +312,7 @@ pub struct DocTestUnknownAny {
 #[diag(passes_doc_test_unknown_spotlight)]
 #[note]
 #[note(passes_no_op_note)]
-pub struct DocTestUnknownSpotlight {
+pub(crate) struct DocTestUnknownSpotlight {
     pub path: String,
     #[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")]
     pub span: Span,
@@ -320,7 +320,7 @@ pub struct DocTestUnknownSpotlight {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_test_unknown_include)]
-pub struct DocTestUnknownInclude {
+pub(crate) struct DocTestUnknownInclude {
     pub path: String,
     pub value: String,
     pub inner: &'static str,
@@ -330,11 +330,11 @@ pub struct DocTestUnknownInclude {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_doc_invalid)]
-pub struct DocInvalid;
+pub(crate) struct DocInvalid;
 
 #[derive(Diagnostic)]
 #[diag(passes_pass_by_value)]
-pub struct PassByValue {
+pub(crate) struct PassByValue {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -343,7 +343,7 @@ pub struct PassByValue {
 
 #[derive(Diagnostic)]
 #[diag(passes_allow_incoherent_impl)]
-pub struct AllowIncoherentImpl {
+pub(crate) struct AllowIncoherentImpl {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -352,7 +352,7 @@ pub struct AllowIncoherentImpl {
 
 #[derive(Diagnostic)]
 #[diag(passes_has_incoherent_inherent_impl)]
-pub struct HasIncoherentInherentImpl {
+pub(crate) struct HasIncoherentInherentImpl {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -361,35 +361,35 @@ pub struct HasIncoherentInherentImpl {
 
 #[derive(Diagnostic)]
 #[diag(passes_both_ffi_const_and_pure, code = E0757)]
-pub struct BothFfiConstAndPure {
+pub(crate) struct BothFfiConstAndPure {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_ffi_pure_invalid_target, code = E0755)]
-pub struct FfiPureInvalidTarget {
+pub(crate) struct FfiPureInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_ffi_const_invalid_target, code = E0756)]
-pub struct FfiConstInvalidTarget {
+pub(crate) struct FfiConstInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_must_use_no_effect)]
-pub struct MustUseNoEffect {
+pub(crate) struct MustUseNoEffect {
     pub article: &'static str,
     pub target: rustc_hir::Target,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_must_not_suspend)]
-pub struct MustNotSuspend {
+pub(crate) struct MustNotSuspend {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -399,7 +399,7 @@ pub struct MustNotSuspend {
 #[derive(LintDiagnostic)]
 #[diag(passes_cold)]
 #[warning]
-pub struct Cold {
+pub(crate) struct Cold {
     #[label]
     pub span: Span,
     pub on_crate: bool,
@@ -408,7 +408,7 @@ pub struct Cold {
 #[derive(LintDiagnostic)]
 #[diag(passes_link)]
 #[warning]
-pub struct Link {
+pub(crate) struct Link {
     #[label]
     pub span: Option<Span>,
 }
@@ -416,7 +416,7 @@ pub struct Link {
 #[derive(LintDiagnostic)]
 #[diag(passes_link_name)]
 #[warning]
-pub struct LinkName<'a> {
+pub(crate) struct LinkName<'a> {
     #[help]
     pub attr_span: Option<Span>,
     #[label]
@@ -426,7 +426,7 @@ pub struct LinkName<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_no_link)]
-pub struct NoLink {
+pub(crate) struct NoLink {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -435,7 +435,7 @@ pub struct NoLink {
 
 #[derive(Diagnostic)]
 #[diag(passes_export_name)]
-pub struct ExportName {
+pub(crate) struct ExportName {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -444,7 +444,7 @@ pub struct ExportName {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_layout_scalar_valid_range_not_struct)]
-pub struct RustcLayoutScalarValidRangeNotStruct {
+pub(crate) struct RustcLayoutScalarValidRangeNotStruct {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -453,14 +453,14 @@ pub struct RustcLayoutScalarValidRangeNotStruct {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_layout_scalar_valid_range_arg)]
-pub struct RustcLayoutScalarValidRangeArg {
+pub(crate) struct RustcLayoutScalarValidRangeArg {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_legacy_const_generics_only)]
-pub struct RustcLegacyConstGenericsOnly {
+pub(crate) struct RustcLegacyConstGenericsOnly {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -469,7 +469,7 @@ pub struct RustcLegacyConstGenericsOnly {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_legacy_const_generics_index)]
-pub struct RustcLegacyConstGenericsIndex {
+pub(crate) struct RustcLegacyConstGenericsIndex {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -478,7 +478,7 @@ pub struct RustcLegacyConstGenericsIndex {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_legacy_const_generics_index_exceed)]
-pub struct RustcLegacyConstGenericsIndexExceed {
+pub(crate) struct RustcLegacyConstGenericsIndexExceed {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -487,14 +487,14 @@ pub struct RustcLegacyConstGenericsIndexExceed {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_legacy_const_generics_index_negative)]
-pub struct RustcLegacyConstGenericsIndexNegative {
+pub(crate) struct RustcLegacyConstGenericsIndexNegative {
     #[primary_span]
     pub invalid_args: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_dirty_clean)]
-pub struct RustcDirtyClean {
+pub(crate) struct RustcDirtyClean {
     #[primary_span]
     pub span: Span,
 }
@@ -502,7 +502,7 @@ pub struct RustcDirtyClean {
 #[derive(LintDiagnostic)]
 #[diag(passes_link_section)]
 #[warning]
-pub struct LinkSection {
+pub(crate) struct LinkSection {
     #[label]
     pub span: Span,
 }
@@ -511,7 +511,7 @@ pub struct LinkSection {
 #[diag(passes_no_mangle_foreign)]
 #[warning]
 #[note]
-pub struct NoMangleForeign {
+pub(crate) struct NoMangleForeign {
     #[label]
     pub span: Span,
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -522,32 +522,32 @@ pub struct NoMangleForeign {
 #[derive(LintDiagnostic)]
 #[diag(passes_no_mangle)]
 #[warning]
-pub struct NoMangle {
+pub(crate) struct NoMangle {
     #[label]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_repr_ident, code = E0565)]
-pub struct ReprIdent {
+pub(crate) struct ReprIdent {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_repr_conflicting, code = E0566)]
-pub struct ReprConflicting {
+pub(crate) struct ReprConflicting {
     #[primary_span]
     pub hint_spans: Vec<Span>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_repr_conflicting, code = E0566)]
-pub struct ReprConflictingLint;
+pub(crate) struct ReprConflictingLint;
 
 #[derive(Diagnostic)]
 #[diag(passes_used_static)]
-pub struct UsedStatic {
+pub(crate) struct UsedStatic {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -557,14 +557,14 @@ pub struct UsedStatic {
 
 #[derive(Diagnostic)]
 #[diag(passes_used_compiler_linker)]
-pub struct UsedCompilerLinker {
+pub(crate) struct UsedCompilerLinker {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_allow_internal_unstable)]
-pub struct AllowInternalUnstable {
+pub(crate) struct AllowInternalUnstable {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -573,7 +573,7 @@ pub struct AllowInternalUnstable {
 
 #[derive(Diagnostic)]
 #[diag(passes_debug_visualizer_placement)]
-pub struct DebugVisualizerPlacement {
+pub(crate) struct DebugVisualizerPlacement {
     #[primary_span]
     pub span: Span,
 }
@@ -583,14 +583,14 @@ pub struct DebugVisualizerPlacement {
 #[note(passes_note_1)]
 #[note(passes_note_2)]
 #[note(passes_note_3)]
-pub struct DebugVisualizerInvalid {
+pub(crate) struct DebugVisualizerInvalid {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_debug_visualizer_unreadable)]
-pub struct DebugVisualizerUnreadable<'a> {
+pub(crate) struct DebugVisualizerUnreadable<'a> {
     #[primary_span]
     pub span: Span,
     pub file: &'a Path,
@@ -599,7 +599,7 @@ pub struct DebugVisualizerUnreadable<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_allow_const_fn_unstable)]
-pub struct RustcAllowConstFnUnstable {
+pub(crate) struct RustcAllowConstFnUnstable {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -608,7 +608,7 @@ pub struct RustcAllowConstFnUnstable {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_safe_intrinsic)]
-pub struct RustcSafeIntrinsic {
+pub(crate) struct RustcSafeIntrinsic {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -617,7 +617,7 @@ pub struct RustcSafeIntrinsic {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_std_internal_symbol)]
-pub struct RustcStdInternalSymbol {
+pub(crate) struct RustcStdInternalSymbol {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -626,7 +626,7 @@ pub struct RustcStdInternalSymbol {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_pub_transparent)]
-pub struct RustcPubTransparent {
+pub(crate) struct RustcPubTransparent {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -635,28 +635,28 @@ pub struct RustcPubTransparent {
 
 #[derive(Diagnostic)]
 #[diag(passes_link_ordinal)]
-pub struct LinkOrdinal {
+pub(crate) struct LinkOrdinal {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_confusables)]
-pub struct Confusables {
+pub(crate) struct Confusables {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_coroutine_on_non_closure)]
-pub struct CoroutineOnNonClosure {
+pub(crate) struct CoroutineOnNonClosure {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_linkage)]
-pub struct Linkage {
+pub(crate) struct Linkage {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -690,23 +690,23 @@ pub(crate) struct IncorrectMetaItemSuggestion {
 
 #[derive(Diagnostic)]
 #[diag(passes_stability_promotable)]
-pub struct StabilityPromotable {
+pub(crate) struct StabilityPromotable {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_deprecated)]
-pub struct Deprecated;
+pub(crate) struct Deprecated;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_macro_use)]
-pub struct MacroUse {
+pub(crate) struct MacroUse {
     pub name: Symbol,
 }
 
 #[derive(LintDiagnostic)]
-pub enum MacroExport {
+pub(crate) enum MacroExport {
     #[diag(passes_macro_export)]
     Normal,
 
@@ -722,7 +722,7 @@ pub enum MacroExport {
 }
 
 #[derive(Subdiagnostic)]
-pub enum UnusedNote {
+pub(crate) enum UnusedNote {
     #[note(passes_unused_empty_lints_note)]
     EmptyList { name: Symbol },
     #[note(passes_unused_no_lints_note)]
@@ -733,7 +733,7 @@ pub enum UnusedNote {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused)]
-pub struct Unused {
+pub(crate) struct Unused {
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub attr_span: Span,
     #[subdiagnostic]
@@ -742,7 +742,7 @@ pub struct Unused {
 
 #[derive(Diagnostic)]
 #[diag(passes_non_exported_macro_invalid_attrs, code = E0518)]
-pub struct NonExportedMacroInvalidAttrs {
+pub(crate) struct NonExportedMacroInvalidAttrs {
     #[primary_span]
     #[label]
     pub attr_span: Span,
@@ -750,14 +750,14 @@ pub struct NonExportedMacroInvalidAttrs {
 
 #[derive(Diagnostic)]
 #[diag(passes_may_dangle)]
-pub struct InvalidMayDangle {
+pub(crate) struct InvalidMayDangle {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_duplicate)]
-pub struct UnusedDuplicate {
+pub(crate) struct UnusedDuplicate {
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub this: Span,
     #[note]
@@ -768,7 +768,7 @@ pub struct UnusedDuplicate {
 
 #[derive(Diagnostic)]
 #[diag(passes_unused_multiple)]
-pub struct UnusedMultiple {
+pub(crate) struct UnusedMultiple {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub this: Span,
@@ -779,7 +779,7 @@ pub struct UnusedMultiple {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_lint_opt_ty)]
-pub struct RustcLintOptTy {
+pub(crate) struct RustcLintOptTy {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -788,7 +788,7 @@ pub struct RustcLintOptTy {
 
 #[derive(Diagnostic)]
 #[diag(passes_rustc_lint_opt_deny_field_access)]
-pub struct RustcLintOptDenyFieldAccess {
+pub(crate) struct RustcLintOptDenyFieldAccess {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -797,7 +797,7 @@ pub struct RustcLintOptDenyFieldAccess {
 
 #[derive(Diagnostic)]
 #[diag(passes_collapse_debuginfo)]
-pub struct CollapseDebuginfo {
+pub(crate) struct CollapseDebuginfo {
     #[primary_span]
     pub attr_span: Span,
     #[label]
@@ -806,14 +806,14 @@ pub struct CollapseDebuginfo {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_deprecated_annotation_has_no_effect)]
-pub struct DeprecatedAnnotationHasNoEffect {
+pub(crate) struct DeprecatedAnnotationHasNoEffect {
     #[suggestion(applicability = "machine-applicable", code = "")]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_unknown_external_lang_item, code = E0264)]
-pub struct UnknownExternLangItem {
+pub(crate) struct UnknownExternLangItem {
     #[primary_span]
     pub span: Span,
     pub lang_item: Symbol,
@@ -821,25 +821,25 @@ pub struct UnknownExternLangItem {
 
 #[derive(Diagnostic)]
 #[diag(passes_missing_panic_handler)]
-pub struct MissingPanicHandler;
+pub(crate) struct MissingPanicHandler;
 
 #[derive(Diagnostic)]
 #[diag(passes_panic_unwind_without_std)]
 #[help]
 #[note]
-pub struct PanicUnwindWithoutStd;
+pub(crate) struct PanicUnwindWithoutStd;
 
 #[derive(Diagnostic)]
 #[diag(passes_missing_lang_item)]
 #[note]
 #[help]
-pub struct MissingLangItem {
+pub(crate) struct MissingLangItem {
     pub name: Symbol,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_lang_item_fn_with_track_caller)]
-pub struct LangItemWithTrackCaller {
+pub(crate) struct LangItemWithTrackCaller {
     #[primary_span]
     pub attr_span: Span,
     pub name: Symbol,
@@ -849,7 +849,7 @@ pub struct LangItemWithTrackCaller {
 
 #[derive(Diagnostic)]
 #[diag(passes_lang_item_fn_with_target_feature)]
-pub struct LangItemWithTargetFeature {
+pub(crate) struct LangItemWithTargetFeature {
     #[primary_span]
     pub attr_span: Span,
     pub name: Symbol,
@@ -859,7 +859,7 @@ pub struct LangItemWithTargetFeature {
 
 #[derive(Diagnostic)]
 #[diag(passes_lang_item_on_incorrect_target, code = E0718)]
-pub struct LangItemOnIncorrectTarget {
+pub(crate) struct LangItemOnIncorrectTarget {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -870,14 +870,14 @@ pub struct LangItemOnIncorrectTarget {
 
 #[derive(Diagnostic)]
 #[diag(passes_unknown_lang_item, code = E0522)]
-pub struct UnknownLangItem {
+pub(crate) struct UnknownLangItem {
     #[primary_span]
     #[label]
     pub span: Span,
     pub name: Symbol,
 }
 
-pub struct InvalidAttrAtCrateLevel {
+pub(crate) struct InvalidAttrAtCrateLevel {
     pub span: Span,
     pub sugg_span: Option<Span>,
     pub name: Symbol,
@@ -885,7 +885,7 @@ pub struct InvalidAttrAtCrateLevel {
 }
 
 #[derive(Clone, Copy)]
-pub struct ItemFollowingInnerAttr {
+pub(crate) struct ItemFollowingInnerAttr {
     pub span: Span,
     pub kind: &'static str,
 }
@@ -916,7 +916,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for InvalidAttrAtCrateLevel {
 
 #[derive(Diagnostic)]
 #[diag(passes_duplicate_diagnostic_item_in_crate)]
-pub struct DuplicateDiagnosticItemInCrate {
+pub(crate) struct DuplicateDiagnosticItemInCrate {
     #[primary_span]
     pub duplicate_span: Option<Span>,
     #[note(passes_diagnostic_item_first_defined)]
@@ -930,7 +930,7 @@ pub struct DuplicateDiagnosticItemInCrate {
 
 #[derive(Diagnostic)]
 #[diag(passes_layout_abi)]
-pub struct LayoutAbi {
+pub(crate) struct LayoutAbi {
     #[primary_span]
     pub span: Span,
     pub abi: String,
@@ -938,7 +938,7 @@ pub struct LayoutAbi {
 
 #[derive(Diagnostic)]
 #[diag(passes_layout_align)]
-pub struct LayoutAlign {
+pub(crate) struct LayoutAlign {
     #[primary_span]
     pub span: Span,
     pub align: String,
@@ -946,7 +946,7 @@ pub struct LayoutAlign {
 
 #[derive(Diagnostic)]
 #[diag(passes_layout_size)]
-pub struct LayoutSize {
+pub(crate) struct LayoutSize {
     #[primary_span]
     pub span: Span,
     pub size: String,
@@ -954,7 +954,7 @@ pub struct LayoutSize {
 
 #[derive(Diagnostic)]
 #[diag(passes_layout_homogeneous_aggregate)]
-pub struct LayoutHomogeneousAggregate {
+pub(crate) struct LayoutHomogeneousAggregate {
     #[primary_span]
     pub span: Span,
     pub homogeneous_aggregate: String,
@@ -962,7 +962,7 @@ pub struct LayoutHomogeneousAggregate {
 
 #[derive(Diagnostic)]
 #[diag(passes_layout_of)]
-pub struct LayoutOf {
+pub(crate) struct LayoutOf {
     #[primary_span]
     pub span: Span,
     pub normalized_ty: String,
@@ -971,14 +971,14 @@ pub struct LayoutOf {
 
 #[derive(Diagnostic)]
 #[diag(passes_layout_invalid_attribute)]
-pub struct LayoutInvalidAttribute {
+pub(crate) struct LayoutInvalidAttribute {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_abi_of)]
-pub struct AbiOf {
+pub(crate) struct AbiOf {
     #[primary_span]
     pub span: Span,
     pub fn_name: Symbol,
@@ -987,7 +987,7 @@ pub struct AbiOf {
 
 #[derive(Diagnostic)]
 #[diag(passes_abi_ne)]
-pub struct AbiNe {
+pub(crate) struct AbiNe {
     #[primary_span]
     pub span: Span,
     pub left: String,
@@ -996,14 +996,14 @@ pub struct AbiNe {
 
 #[derive(Diagnostic)]
 #[diag(passes_abi_invalid_attribute)]
-pub struct AbiInvalidAttribute {
+pub(crate) struct AbiInvalidAttribute {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_unrecognized_field)]
-pub struct UnrecognizedField {
+pub(crate) struct UnrecognizedField {
     #[primary_span]
     pub span: Span,
     pub name: Symbol,
@@ -1011,7 +1011,7 @@ pub struct UnrecognizedField {
 
 #[derive(Diagnostic)]
 #[diag(passes_feature_stable_twice, code = E0711)]
-pub struct FeatureStableTwice {
+pub(crate) struct FeatureStableTwice {
     #[primary_span]
     pub span: Span,
     pub feature: Symbol,
@@ -1021,7 +1021,7 @@ pub struct FeatureStableTwice {
 
 #[derive(Diagnostic)]
 #[diag(passes_feature_previously_declared, code = E0711)]
-pub struct FeaturePreviouslyDeclared<'a, 'b> {
+pub(crate) struct FeaturePreviouslyDeclared<'a, 'b> {
     #[primary_span]
     pub span: Span,
     pub feature: Symbol,
@@ -1029,7 +1029,7 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> {
     pub prev_declared: &'b str,
 }
 
-pub struct BreakNonLoop<'a> {
+pub(crate) struct BreakNonLoop<'a> {
     pub span: Span,
     pub head: Option<Span>,
     pub kind: &'a str,
@@ -1084,7 +1084,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_continue_labeled_block, code = E0696)]
-pub struct ContinueLabeledBlock {
+pub(crate) struct ContinueLabeledBlock {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1094,7 +1094,7 @@ pub struct ContinueLabeledBlock {
 
 #[derive(Diagnostic)]
 #[diag(passes_break_inside_closure, code = E0267)]
-pub struct BreakInsideClosure<'a> {
+pub(crate) struct BreakInsideClosure<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1105,7 +1105,7 @@ pub struct BreakInsideClosure<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_break_inside_coroutine, code = E0267)]
-pub struct BreakInsideCoroutine<'a> {
+pub(crate) struct BreakInsideCoroutine<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1118,7 +1118,7 @@ pub struct BreakInsideCoroutine<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_outside_loop, code = E0268)]
-pub struct OutsideLoop<'a> {
+pub(crate) struct OutsideLoop<'a> {
     #[primary_span]
     #[label]
     pub spans: Vec<Span>,
@@ -1129,7 +1129,7 @@ pub struct OutsideLoop<'a> {
 }
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(passes_outside_loop_suggestion, applicability = "maybe-incorrect")]
-pub struct OutsideLoopSuggestion {
+pub(crate) struct OutsideLoopSuggestion {
     #[suggestion_part(code = "'block: ")]
     pub block_span: Span,
     #[suggestion_part(code = " 'block")]
@@ -1138,7 +1138,7 @@ pub struct OutsideLoopSuggestion {
 
 #[derive(Diagnostic)]
 #[diag(passes_unlabeled_in_labeled_block, code = E0695)]
-pub struct UnlabeledInLabeledBlock<'a> {
+pub(crate) struct UnlabeledInLabeledBlock<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1147,7 +1147,7 @@ pub struct UnlabeledInLabeledBlock<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_unlabeled_cf_in_while_condition, code = E0590)]
-pub struct UnlabeledCfInWhileCondition<'a> {
+pub(crate) struct UnlabeledCfInWhileCondition<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1156,11 +1156,11 @@ pub struct UnlabeledCfInWhileCondition<'a> {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_undefined_naked_function_abi)]
-pub struct UndefinedNakedFunctionAbi;
+pub(crate) struct UndefinedNakedFunctionAbi;
 
 #[derive(Diagnostic)]
 #[diag(passes_no_patterns)]
-pub struct NoPatterns {
+pub(crate) struct NoPatterns {
     #[primary_span]
     pub span: Span,
 }
@@ -1168,12 +1168,12 @@ pub struct NoPatterns {
 #[derive(Diagnostic)]
 #[diag(passes_params_not_allowed)]
 #[help]
-pub struct ParamsNotAllowed {
+pub(crate) struct ParamsNotAllowed {
     #[primary_span]
     pub span: Span,
 }
 
-pub struct NakedFunctionsAsmBlock {
+pub(crate) struct NakedFunctionsAsmBlock {
     pub span: Span,
     pub multiple_asms: Vec<Span>,
     pub non_asms: Vec<Span>,
@@ -1197,14 +1197,14 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for NakedFunctionsAsmBlock {
 
 #[derive(Diagnostic)]
 #[diag(passes_naked_functions_operands, code = E0787)]
-pub struct NakedFunctionsOperands {
+pub(crate) struct NakedFunctionsOperands {
     #[primary_span]
     pub unsupported_operands: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_naked_functions_asm_options, code = E0787)]
-pub struct NakedFunctionsAsmOptions {
+pub(crate) struct NakedFunctionsAsmOptions {
     #[primary_span]
     pub span: Span,
     pub unsupported_options: String,
@@ -1212,7 +1212,7 @@ pub struct NakedFunctionsAsmOptions {
 
 #[derive(Diagnostic)]
 #[diag(passes_naked_functions_must_use_noreturn, code = E0787)]
-pub struct NakedFunctionsMustUseNoreturn {
+pub(crate) struct NakedFunctionsMustUseNoreturn {
     #[primary_span]
     pub span: Span,
     #[suggestion(code = ", options(noreturn)", applicability = "machine-applicable")]
@@ -1221,7 +1221,7 @@ pub struct NakedFunctionsMustUseNoreturn {
 
 #[derive(Diagnostic)]
 #[diag(passes_naked_functions_incompatible_attribute, code = E0736)]
-pub struct NakedFunctionIncompatibleAttribute {
+pub(crate) struct NakedFunctionIncompatibleAttribute {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1232,7 +1232,7 @@ pub struct NakedFunctionIncompatibleAttribute {
 
 #[derive(Diagnostic)]
 #[diag(passes_attr_only_in_functions)]
-pub struct AttrOnlyInFunctions {
+pub(crate) struct AttrOnlyInFunctions {
     #[primary_span]
     pub span: Span,
     pub attr: Symbol,
@@ -1240,7 +1240,7 @@ pub struct AttrOnlyInFunctions {
 
 #[derive(Diagnostic)]
 #[diag(passes_multiple_rustc_main, code = E0137)]
-pub struct MultipleRustcMain {
+pub(crate) struct MultipleRustcMain {
     #[primary_span]
     pub span: Span,
     #[label(passes_first)]
@@ -1251,7 +1251,7 @@ pub struct MultipleRustcMain {
 
 #[derive(Diagnostic)]
 #[diag(passes_multiple_start_functions, code = E0138)]
-pub struct MultipleStartFunctions {
+pub(crate) struct MultipleStartFunctions {
     #[primary_span]
     pub span: Span,
     #[label]
@@ -1262,12 +1262,12 @@ pub struct MultipleStartFunctions {
 
 #[derive(Diagnostic)]
 #[diag(passes_extern_main)]
-pub struct ExternMain {
+pub(crate) struct ExternMain {
     #[primary_span]
     pub span: Span,
 }
 
-pub struct NoMainErr {
+pub(crate) struct NoMainErr {
     pub sp: Span,
     pub crate_name: Symbol,
     pub has_filename: bool,
@@ -1321,7 +1321,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr {
     }
 }
 
-pub struct DuplicateLangItem {
+pub(crate) struct DuplicateLangItem {
     pub local_span: Option<Span>,
     pub lang_item_name: Symbol,
     pub crate_name: Symbol,
@@ -1386,7 +1386,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for DuplicateLangItem {
 
 #[derive(Diagnostic)]
 #[diag(passes_incorrect_target, code = E0718)]
-pub struct IncorrectTarget<'a> {
+pub(crate) struct IncorrectTarget<'a> {
     #[primary_span]
     pub span: Span,
     #[label]
@@ -1400,21 +1400,21 @@ pub struct IncorrectTarget<'a> {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_useless_assignment)]
-pub struct UselessAssignment<'a> {
+pub(crate) struct UselessAssignment<'a> {
     pub is_field_assign: bool,
     pub ty: Ty<'a>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_only_has_effect_on)]
-pub struct OnlyHasEffectOn {
+pub(crate) struct OnlyHasEffectOn {
     pub attr_name: Symbol,
     pub target_name: String,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_object_lifetime_err)]
-pub struct ObjectLifetimeErr {
+pub(crate) struct ObjectLifetimeErr {
     #[primary_span]
     pub span: Span,
     pub repr: String,
@@ -1423,13 +1423,13 @@ pub struct ObjectLifetimeErr {
 #[derive(Diagnostic)]
 #[diag(passes_unrecognized_repr_hint, code = E0552)]
 #[help]
-pub struct UnrecognizedReprHint {
+pub(crate) struct UnrecognizedReprHint {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-pub enum AttrApplication {
+pub(crate) enum AttrApplication {
     #[diag(passes_attr_application_enum, code = E0517)]
     Enum {
         #[primary_span]
@@ -1469,7 +1469,7 @@ pub enum AttrApplication {
 
 #[derive(Diagnostic)]
 #[diag(passes_transparent_incompatible, code = E0692)]
-pub struct TransparentIncompatible {
+pub(crate) struct TransparentIncompatible {
     #[primary_span]
     pub hint_spans: Vec<Span>,
     pub target: String,
@@ -1477,14 +1477,14 @@ pub struct TransparentIncompatible {
 
 #[derive(Diagnostic)]
 #[diag(passes_deprecated_attribute, code = E0549)]
-pub struct DeprecatedAttribute {
+pub(crate) struct DeprecatedAttribute {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_useless_stability)]
-pub struct UselessStability {
+pub(crate) struct UselessStability {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1494,7 +1494,7 @@ pub struct UselessStability {
 
 #[derive(Diagnostic)]
 #[diag(passes_cannot_stabilize_deprecated)]
-pub struct CannotStabilizeDeprecated {
+pub(crate) struct CannotStabilizeDeprecated {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -1504,7 +1504,7 @@ pub struct CannotStabilizeDeprecated {
 
 #[derive(Diagnostic)]
 #[diag(passes_missing_stability_attr)]
-pub struct MissingStabilityAttr<'a> {
+pub(crate) struct MissingStabilityAttr<'a> {
     #[primary_span]
     pub span: Span,
     pub descr: &'a str,
@@ -1512,7 +1512,7 @@ pub struct MissingStabilityAttr<'a> {
 
 #[derive(Diagnostic)]
 #[diag(passes_missing_const_stab_attr)]
-pub struct MissingConstStabAttr<'a> {
+pub(crate) struct MissingConstStabAttr<'a> {
     #[primary_span]
     pub span: Span,
     pub descr: &'a str,
@@ -1521,14 +1521,14 @@ pub struct MissingConstStabAttr<'a> {
 #[derive(Diagnostic)]
 #[diag(passes_trait_impl_const_stable)]
 #[note]
-pub struct TraitImplConstStable {
+pub(crate) struct TraitImplConstStable {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(passes_unknown_feature, code = E0635)]
-pub struct UnknownFeature {
+pub(crate) struct UnknownFeature {
     #[primary_span]
     pub span: Span,
     pub feature: Symbol,
@@ -1536,7 +1536,7 @@ pub struct UnknownFeature {
 
 #[derive(Diagnostic)]
 #[diag(passes_implied_feature_not_exist)]
-pub struct ImpliedFeatureNotExist {
+pub(crate) struct ImpliedFeatureNotExist {
     #[primary_span]
     pub span: Span,
     pub feature: Symbol,
@@ -1545,14 +1545,14 @@ pub struct ImpliedFeatureNotExist {
 
 #[derive(Diagnostic)]
 #[diag(passes_duplicate_feature_err, code = E0636)]
-pub struct DuplicateFeatureErr {
+pub(crate) struct DuplicateFeatureErr {
     #[primary_span]
     pub span: Span,
     pub feature: Symbol,
 }
 #[derive(Diagnostic)]
 #[diag(passes_missing_const_err)]
-pub struct MissingConstErr {
+pub(crate) struct MissingConstErr {
     #[primary_span]
     #[help]
     pub fn_sig_span: Span,
@@ -1561,7 +1561,7 @@ pub struct MissingConstErr {
 }
 
 #[derive(LintDiagnostic)]
-pub enum MultipleDeadCodes<'tcx> {
+pub(crate) enum MultipleDeadCodes<'tcx> {
     #[diag(passes_dead_codes)]
     DeadCodes {
         multiple: bool,
@@ -1592,7 +1592,7 @@ pub enum MultipleDeadCodes<'tcx> {
 
 #[derive(Subdiagnostic)]
 #[label(passes_parent_info)]
-pub struct ParentInfo<'tcx> {
+pub(crate) struct ParentInfo<'tcx> {
     pub num: usize,
     pub descr: &'tcx str,
     pub parent_descr: &'tcx str,
@@ -1602,14 +1602,14 @@ pub struct ParentInfo<'tcx> {
 
 #[derive(Subdiagnostic)]
 #[note(passes_ignored_derived_impls)]
-pub struct IgnoredDerivedImpls {
+pub(crate) struct IgnoredDerivedImpls {
     pub name: Symbol,
     pub trait_list: DiagSymbolList,
     pub trait_list_len: usize,
 }
 
 #[derive(Subdiagnostic)]
-pub enum ChangeFields {
+pub(crate) enum ChangeFields {
     #[multipart_suggestion(
         passes_change_fields_to_be_of_unit_type,
         applicability = "has-placeholders"
@@ -1633,14 +1633,14 @@ pub(crate) struct ProcMacroBadSig {
 
 #[derive(Diagnostic)]
 #[diag(passes_skipping_const_checks)]
-pub struct SkippingConstChecks {
+pub(crate) struct SkippingConstChecks {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unreachable_due_to_uninhabited)]
-pub struct UnreachableDueToUninhabited<'desc, 'tcx> {
+pub(crate) struct UnreachableDueToUninhabited<'desc, 'tcx> {
     pub descr: &'desc str,
     #[label]
     pub expr: Span,
@@ -1653,20 +1653,20 @@ pub struct UnreachableDueToUninhabited<'desc, 'tcx> {
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_var_maybe_capture_ref)]
 #[help]
-pub struct UnusedVarMaybeCaptureRef {
+pub(crate) struct UnusedVarMaybeCaptureRef {
     pub name: String,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_capture_maybe_capture_ref)]
 #[help]
-pub struct UnusedCaptureMaybeCaptureRef {
+pub(crate) struct UnusedCaptureMaybeCaptureRef {
     pub name: String,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_var_remove_field)]
-pub struct UnusedVarRemoveField {
+pub(crate) struct UnusedVarRemoveField {
     pub name: String,
     #[subdiagnostic]
     pub sugg: UnusedVarRemoveFieldSugg,
@@ -1677,7 +1677,7 @@ pub struct UnusedVarRemoveField {
     passes_unused_var_remove_field_suggestion,
     applicability = "machine-applicable"
 )]
-pub struct UnusedVarRemoveFieldSugg {
+pub(crate) struct UnusedVarRemoveFieldSugg {
     #[suggestion_part(code = "")]
     pub spans: Vec<Span>,
 }
@@ -1685,20 +1685,20 @@ pub struct UnusedVarRemoveFieldSugg {
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_var_assigned_only)]
 #[note]
-pub struct UnusedVarAssignedOnly {
+pub(crate) struct UnusedVarAssignedOnly {
     pub name: String,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unnecessary_stable_feature)]
-pub struct UnnecessaryStableFeature {
+pub(crate) struct UnnecessaryStableFeature {
     pub feature: Symbol,
     pub since: Symbol,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unnecessary_partial_stable_feature)]
-pub struct UnnecessaryPartialStableFeature {
+pub(crate) struct UnnecessaryPartialStableFeature {
     #[suggestion(code = "{implies}", applicability = "maybe-incorrect")]
     pub span: Span,
     #[suggestion(passes_suggestion_remove, code = "", applicability = "maybe-incorrect")]
@@ -1711,25 +1711,25 @@ pub struct UnnecessaryPartialStableFeature {
 #[derive(LintDiagnostic)]
 #[diag(passes_ineffective_unstable_impl)]
 #[note]
-pub struct IneffectiveUnstableImpl;
+pub(crate) struct IneffectiveUnstableImpl;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_assign)]
 #[help]
-pub struct UnusedAssign {
+pub(crate) struct UnusedAssign {
     pub name: String,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_assign_passed)]
 #[help]
-pub struct UnusedAssignPassed {
+pub(crate) struct UnusedAssignPassed {
     pub name: String,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_variable_try_prefix)]
-pub struct UnusedVariableTryPrefix {
+pub(crate) struct UnusedVariableTryPrefix {
     #[label]
     pub label: Option<Span>,
     #[subdiagnostic]
@@ -1740,7 +1740,7 @@ pub struct UnusedVariableTryPrefix {
 }
 
 #[derive(Subdiagnostic)]
-pub enum UnusedVariableSugg {
+pub(crate) enum UnusedVariableSugg {
     #[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")]
     TryPrefixSugg {
         #[suggestion_part(code = "_{name}")]
@@ -1755,7 +1755,7 @@ pub enum UnusedVariableSugg {
     },
 }
 
-pub struct UnusedVariableStringInterp {
+pub(crate) struct UnusedVariableStringInterp {
     pub lit: Span,
     pub lo: Span,
     pub hi: Span,
@@ -1778,14 +1778,14 @@ impl Subdiagnostic for UnusedVariableStringInterp {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_unused_variable_try_ignore)]
-pub struct UnusedVarTryIgnore {
+pub(crate) struct UnusedVarTryIgnore {
     #[subdiagnostic]
     pub sugg: UnusedVarTryIgnoreSugg,
 }
 
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")]
-pub struct UnusedVarTryIgnoreSugg {
+pub(crate) struct UnusedVarTryIgnoreSugg {
     #[suggestion_part(code = "{name}: _")]
     pub shorthands: Vec<Span>,
     #[suggestion_part(code = "_")]
@@ -1796,14 +1796,14 @@ pub struct UnusedVarTryIgnoreSugg {
 #[derive(LintDiagnostic)]
 #[diag(passes_attr_crate_level)]
 #[note]
-pub struct AttrCrateLevelOnly {
+pub(crate) struct AttrCrateLevelOnly {
     #[subdiagnostic]
     pub sugg: Option<AttrCrateLevelOnlySugg>,
 }
 
 #[derive(Subdiagnostic)]
 #[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")]
-pub struct AttrCrateLevelOnlySugg {
+pub(crate) struct AttrCrateLevelOnlySugg {
     #[primary_span]
     pub attr: Span,
 }
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 71b0ebb0e21..8038afb955e 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -359,6 +359,6 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
     }
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.get_lang_items = get_lang_items;
 }
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index a0f5f98aafc..664da65068d 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -12,6 +12,7 @@
 #![feature(map_try_insert)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use rustc_middle::query::Providers;
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index e60985ba16f..9d5766865c7 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -16,7 +16,7 @@ use rustc_span::{sym, Span};
 
 use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice};
 
-pub struct LibFeatureCollector<'tcx> {
+struct LibFeatureCollector<'tcx> {
     tcx: TyCtxt<'tcx>,
     lib_features: LibFeatures,
 }
@@ -153,6 +153,6 @@ fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures {
     collector.lib_features
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.lib_features = lib_features;
 }
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index d3b85da4630..db3eaea68b5 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -178,7 +178,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     lsets.warn_about_unused_args(&body, entry_ln);
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { check_liveness, ..*providers };
 }
 
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index dee8ba7e87d..8d9e00b9f3c 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -500,6 +500,6 @@ fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
     reachable_context.reachable_symbols
 }
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { reachable_set, ..*providers };
 }
diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs
index f2454514e4d..0544d08f5b1 100644
--- a/compiler/rustc_passes/src/upvars.rs
+++ b/compiler/rustc_passes/src/upvars.rs
@@ -9,7 +9,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.upvars_mentioned = |tcx, def_id| {
         if !tcx.is_closure_like(def_id) {
             return None;
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 90691ca1790..020128f29c5 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -15,7 +15,11 @@ use crate::errors::{
 
 /// Checks the crate for usage of weak lang items, returning a vector of all the
 /// lang items required by this crate, but not defined yet.
-pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems, krate: &ast::Crate) {
+pub(crate) fn check_crate(
+    tcx: TyCtxt<'_>,
+    items: &mut lang_items::LanguageItems,
+    krate: &ast::Crate,
+) {
     // These are never called by user code, they're generated by the compiler.
     // They will never implicitly be added to the `missing` array unless we do
     // so here.
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 6c9c848bb10..fec44d5af55 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -6,6 +6,7 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 #![cfg_attr(feature = "rustc", feature(let_chains))]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod constructor;
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index 89face10750..34553c2b90a 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -5,7 +5,7 @@ use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
 #[diag(privacy_field_is_private, code = E0451)]
-pub struct FieldIsPrivate {
+pub(crate) struct FieldIsPrivate {
     #[primary_span]
     pub span: Span,
     pub field_name: Symbol,
@@ -16,7 +16,7 @@ pub struct FieldIsPrivate {
 }
 
 #[derive(Subdiagnostic)]
-pub enum FieldIsPrivateLabel {
+pub(crate) enum FieldIsPrivateLabel {
     #[label(privacy_field_is_private_is_update_syntax_label)]
     IsUpdateSyntax {
         #[primary_span]
@@ -32,7 +32,7 @@ pub enum FieldIsPrivateLabel {
 
 #[derive(Diagnostic)]
 #[diag(privacy_item_is_private)]
-pub struct ItemIsPrivate<'a> {
+pub(crate) struct ItemIsPrivate<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -42,7 +42,7 @@ pub struct ItemIsPrivate<'a> {
 
 #[derive(Diagnostic)]
 #[diag(privacy_unnamed_item_is_private)]
-pub struct UnnamedItemIsPrivate {
+pub(crate) struct UnnamedItemIsPrivate {
     #[primary_span]
     pub span: Span,
     pub kind: &'static str,
@@ -50,7 +50,7 @@ pub struct UnnamedItemIsPrivate {
 
 #[derive(Diagnostic)]
 #[diag(privacy_in_public_interface, code = E0446)]
-pub struct InPublicInterface<'a> {
+pub(crate) struct InPublicInterface<'a> {
     #[primary_span]
     #[label]
     pub span: Span,
@@ -63,7 +63,7 @@ pub struct InPublicInterface<'a> {
 
 #[derive(Diagnostic)]
 #[diag(privacy_report_effective_visibility)]
-pub struct ReportEffectiveVisibility {
+pub(crate) struct ReportEffectiveVisibility {
     #[primary_span]
     pub span: Span,
     pub descr: String,
@@ -71,7 +71,7 @@ pub struct ReportEffectiveVisibility {
 
 #[derive(LintDiagnostic)]
 #[diag(privacy_from_private_dep_in_public_interface)]
-pub struct FromPrivateDependencyInPublicInterface<'a> {
+pub(crate) struct FromPrivateDependencyInPublicInterface<'a> {
     pub kind: &'a str,
     pub descr: DiagArgFromDisplay<'a>,
     pub krate: Symbol,
@@ -79,7 +79,7 @@ pub struct FromPrivateDependencyInPublicInterface<'a> {
 
 #[derive(LintDiagnostic)]
 #[diag(privacy_unnameable_types_lint)]
-pub struct UnnameableTypesLint<'a> {
+pub(crate) struct UnnameableTypesLint<'a> {
     #[label]
     pub span: Span,
     pub kind: &'a str,
@@ -93,7 +93,7 @@ pub struct UnnameableTypesLint<'a> {
 // See https://rust-lang.github.io/rfcs/2145-type-privacy.html for more details.
 #[derive(LintDiagnostic)]
 #[diag(privacy_private_interface_or_bounds_lint)]
-pub struct PrivateInterfacesOrBoundsLint<'a> {
+pub(crate) struct PrivateInterfacesOrBoundsLint<'a> {
     #[label(privacy_item_label)]
     pub item_span: Span,
     pub item_kind: &'a str,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 9f78215bfd1..572f71d7c77 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 mod errors;
@@ -1497,7 +1498,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
         self.effective_visibilities.effective_vis(def_id).copied()
     }
 
-    pub fn check_item(&mut self, id: ItemId) {
+    fn check_item(&mut self, id: ItemId) {
         let tcx = self.tcx;
         let def_id = id.owner_id.def_id;
         let item_visibility = tcx.local_visibility(def_id);
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index f4a4c602f69..a6c863a6b7b 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -8,6 +8,7 @@
 #![feature(min_specialization)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use field_offset::offset_of;
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index c064b2bd6c1..6a6698b019c 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -541,7 +541,7 @@ macro_rules! expand_if_cached {
 /// Don't show the backtrace for query system by default
 /// use `RUST_BACKTRACE=full` to show all the backtraces
 #[inline(never)]
-pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
+pub(crate) fn __rust_begin_short_backtrace<F, T>(f: F) -> T
 where
     F: FnOnce() -> T,
 {
@@ -557,17 +557,17 @@ macro_rules! define_queries {
      $($(#[$attr:meta])*
         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
 
-        pub(crate) mod query_impl { $(pub mod $name {
+        pub(crate) mod query_impl { $(pub(crate) mod $name {
             use super::super::*;
             use std::marker::PhantomData;
 
-            pub mod get_query_incr {
+            pub(crate) mod get_query_incr {
                 use super::*;
 
                 // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
                 // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
                 #[inline(never)]
-                pub fn __rust_end_short_backtrace<'tcx>(
+                pub(crate) fn __rust_end_short_backtrace<'tcx>(
                     tcx: TyCtxt<'tcx>,
                     span: Span,
                     key: queries::$name::Key<'tcx>,
@@ -585,11 +585,11 @@ macro_rules! define_queries {
                 }
             }
 
-            pub mod get_query_non_incr {
+            pub(crate) mod get_query_non_incr {
                 use super::*;
 
                 #[inline(never)]
-                pub fn __rust_end_short_backtrace<'tcx>(
+                pub(crate) fn __rust_end_short_backtrace<'tcx>(
                     tcx: TyCtxt<'tcx>,
                     span: Span,
                     key: queries::$name::Key<'tcx>,
@@ -604,7 +604,9 @@ macro_rules! define_queries {
                 }
             }
 
-            pub fn dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> {
+            pub(crate) fn dynamic_query<'tcx>()
+                -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>>
+            {
                 DynamicQuery {
                     name: stringify!($name),
                     eval_always: is_eval_always!([$($modifiers)*]),
@@ -667,7 +669,7 @@ macro_rules! define_queries {
             }
 
             #[derive(Copy, Clone, Default)]
-            pub struct QueryType<'tcx> {
+            pub(crate) struct QueryType<'tcx> {
                 data: PhantomData<&'tcx ()>
             }
 
@@ -696,7 +698,7 @@ macro_rules! define_queries {
                 }
             }
 
-            pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) {
+            pub(crate) fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) {
                 let make_query = |tcx, key| {
                     let kind = rustc_middle::dep_graph::dep_kinds::$name;
                     let name = stringify!($name);
@@ -711,11 +713,17 @@ macro_rules! define_queries {
                 // don't `unwrap()` here, just manually check for `None` and do best-effort error
                 // reporting.
                 if res.is_none() {
-                    tracing::warn!("Failed to collect active jobs for query with name `{}`!", stringify!($name));
+                    tracing::warn!(
+                        "Failed to collect active jobs for query with name `{}`!",
+                        stringify!($name)
+                    );
                 }
             }
 
-            pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) {
+            pub(crate) fn alloc_self_profile_query_strings<'tcx>(
+                tcx: TyCtxt<'tcx>,
+                string_cache: &mut QueryKeyStringCache
+            ) {
                 $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
                     tcx,
                     stringify!($name),
@@ -725,7 +733,7 @@ macro_rules! define_queries {
             }
 
             item_if_cached! { [$($modifiers)*] {
-                pub fn encode_query_results<'tcx>(
+                pub(crate) fn encode_query_results<'tcx>(
                     tcx: TyCtxt<'tcx>,
                     encoder: &mut CacheEncoder<'_, 'tcx>,
                     query_result_index: &mut EncodedDepNodeIndex
@@ -739,7 +747,7 @@ macro_rules! define_queries {
                 }
             }}
 
-            pub fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) {
+            pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) {
                 $crate::plumbing::query_key_hash_verify(
                     query_impl::$name::QueryType::config(tcx),
                     QueryCtxt::new(tcx),
@@ -795,7 +803,7 @@ macro_rules! define_queries {
             use rustc_query_system::dep_graph::FingerprintStyle;
 
             // We use this for most things when incr. comp. is turned off.
-            pub fn Null<'tcx>() -> DepKindStruct<'tcx> {
+            pub(crate) fn Null<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
@@ -807,7 +815,7 @@ macro_rules! define_queries {
             }
 
             // We use this for the forever-red node.
-            pub fn Red<'tcx>() -> DepKindStruct<'tcx> {
+            pub(crate) fn Red<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
@@ -818,7 +826,7 @@ macro_rules! define_queries {
                 }
             }
 
-            pub fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
+            pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: true,
                     is_eval_always: false,
@@ -829,7 +837,7 @@ macro_rules! define_queries {
                 }
             }
 
-            pub fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
+            pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
@@ -840,7 +848,7 @@ macro_rules! define_queries {
                 }
             }
 
-            pub fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
+            pub(crate) fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index ab4a8be0fbf..a4fb0a5b072 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -617,14 +617,14 @@ impl<D: Deps> EncoderState<D> {
     }
 }
 
-pub struct GraphEncoder<D: Deps> {
+pub(crate) struct GraphEncoder<D: Deps> {
     profiler: SelfProfilerRef,
     status: Lock<Option<EncoderState<D>>>,
     record_graph: Option<Lock<DepGraphQuery>>,
 }
 
 impl<D: Deps> GraphEncoder<D> {
-    pub fn new(
+    pub(crate) fn new(
         encoder: FileEncoder,
         prev_node_count: usize,
         record_graph: bool,
@@ -723,7 +723,7 @@ impl<D: Deps> GraphEncoder<D> {
         )
     }
 
-    pub fn finish(&self) -> FileEncodeResult {
+    pub(crate) fn finish(&self) -> FileEncodeResult {
         let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph_finish");
 
         self.status.lock().take().unwrap().finish(&self.profiler)
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index 9db6fac8036..860f2e66915 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -5,7 +5,7 @@ use rustc_span::{Span, Symbol};
 
 #[derive(Subdiagnostic)]
 #[note(query_system_cycle_stack_middle)]
-pub struct CycleStack {
+pub(crate) struct CycleStack {
     #[primary_span]
     pub span: Span,
     pub desc: String,
@@ -20,7 +20,7 @@ pub enum HandleCycleError {
 }
 
 #[derive(Subdiagnostic)]
-pub enum StackCount {
+pub(crate) enum StackCount {
     #[note(query_system_cycle_stack_single)]
     Single,
     #[note(query_system_cycle_stack_multiple)]
@@ -28,7 +28,7 @@ pub enum StackCount {
 }
 
 #[derive(Subdiagnostic)]
-pub enum Alias {
+pub(crate) enum Alias {
     #[note(query_system_cycle_recursive_ty_alias)]
     #[help(query_system_cycle_recursive_ty_alias_help1)]
     #[help(query_system_cycle_recursive_ty_alias_help2)]
@@ -39,7 +39,7 @@ pub enum Alias {
 
 #[derive(Subdiagnostic)]
 #[note(query_system_cycle_usage)]
-pub struct CycleUsage {
+pub(crate) struct CycleUsage {
     #[primary_span]
     pub span: Span,
     pub usage: String,
@@ -47,7 +47,7 @@ pub struct CycleUsage {
 
 #[derive(Diagnostic)]
 #[diag(query_system_cycle, code = E0391)]
-pub struct Cycle {
+pub(crate) struct Cycle {
     #[primary_span]
     pub span: Span,
     pub stack_bottom: String,
@@ -65,14 +65,14 @@ pub struct Cycle {
 
 #[derive(Diagnostic)]
 #[diag(query_system_reentrant)]
-pub struct Reentrant;
+pub(crate) struct Reentrant;
 
 #[derive(Diagnostic)]
 #[diag(query_system_increment_compilation)]
 #[help]
 #[note(query_system_increment_compilation_note1)]
 #[note(query_system_increment_compilation_note2)]
-pub struct IncrementCompilation {
+pub(crate) struct IncrementCompilation {
     pub run_cmd: String,
     pub dep_node: String,
 }
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index 7a50a9534c2..ba7a631fb54 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(hash_raw_entry)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 pub mod cache;
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 02fdc1ae668..8ffd00d1b2e 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -21,6 +21,7 @@
 #![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use std::cell::{Cell, RefCell};
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 4fb3702b05d..fbdb3cb1534 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -22,7 +22,9 @@ use rustc_feature::UnstableFeatures;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
 use rustc_span::source_map::FilePathMapping;
-use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
+use rustc_span::{
+    sym, FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm, Symbol,
+};
 use rustc_target::spec::{
     FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTriple,
 };
@@ -402,6 +404,23 @@ impl LocationDetail {
     }
 }
 
+/// Values for the `-Z fmt-debug` flag.
+#[derive(Copy, Clone, PartialEq, Hash, Debug)]
+pub enum FmtDebug {
+    /// Derive fully-featured implementation
+    Full,
+    /// Print only type name, without fields
+    Shallow,
+    /// `#[derive(Debug)]` and `{:?}` are no-ops
+    None,
+}
+
+impl FmtDebug {
+    pub(crate) fn all() -> [Symbol; 3] {
+        [sym::full, sym::none, sym::shallow]
+    }
+}
+
 #[derive(Clone, PartialEq, Hash, Debug)]
 pub enum SwitchWithOptPath {
     Enabled(Option<PathBuf>),
@@ -2994,7 +3013,7 @@ pub(crate) mod dep_tracking {
 
     use super::{
         BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
-        CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
+        CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
         InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
         LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
         PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks,
@@ -3088,6 +3107,7 @@ pub(crate) mod dep_tracking {
         OutputType,
         RealFileName,
         LocationDetail,
+        FmtDebug,
         BranchProtection,
         OomStrategy,
         LanguageIdentifier,
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index a64b1e21e9e..0fa776ecb5c 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -31,7 +31,7 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::Align;
 use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, Target, TargetTriple, TARGETS};
 
-use crate::config::CrateType;
+use crate::config::{CrateType, FmtDebug};
 use crate::Session;
 
 /// The parsed `--cfg` options that define the compilation environment of the
@@ -142,6 +142,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
             | (sym::target_has_atomic_equal_alignment, Some(_))
             | (sym::target_has_atomic_load_store, Some(_))
             | (sym::target_thread_local, None) => disallow(cfg, "--target"),
+            (sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
             _ => {}
         }
     }
@@ -179,6 +180,20 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
         ins_none!(sym::debug_assertions);
     }
 
+    if sess.is_nightly_build() {
+        match sess.opts.unstable_opts.fmt_debug {
+            FmtDebug::Full => {
+                ins_sym!(sym::fmt_debug, sym::full);
+            }
+            FmtDebug::Shallow => {
+                ins_sym!(sym::fmt_debug, sym::shallow);
+            }
+            FmtDebug::None => {
+                ins_sym!(sym::fmt_debug, sym::none);
+            }
+        }
+    }
+
     if sess.overflow_checks() {
         ins_none!(sym::overflow_checks);
     }
@@ -326,6 +341,8 @@ impl CheckCfg {
 
         ins!(sym::debug_assertions, no_values);
 
+        ins!(sym::fmt_debug, empty_values).extend(FmtDebug::all());
+
         // These four are never set by rustc, but we set them anyway; they
         // should not trigger the lint because `cargo clippy`, `cargo doc`,
         // `cargo test`, `cargo miri run` and `cargo fmt` (respectively)
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 23231fbffbf..4492ad09357 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -408,6 +408,7 @@ mod desc {
     pub const parse_linker_plugin_lto: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin";
     pub const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`";
+    pub const parse_fmt_debug: &str = "either `full`, `shallow`, or `none`";
     pub const parse_switch_with_opt_path: &str =
         "an optional path to the profiling data output directory";
     pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`";
@@ -589,6 +590,16 @@ mod parse {
         }
     }
 
+    pub(crate) fn parse_fmt_debug(opt: &mut FmtDebug, v: Option<&str>) -> bool {
+        *opt = match v {
+            Some("full") => FmtDebug::Full,
+            Some("shallow") => FmtDebug::Shallow,
+            Some("none") => FmtDebug::None,
+            _ => return false,
+        };
+        true
+    }
+
     pub(crate) fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
         if let Some(v) = v {
             ld.line = false;
@@ -1724,6 +1735,9 @@ options! {
     flatten_format_args: bool = (true, parse_bool, [TRACKED],
         "flatten nested format_args!() and literals into a simplified format_args!() call \
         (default: yes)"),
+    fmt_debug: FmtDebug = (FmtDebug::Full, parse_fmt_debug, [TRACKED],
+        "how detailed `#[derive(Debug)]` should be. `full` prints types recursively, \
+        `shallow` prints only type names, `none` prints nothing and disables `{:?}`. (default: `full`)"),
     force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
         "force all crates to be `rustc_private` unstable (default: no)"),
     fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
@@ -1797,6 +1811,8 @@ options! {
         "link the `.rlink` file generated by `-Z no-link` (default: no)"),
     linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED],
         "a comma-separated list of linker features to enable (+) or disable (-): `lld`"),
+    lint_llvm_ir: bool = (false, parse_bool, [TRACKED],
+        "lint LLVM IR (default: no)"),
     lint_mir: bool = (false, parse_bool, [UNTRACKED],
         "lint MIR before and after each transformation"),
     llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index aba56732725..16f5e55835e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -536,6 +536,7 @@ symbols! {
         cfg_attr_multi,
         cfg_doctest,
         cfg_eval,
+        cfg_fmt_debug,
         cfg_hide,
         cfg_overflow_checks,
         cfg_panic,
@@ -895,6 +896,7 @@ symbols! {
         fmaf32,
         fmaf64,
         fmt,
+        fmt_debug,
         fmul_algebraic,
         fmul_fast,
         fn_align,
@@ -938,6 +940,7 @@ symbols! {
         fs_create_dir,
         fsub_algebraic,
         fsub_fast,
+        full,
         fundamental,
         fused_iterator,
         future,
@@ -1281,6 +1284,7 @@ symbols! {
         new_binary,
         new_const,
         new_debug,
+        new_debug_noop,
         new_display,
         new_lower_exp,
         new_lower_hex,
@@ -1715,6 +1719,7 @@ symbols! {
         semitransparent,
         sha512_sm_x86,
         shadow_call_stack,
+        shallow,
         shl,
         shl_assign,
         shorter_tail_lifetimes,
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
index bfd88bd042e..61226809e52 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
@@ -28,7 +28,7 @@ pub fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
             eh_frame_header: false,
-            supported_sanitizers: SanitizerSet::KERNELADDRESS,
+            supported_sanitizers: SanitizerSet::KERNELADDRESS | SanitizerSet::SHADOWCALLSTACK,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
index fa3f1eff457..b7444df04cd 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
@@ -27,7 +27,7 @@ pub fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
             eh_frame_header: false,
-            supported_sanitizers: SanitizerSet::KERNELADDRESS,
+            supported_sanitizers: SanitizerSet::KERNELADDRESS | SanitizerSet::SHADOWCALLSTACK,
             ..Default::default()
         },
     }
diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs
index 32d15c386cb..3f1c58bbd72 100644
--- a/library/core/benches/lib.rs
+++ b/library/core/benches/lib.rs
@@ -8,6 +8,7 @@
 #![feature(iter_array_chunks)]
 #![feature(iter_next_chunk)]
 #![feature(iter_advance_by)]
+#![feature(isqrt)]
 
 extern crate test;
 
diff --git a/library/core/benches/num/int_sqrt/mod.rs b/library/core/benches/num/int_sqrt/mod.rs
new file mode 100644
index 00000000000..3c9d173e456
--- /dev/null
+++ b/library/core/benches/num/int_sqrt/mod.rs
@@ -0,0 +1,62 @@
+use rand::Rng;
+use test::{black_box, Bencher};
+
+macro_rules! int_sqrt_bench {
+    ($t:ty, $predictable:ident, $random:ident, $random_small:ident, $random_uniform:ident) => {
+        #[bench]
+        fn $predictable(bench: &mut Bencher) {
+            bench.iter(|| {
+                for n in 0..(<$t>::BITS / 8) {
+                    for i in 1..=(100 as $t) {
+                        let x = black_box(i << (n * 8));
+                        black_box(x.isqrt());
+                    }
+                }
+            });
+        }
+
+        #[bench]
+        fn $random(bench: &mut Bencher) {
+            let mut rng = crate::bench_rng();
+            /* Exponentially distributed random numbers from the whole range of the type.  */
+            let numbers: Vec<$t> =
+                (0..256).map(|_| rng.gen::<$t>() >> rng.gen_range(0..<$t>::BITS)).collect();
+            bench.iter(|| {
+                for x in &numbers {
+                    black_box(black_box(x).isqrt());
+                }
+            });
+        }
+
+        #[bench]
+        fn $random_small(bench: &mut Bencher) {
+            let mut rng = crate::bench_rng();
+            /* Exponentially distributed random numbers from the range 0..256.  */
+            let numbers: Vec<$t> =
+                (0..256).map(|_| (rng.gen::<u8>() >> rng.gen_range(0..u8::BITS)) as $t).collect();
+            bench.iter(|| {
+                for x in &numbers {
+                    black_box(black_box(x).isqrt());
+                }
+            });
+        }
+
+        #[bench]
+        fn $random_uniform(bench: &mut Bencher) {
+            let mut rng = crate::bench_rng();
+            /* Exponentially distributed random numbers from the whole range of the type.  */
+            let numbers: Vec<$t> = (0..256).map(|_| rng.gen::<$t>()).collect();
+            bench.iter(|| {
+                for x in &numbers {
+                    black_box(black_box(x).isqrt());
+                }
+            });
+        }
+    };
+}
+
+int_sqrt_bench! {u8, u8_sqrt_predictable, u8_sqrt_random, u8_sqrt_random_small, u8_sqrt_uniform}
+int_sqrt_bench! {u16, u16_sqrt_predictable, u16_sqrt_random, u16_sqrt_random_small, u16_sqrt_uniform}
+int_sqrt_bench! {u32, u32_sqrt_predictable, u32_sqrt_random, u32_sqrt_random_small, u32_sqrt_uniform}
+int_sqrt_bench! {u64, u64_sqrt_predictable, u64_sqrt_random, u64_sqrt_random_small, u64_sqrt_uniform}
+int_sqrt_bench! {u128, u128_sqrt_predictable, u128_sqrt_random, u128_sqrt_random_small, u128_sqrt_uniform}
diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs
index c1dc3a30622..7ff7443cfa7 100644
--- a/library/core/benches/num/mod.rs
+++ b/library/core/benches/num/mod.rs
@@ -2,6 +2,7 @@ mod dec2flt;
 mod flt2dec;
 mod int_log;
 mod int_pow;
+mod int_sqrt;
 
 use std::str::FromStr;
 
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 65a4d537cc7..f29ac99b292 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -118,6 +118,10 @@ impl<'a> Argument<'a> {
         Self::new(x, Debug::fmt)
     }
     #[inline(always)]
+    pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'_> {
+        Self::new(x, |_, _| Ok(()))
+    }
+    #[inline(always)]
     pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> {
         Self::new(x, Octal::fmt)
     }
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 42461a3345b..878a911dde5 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1641,7 +1641,33 @@ macro_rules! int_impl {
             if self < 0 {
                 None
             } else {
-                Some((self as $UnsignedT).isqrt() as Self)
+                // SAFETY: Input is nonnegative in this `else` branch.
+                let result = unsafe {
+                    crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT
+                };
+
+                // Inform the optimizer what the range of outputs is. If
+                // testing `core` crashes with no panic message and a
+                // `num::int_sqrt::i*` test failed, it's because your edits
+                // caused these assertions to become false.
+                //
+                // SAFETY: Integer square root is a monotonically nondecreasing
+                // function, which means that increasing the input will never
+                // cause the output to decrease. Thus, since the input for
+                // nonnegative signed integers is bounded by
+                // `[0, <$ActualT>::MAX]`, sqrt(n) will be bounded by
+                // `[sqrt(0), sqrt(<$ActualT>::MAX)]`.
+                unsafe {
+                    // SAFETY: `<$ActualT>::MAX` is nonnegative.
+                    const MAX_RESULT: $SelfT = unsafe {
+                        crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT
+                    };
+
+                    crate::hint::assert_unchecked(result >= 0);
+                    crate::hint::assert_unchecked(result <= MAX_RESULT);
+                }
+
+                Some(result)
             }
         }
 
@@ -2862,15 +2888,11 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
+        #[track_caller]
         pub const fn isqrt(self) -> Self {
-            // I would like to implement it as
-            // ```
-            // self.checked_isqrt().expect("argument of integer square root must be non-negative")
-            // ```
-            // but `expect` is not yet stable as a `const fn`.
             match self.checked_isqrt() {
                 Some(sqrt) => sqrt,
-                None => panic!("argument of integer square root must be non-negative"),
+                None => crate::num::int_sqrt::panic_for_negative_argument(),
             }
         }
 
diff --git a/library/core/src/num/int_sqrt.rs b/library/core/src/num/int_sqrt.rs
new file mode 100644
index 00000000000..601e81f6993
--- /dev/null
+++ b/library/core/src/num/int_sqrt.rs
@@ -0,0 +1,316 @@
+//! These functions use the [Karatsuba square root algorithm][1] to compute the
+//! [integer square root](https://en.wikipedia.org/wiki/Integer_square_root)
+//! for the primitive integer types.
+//!
+//! The signed integer functions can only handle **nonnegative** inputs, so
+//! that must be checked before calling those.
+//!
+//! [1]: <https://web.archive.org/web/20230511212802/https://inria.hal.science/inria-00072854v1/file/RR-3805.pdf>
+//! "Paul Zimmermann. Karatsuba Square Root. \[Research Report\] RR-3805,
+//! INRIA. 1999, pp.8. (inria-00072854)"
+
+/// This array stores the [integer square roots](
+/// https://en.wikipedia.org/wiki/Integer_square_root) and remainders of each
+/// [`u8`](prim@u8) value. For example, `U8_ISQRT_WITH_REMAINDER[17]` will be
+/// `(4, 1)` because the integer square root of 17 is 4 and because 17 is 1
+/// higher than 4 squared.
+const U8_ISQRT_WITH_REMAINDER: [(u8, u8); 256] = {
+    let mut result = [(0, 0); 256];
+
+    let mut n: usize = 0;
+    let mut isqrt_n: usize = 0;
+    while n < result.len() {
+        result[n] = (isqrt_n as u8, (n - isqrt_n.pow(2)) as u8);
+
+        n += 1;
+        if n == (isqrt_n + 1).pow(2) {
+            isqrt_n += 1;
+        }
+    }
+
+    result
+};
+
+/// Returns the [integer square root](
+/// https://en.wikipedia.org/wiki/Integer_square_root) of any [`u8`](prim@u8)
+/// input.
+#[must_use = "this returns the result of the operation, \
+              without modifying the original"]
+#[inline]
+pub const fn u8(n: u8) -> u8 {
+    U8_ISQRT_WITH_REMAINDER[n as usize].0
+}
+
+/// Generates an `i*` function that returns the [integer square root](
+/// https://en.wikipedia.org/wiki/Integer_square_root) of any **nonnegative**
+/// input of a specific signed integer type.
+macro_rules! signed_fn {
+    ($SignedT:ident, $UnsignedT:ident) => {
+        /// Returns the [integer square root](
+        /// https://en.wikipedia.org/wiki/Integer_square_root) of any
+        /// **nonnegative**
+        #[doc = concat!("[`", stringify!($SignedT), "`](prim@", stringify!($SignedT), ")")]
+        /// input.
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when the input is negative.
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn $SignedT(n: $SignedT) -> $SignedT {
+            debug_assert!(n >= 0, "Negative input inside `isqrt`.");
+            $UnsignedT(n as $UnsignedT) as $SignedT
+        }
+    };
+}
+
+signed_fn!(i8, u8);
+signed_fn!(i16, u16);
+signed_fn!(i32, u32);
+signed_fn!(i64, u64);
+signed_fn!(i128, u128);
+
+/// Generates a `u*` function that returns the [integer square root](
+/// https://en.wikipedia.org/wiki/Integer_square_root) of any input of
+/// a specific unsigned integer type.
+macro_rules! unsigned_fn {
+    ($UnsignedT:ident, $HalfBitsT:ident, $stages:ident) => {
+        /// Returns the [integer square root](
+        /// https://en.wikipedia.org/wiki/Integer_square_root) of any
+        #[doc = concat!("[`", stringify!($UnsignedT), "`](prim@", stringify!($UnsignedT), ")")]
+        /// input.
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT {
+            if n <= <$HalfBitsT>::MAX as $UnsignedT {
+                $HalfBitsT(n as $HalfBitsT) as $UnsignedT
+            } else {
+                // The normalization shift satisfies the Karatsuba square root
+                // algorithm precondition "a₃ ≥ b/4" where a₃ is the most
+                // significant quarter of `n`'s bits and b is the number of
+                // values that can be represented by that quarter of the bits.
+                //
+                // b/4 would then be all 0s except the second most significant
+                // bit (010...0) in binary. Since a₃ must be at least b/4, a₃'s
+                // most significant bit or its neighbor must be a 1. Since a₃'s
+                // most significant bits are `n`'s most significant bits, the
+                // same applies to `n`.
+                //
+                // The reason to shift by an even number of bits is because an
+                // even number of bits produces the square root shifted to the
+                // left by half of the normalization shift:
+                //
+                // sqrt(n << (2 * p))
+                // sqrt(2.pow(2 * p) * n)
+                // sqrt(2.pow(2 * p)) * sqrt(n)
+                // 2.pow(p) * sqrt(n)
+                // sqrt(n) << p
+                //
+                // Shifting by an odd number of bits leaves an ugly sqrt(2)
+                // multiplied in:
+                //
+                // sqrt(n << (2 * p + 1))
+                // sqrt(2.pow(2 * p + 1) * n)
+                // sqrt(2 * 2.pow(2 * p) * n)
+                // sqrt(2) * sqrt(2.pow(2 * p)) * sqrt(n)
+                // sqrt(2) * 2.pow(p) * sqrt(n)
+                // sqrt(2) * (sqrt(n) << p)
+                const EVEN_MAKING_BITMASK: u32 = !1;
+                let normalization_shift = n.leading_zeros() & EVEN_MAKING_BITMASK;
+                n <<= normalization_shift;
+
+                let s = $stages(n);
+
+                let denormalization_shift = normalization_shift >> 1;
+                s >> denormalization_shift
+            }
+        }
+    };
+}
+
+/// Generates the first stage of the computation after normalization.
+///
+/// # Safety
+///
+/// `$n` must be nonzero.
+macro_rules! first_stage {
+    ($original_bits:literal, $n:ident) => {{
+        debug_assert!($n != 0, "`$n` is  zero in `first_stage!`.");
+
+        const N_SHIFT: u32 = $original_bits - 8;
+        let n = $n >> N_SHIFT;
+
+        let (s, r) = U8_ISQRT_WITH_REMAINDER[n as usize];
+
+        // Inform the optimizer that `s` is nonzero. This will allow it to
+        // avoid generating code to handle division-by-zero panics in the next
+        // stage.
+        //
+        // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn`
+        // macro recurses instead of continuing to this point, so the original
+        // `$n` wasn't a 0 if we've reached here.
+        //
+        // Then the `unsigned_fn` macro normalizes `$n` so that at least one of
+        // its two most-significant bits is a 1.
+        //
+        // Then this stage puts the eight most-significant bits of `$n` into
+        // `n`. This means that `n` here has at least one 1 bit in its two
+        // most-significant bits, making `n` nonzero.
+        //
+        // `U8_ISQRT_WITH_REMAINDER[n as usize]` will give a nonzero `s` when
+        // given a nonzero `n`.
+        unsafe { crate::hint::assert_unchecked(s != 0) };
+        (s, r)
+    }};
+}
+
+/// Generates a middle stage of the computation.
+///
+/// # Safety
+///
+/// `$s` must be nonzero.
+macro_rules! middle_stage {
+    ($original_bits:literal, $ty:ty, $n:ident, $s:ident, $r:ident) => {{
+        debug_assert!($s != 0, "`$s` is  zero in `middle_stage!`.");
+
+        const N_SHIFT: u32 = $original_bits - <$ty>::BITS;
+        let n = ($n >> N_SHIFT) as $ty;
+
+        const HALF_BITS: u32 = <$ty>::BITS >> 1;
+        const QUARTER_BITS: u32 = <$ty>::BITS >> 2;
+        const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1;
+        const LOWEST_QUARTER_1_BITS: $ty = (1 << QUARTER_BITS) - 1;
+
+        let lo = n & LOWER_HALF_1_BITS;
+        let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS);
+        let denominator = ($s as $ty) << 1;
+        let q = numerator / denominator;
+        let u = numerator % denominator;
+
+        let mut s = ($s << QUARTER_BITS) as $ty + q;
+        let (mut r, overflow) =
+            ((u << QUARTER_BITS) | (lo & LOWEST_QUARTER_1_BITS)).overflowing_sub(q * q);
+        if overflow {
+            r = r.wrapping_add(2 * s - 1);
+            s -= 1;
+        }
+
+        // Inform the optimizer that `s` is nonzero. This will allow it to
+        // avoid generating code to handle division-by-zero panics in the next
+        // stage.
+        //
+        // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn`
+        // macro recurses instead of continuing to this point, so the original
+        // `$n` wasn't a 0 if we've reached here.
+        //
+        // Then the `unsigned_fn` macro normalizes `$n` so that at least one of
+        // its two most-significant bits is a 1.
+        //
+        // Then these stages take as many of the most-significant bits of `$n`
+        // as will fit in this stage's type. For example, the stage that
+        // handles `u32` deals with the 32 most-significant bits of `$n`. This
+        // means that each stage has at least one 1 bit in `n`'s two
+        // most-significant bits, making `n` nonzero.
+        //
+        // Then this stage will produce the correct integer square root for
+        // that `n` value. Since `n` is nonzero, `s` will also be nonzero.
+        unsafe { crate::hint::assert_unchecked(s != 0) };
+        (s, r)
+    }};
+}
+
+/// Generates the last stage of the computation before denormalization.
+///
+/// # Safety
+///
+/// `$s` must be nonzero.
+macro_rules! last_stage {
+    ($ty:ty, $n:ident, $s:ident, $r:ident) => {{
+        debug_assert!($s != 0, "`$s` is  zero in `last_stage!`.");
+
+        const HALF_BITS: u32 = <$ty>::BITS >> 1;
+        const QUARTER_BITS: u32 = <$ty>::BITS >> 2;
+        const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1;
+
+        let lo = $n & LOWER_HALF_1_BITS;
+        let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS);
+        let denominator = ($s as $ty) << 1;
+
+        let q = numerator / denominator;
+        let mut s = ($s << QUARTER_BITS) as $ty + q;
+        let (s_squared, overflow) = s.overflowing_mul(s);
+        if overflow || s_squared > $n {
+            s -= 1;
+        }
+        s
+    }};
+}
+
+/// Takes the normalized [`u16`](prim@u16) input and gets its normalized
+/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root).
+///
+/// # Safety
+///
+/// `n` must be nonzero.
+#[inline]
+const fn u16_stages(n: u16) -> u16 {
+    let (s, r) = first_stage!(16, n);
+    last_stage!(u16, n, s, r)
+}
+
+/// Takes the normalized [`u32`](prim@u32) input and gets its normalized
+/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root).
+///
+/// # Safety
+///
+/// `n` must be nonzero.
+#[inline]
+const fn u32_stages(n: u32) -> u32 {
+    let (s, r) = first_stage!(32, n);
+    let (s, r) = middle_stage!(32, u16, n, s, r);
+    last_stage!(u32, n, s, r)
+}
+
+/// Takes the normalized [`u64`](prim@u64) input and gets its normalized
+/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root).
+///
+/// # Safety
+///
+/// `n` must be nonzero.
+#[inline]
+const fn u64_stages(n: u64) -> u64 {
+    let (s, r) = first_stage!(64, n);
+    let (s, r) = middle_stage!(64, u16, n, s, r);
+    let (s, r) = middle_stage!(64, u32, n, s, r);
+    last_stage!(u64, n, s, r)
+}
+
+/// Takes the normalized [`u128`](prim@u128) input and gets its normalized
+/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root).
+///
+/// # Safety
+///
+/// `n` must be nonzero.
+#[inline]
+const fn u128_stages(n: u128) -> u128 {
+    let (s, r) = first_stage!(128, n);
+    let (s, r) = middle_stage!(128, u16, n, s, r);
+    let (s, r) = middle_stage!(128, u32, n, s, r);
+    let (s, r) = middle_stage!(128, u64, n, s, r);
+    last_stage!(u128, n, s, r)
+}
+
+unsigned_fn!(u16, u8, u16_stages);
+unsigned_fn!(u32, u16, u32_stages);
+unsigned_fn!(u64, u32, u64_stages);
+unsigned_fn!(u128, u64, u128_stages);
+
+/// Instantiate this panic logic once, rather than for all the isqrt methods
+/// on every single primitive type.
+#[cold]
+#[track_caller]
+pub const fn panic_for_negative_argument() -> ! {
+    panic!("argument of integer square root cannot be negative")
+}
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 309e1ba958a..e9e5324666a 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -41,6 +41,7 @@ mod uint_macros; // import uint_impl!
 
 mod error;
 mod int_log10;
+mod int_sqrt;
 mod nonzero;
 mod overflow_panic;
 mod saturating;
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index c6e9c249048..8b888f12da0 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -7,7 +7,7 @@ use crate::marker::{Freeze, StructuralPartialEq};
 use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
 use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::str::FromStr;
-use crate::{fmt, hint, intrinsics, ptr, ub_checks};
+use crate::{fmt, intrinsics, ptr, ub_checks};
 
 /// A marker trait for primitive types which can be zero.
 ///
@@ -1545,31 +1545,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
                       without modifying the original"]
         #[inline]
         pub const fn isqrt(self) -> Self {
-            // The algorithm is based on the one presented in
-            // <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)>
-            // which cites as source the following C code:
-            // <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>.
-
-            let mut op = self.get();
-            let mut res = 0;
-            let mut one = 1 << (self.ilog2() & !1);
-
-            while one != 0 {
-                if op >= res + one {
-                    op -= res + one;
-                    res = (res >> 1) + one;
-                } else {
-                    res >>= 1;
-                }
-                one >>= 2;
-            }
+            let result = self.get().isqrt();
 
-            // SAFETY: The result fits in an integer with half as many bits.
-            // Inform the optimizer about it.
-            unsafe { hint::assert_unchecked(res < 1 << (Self::BITS / 2)) };
-
-            // SAFETY: The square root of an integer >= 1 is always >= 1.
-            unsafe { Self::new_unchecked(res) }
+            // SAFETY: Integer square root is a monotonically nondecreasing
+            // function, which means that increasing the input will never cause
+            // the output to decrease. Thus, since the input for nonzero
+            // unsigned integers has a lower bound of 1, the lower bound of the
+            // results will be sqrt(1), which is 1, so a result can't be zero.
+            unsafe { Self::new_unchecked(result) }
         }
     };
 
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 0d0bbc5256f..d9036abecc5 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2762,10 +2762,24 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline]
         pub const fn isqrt(self) -> Self {
-            match NonZero::new(self) {
-                Some(x) => x.isqrt().get(),
-                None => 0,
+            let result = crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT;
+
+            // Inform the optimizer what the range of outputs is. If testing
+            // `core` crashes with no panic message and a `num::int_sqrt::u*`
+            // test failed, it's because your edits caused these assertions or
+            // the assertions in `fn isqrt` of `nonzero.rs` to become false.
+            //
+            // SAFETY: Integer square root is a monotonically nondecreasing
+            // function, which means that increasing the input will never
+            // cause the output to decrease. Thus, since the input for unsigned
+            // integers is bounded by `[0, <$ActualT>::MAX]`, sqrt(n) will be
+            // bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]`.
+            unsafe {
+                const MAX_RESULT: $SelfT = crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT;
+                crate::hint::assert_unchecked(result <= MAX_RESULT);
             }
+
+            result
         }
 
         /// Performs Euclidean division.
diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs
index 7cd3b54e3f3..830a96204ca 100644
--- a/library/core/tests/num/int_macros.rs
+++ b/library/core/tests/num/int_macros.rs
@@ -289,38 +289,6 @@ macro_rules! int_module {
         }
 
         #[test]
-        fn test_isqrt() {
-            assert_eq!($T::MIN.checked_isqrt(), None);
-            assert_eq!((-1 as $T).checked_isqrt(), None);
-            assert_eq!((0 as $T).isqrt(), 0 as $T);
-            assert_eq!((1 as $T).isqrt(), 1 as $T);
-            assert_eq!((2 as $T).isqrt(), 1 as $T);
-            assert_eq!((99 as $T).isqrt(), 9 as $T);
-            assert_eq!((100 as $T).isqrt(), 10 as $T);
-        }
-
-        #[cfg(not(miri))] // Miri is too slow
-        #[test]
-        fn test_lots_of_isqrt() {
-            let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T;
-            for n in 0..=n_max {
-                let isqrt: $T = n.isqrt();
-
-                assert!(isqrt.pow(2) <= n);
-                let (square, overflow) = (isqrt + 1).overflowing_pow(2);
-                assert!(overflow || square > n);
-            }
-
-            for n in ($T::MAX - 127)..=$T::MAX {
-                let isqrt: $T = n.isqrt();
-
-                assert!(isqrt.pow(2) <= n);
-                let (square, overflow) = (isqrt + 1).overflowing_pow(2);
-                assert!(overflow || square > n);
-            }
-        }
-
-        #[test]
         fn test_div_floor() {
             let a: $T = 8;
             let b = 3;
diff --git a/library/core/tests/num/int_sqrt.rs b/library/core/tests/num/int_sqrt.rs
new file mode 100644
index 00000000000..d68db0787d2
--- /dev/null
+++ b/library/core/tests/num/int_sqrt.rs
@@ -0,0 +1,248 @@
+macro_rules! tests {
+    ($isqrt_consistency_check_fn_macro:ident : $($T:ident)+) => {
+        $(
+            mod $T {
+                $isqrt_consistency_check_fn_macro!($T);
+
+                // Check that the following produce the correct values from
+                // `isqrt`:
+                //
+                // * the first and last 128 nonnegative values
+                // * powers of two, minus one
+                // * powers of two
+                //
+                // For signed types, check that `checked_isqrt` and `isqrt`
+                // either produce the same numeric value or respectively
+                // produce `None` and a panic. Make sure to do a consistency
+                // check for `<$T>::MIN` as well, as no nonnegative values
+                // negate to it.
+                //
+                // For unsigned types check that `isqrt` produces the same
+                // numeric value for `$T` and `NonZero<$T>`.
+                #[test]
+                fn isqrt() {
+                    isqrt_consistency_check(<$T>::MIN);
+
+                    for n in (0..=127)
+                        .chain(<$T>::MAX - 127..=<$T>::MAX)
+                        .chain((0..<$T>::MAX.count_ones()).map(|exponent| (1 << exponent) - 1))
+                        .chain((0..<$T>::MAX.count_ones()).map(|exponent| 1 << exponent))
+                    {
+                        isqrt_consistency_check(n);
+
+                        let isqrt_n = n.isqrt();
+                        assert!(
+                            isqrt_n
+                                .checked_mul(isqrt_n)
+                                .map(|isqrt_n_squared| isqrt_n_squared <= n)
+                                .unwrap_or(false),
+                            "`{n}.isqrt()` should be lower than {isqrt_n}."
+                        );
+                        assert!(
+                            (isqrt_n + 1)
+                                .checked_mul(isqrt_n + 1)
+                                .map(|isqrt_n_plus_1_squared| n < isqrt_n_plus_1_squared)
+                                .unwrap_or(true),
+                            "`{n}.isqrt()` should be higher than {isqrt_n})."
+                        );
+                    }
+                }
+
+                // Check the square roots of:
+                //
+                // * the first 1,024 perfect squares
+                // * halfway between each of the first 1,024 perfect squares
+                //   and the next perfect square
+                // * the next perfect square after the each of the first 1,024
+                //   perfect squares, minus one
+                // * the last 1,024 perfect squares
+                // * the last 1,024 perfect squares, minus one
+                // * halfway between each of the last 1,024 perfect squares
+                //   and the previous perfect square
+                #[test]
+                // Skip this test on Miri, as it takes too long to run.
+                #[cfg(not(miri))]
+                fn isqrt_extended() {
+                    // The correct value is worked out by using the fact that
+                    // the nth nonzero perfect square is the sum of the first n
+                    // odd numbers:
+                    //
+                    //  1 = 1
+                    //  4 = 1 + 3
+                    //  9 = 1 + 3 + 5
+                    // 16 = 1 + 3 + 5 + 7
+                    //
+                    // Note also that the last odd number added in is two times
+                    // the square root of the previous perfect square, plus
+                    // one:
+                    //
+                    // 1 = 2*0 + 1
+                    // 3 = 2*1 + 1
+                    // 5 = 2*2 + 1
+                    // 7 = 2*3 + 1
+                    //
+                    // That means we can add the square root of this perfect
+                    // square once to get about halfway to the next perfect
+                    // square, then we can add the square root of this perfect
+                    // square again to get to the next perfect square, minus
+                    // one, then we can add one to get to the next perfect
+                    // square.
+                    //
+                    // This allows us to, for each of the first 1,024 perfect
+                    // squares, test that the square roots of the following are
+                    // all correct and equal to each other:
+                    //
+                    // * the current perfect square
+                    // * about halfway to the next perfect square
+                    // * the next perfect square, minus one
+                    let mut n: $T = 0;
+                    for sqrt_n in 0..1_024.min((1_u128 << (<$T>::MAX.count_ones()/2)) - 1) as $T {
+                        isqrt_consistency_check(n);
+                        assert_eq!(
+                            n.isqrt(),
+                            sqrt_n,
+                            "`{sqrt_n}.pow(2).isqrt()` should be {sqrt_n}."
+                        );
+
+                        n += sqrt_n;
+                        isqrt_consistency_check(n);
+                        assert_eq!(
+                            n.isqrt(),
+                            sqrt_n,
+                            "{n} is about halfway between `{sqrt_n}.pow(2)` and `{}.pow(2)`, so `{n}.isqrt()` should be {sqrt_n}.",
+                            sqrt_n + 1
+                        );
+
+                        n += sqrt_n;
+                        isqrt_consistency_check(n);
+                        assert_eq!(
+                            n.isqrt(),
+                            sqrt_n,
+                            "`({}.pow(2) - 1).isqrt()` should be {sqrt_n}.",
+                            sqrt_n + 1
+                        );
+
+                        n += 1;
+                    }
+
+                    // Similarly, for each of the last 1,024 perfect squares,
+                    // check:
+                    //
+                    // * the current perfect square
+                    // * the current perfect square, minus one
+                    // * about halfway to the previous perfect square
+                    //
+                    // `MAX`'s `isqrt` return value is verified in the `isqrt`
+                    // test function above.
+                    let maximum_sqrt = <$T>::MAX.isqrt();
+                    let mut n = maximum_sqrt * maximum_sqrt;
+
+                    for sqrt_n in (maximum_sqrt - 1_024.min((1_u128 << (<$T>::MAX.count_ones()/2)) - 1) as $T..maximum_sqrt).rev() {
+                        isqrt_consistency_check(n);
+                        assert_eq!(
+                            n.isqrt(),
+                            sqrt_n + 1,
+                            "`{0}.pow(2).isqrt()` should be {0}.",
+                            sqrt_n + 1
+                        );
+
+                        n -= 1;
+                        isqrt_consistency_check(n);
+                        assert_eq!(
+                            n.isqrt(),
+                            sqrt_n,
+                            "`({}.pow(2) - 1).isqrt()` should be {sqrt_n}.",
+                            sqrt_n + 1
+                        );
+
+                        n -= sqrt_n;
+                        isqrt_consistency_check(n);
+                        assert_eq!(
+                            n.isqrt(),
+                            sqrt_n,
+                            "{n} is about halfway between `{sqrt_n}.pow(2)` and `{}.pow(2)`, so `{n}.isqrt()` should be {sqrt_n}.",
+                            sqrt_n + 1
+                        );
+
+                        n -= sqrt_n;
+                    }
+                }
+            }
+        )*
+    };
+}
+
+macro_rules! signed_check {
+    ($T:ident) => {
+        /// This takes an input and, if it's nonnegative or
+        #[doc = concat!("`", stringify!($T), "::MIN`,")]
+        /// checks that `isqrt` and `checked_isqrt` produce equivalent results
+        /// for that input and for the negative of that input.
+        ///
+        /// # Note
+        ///
+        /// This cannot check that negative inputs to `isqrt` cause panics if
+        /// panics abort instead of unwind.
+        fn isqrt_consistency_check(n: $T) {
+            // `<$T>::MIN` will be negative, so ignore it in this nonnegative
+            // section.
+            if n >= 0 {
+                assert_eq!(
+                    Some(n.isqrt()),
+                    n.checked_isqrt(),
+                    "`{n}.checked_isqrt()` should match `Some({n}.isqrt())`.",
+                );
+            }
+
+            // `wrapping_neg` so that `<$T>::MIN` will negate to itself rather
+            // than panicking.
+            let negative_n = n.wrapping_neg();
+
+            // Zero negated will still be nonnegative, so ignore it in this
+            // negative section.
+            if negative_n < 0 {
+                assert_eq!(
+                    negative_n.checked_isqrt(),
+                    None,
+                    "`({negative_n}).checked_isqrt()` should be `None`, as {negative_n} is negative.",
+                );
+
+                // `catch_unwind` only works when panics unwind rather than abort.
+                #[cfg(panic = "unwind")]
+                {
+                    std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| (-n).isqrt())).expect_err(
+                        &format!("`({negative_n}).isqrt()` should have panicked, as {negative_n} is negative.")
+                    );
+                }
+            }
+        }
+    };
+}
+
+macro_rules! unsigned_check {
+    ($T:ident) => {
+        /// This takes an input and, if it's nonzero, checks that `isqrt`
+        /// produces the same numeric value for both
+        #[doc = concat!("`", stringify!($T), "` and ")]
+        #[doc = concat!("`NonZero<", stringify!($T), ">`.")]
+        fn isqrt_consistency_check(n: $T) {
+            // Zero cannot be turned into a `NonZero` value, so ignore it in
+            // this nonzero section.
+            if n > 0 {
+                assert_eq!(
+                    n.isqrt(),
+                    core::num::NonZero::<$T>::new(n)
+                        .expect(
+                            "Was not able to create a new `NonZero` value from a nonzero number."
+                        )
+                        .isqrt()
+                        .get(),
+                    "`{n}.isqrt` should match `NonZero`'s `{n}.isqrt().get()`.",
+                );
+            }
+        }
+    };
+}
+
+tests!(signed_check: i8 i16 i32 i64 i128);
+tests!(unsigned_check: u8 u16 u32 u64 u128);
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index dad46ad88fe..b14fe0b22c3 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -27,6 +27,7 @@ mod const_from;
 mod dec2flt;
 mod flt2dec;
 mod int_log;
+mod int_sqrt;
 mod ops;
 mod wrapping;
 
diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md
index dfc4871b924..992f14a79bf 100644
--- a/src/doc/rustc/src/check-cfg.md
+++ b/src/doc/rustc/src/check-cfg.md
@@ -99,7 +99,7 @@ the need to specify them manually.
 Well known names and values are implicitly added as long as at least one `--check-cfg` argument
 is present.
 
-As of `2024-05-06T`, the list of known names is as follows:
+As of `2024-08-20T`, the list of known names is as follows:
 
 <!--- See CheckCfg::fill_well_known in compiler/rustc_session/src/config.rs -->
 
@@ -107,6 +107,7 @@ As of `2024-05-06T`, the list of known names is as follows:
  - `debug_assertions`
  - `doc`
  - `doctest`
+ - `fmt_debug`
  - `miri`
  - `overflow_checks`
  - `panic`
diff --git a/src/doc/unstable-book/src/compiler-flags/fmt-debug.md b/src/doc/unstable-book/src/compiler-flags/fmt-debug.md
new file mode 100644
index 00000000000..bb8663dceae
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/fmt-debug.md
@@ -0,0 +1,15 @@
+# `fmt-debug`
+
+The tracking issue for this feature is: [#129709](https://github.com/rust-lang/rust/issues/129709).
+
+------------------------
+
+Option `-Z fmt-debug=val` controls verbosity of derived `Debug` implementations
+and debug formatting in format strings (`{:?}`).
+
+* `full` — `#[derive(Debug)]` prints types recursively. This is the default behavior.
+
+* `shallow` — `#[derive(Debug)]` prints only the type name, or name of a variant of a fieldless enums. Details of the `Debug` implementation are not stable and may change in the future. Behavior of custom `fmt::Debug` implementations is not affected.
+
+* `none` — `#[derive(Debug)]` does not print anything at all. `{:?}` in formatting strings has no effect.
+  This option may reduce size of binaries, and remove occurrences of type names in the binary that are not removed by striping symbols. However, it may also cause `panic!` and `assert!` messages to be incomplete.
diff --git a/src/doc/unstable-book/src/compiler-flags/lint-llvm-ir.md b/src/doc/unstable-book/src/compiler-flags/lint-llvm-ir.md
new file mode 100644
index 00000000000..7b99c25a694
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/lint-llvm-ir.md
@@ -0,0 +1,7 @@
+# `lint-llvm-ir`
+
+---------------------
+
+This flag will add `LintPass` to the start of the pipeline.
+You can use it to check for common errors in the LLVM IR generated by `rustc`.
+You can add `-Cllvm-args=-lint-abort-on-error` to abort the process if errors were found.
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index edc63a25ac1..24940f0d6fb 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -775,22 +775,47 @@ See the [Clang SafeStack documentation][clang-safestack] for more details.
 
 # ShadowCallStack
 
-ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack' and loading the return address from that shadow call stack.
-
-ShadowCallStack requires a platform ABI which reserves `x18` as the instrumentation makes use of this register.
+ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack'
+and loading the return address from that shadow call stack.
+AArch64 and RISC-V both have a platform register defined in their ABIs, which is `x18` and `x3`/`gp` respectively, that can optionally be reserved for this purpose.
+Software support from the operating system and runtime may be required depending on the target platform which is detailed in the remaining section.
+See the [Clang ShadowCallStack documentation][clang-scs] for more details.
 
 ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and is supported on the following targets:
 
-* `aarch64-linux-android`
+## AArch64 family
 
-A runtime must be provided by the application or operating system.
+ShadowCallStack requires the use of the ABI defined platform register, `x18`, which is required for code generation purposes.
+When `x18` is not reserved, and is instead used as a scratch register subsequently, enabling ShadowCallStack would lead to undefined behaviour
+due to corruption of return address or invalid memory access when the instrumentation restores return register to the link register `lr` from the
+already clobbered `x18` register.
+In other words, code that is calling into or called by functions instrumented with ShadowCallStack must reserve the `x18` register or preserve its value.
 
-See the [Clang ShadowCallStack documentation][clang-scs] for more details.
+### `aarch64-linux-android` and `aarch64-unknown-fuchsia`/`aarch64-fuchsia`
 
-* `aarch64-unknown-none`
+This target already reserves the `x18` register.
+A runtime must be provided by the application or operating system.
+If `bionic` is used on this target, the software support is provided.
+Otherwise, a runtime needs to prepare a memory region and points `x18` to the region which serves as the shadow call stack.
+
+### `aarch64-unknown-none`
 
 In addition to support from a runtime by the application or operating system, the `-Zfixed-x18` flag is also mandatory.
 
+## RISC-V 64 family
+
+ShadowCallStack uses either the `gp` register for software shadow stack, also known as `x3`, or the `ssp` register if [`Zicfiss`][riscv-zicfiss] extension is available.
+`gp`/`x3` is currently always reserved and available for ShadowCallStack instrumentation, and `ssp` in case of `Zicfiss` is only accessible through its dedicated shadow stack instructions.
+
+Support from the runtime and operating system is required when `gp`/`x3` is used for software shadow stack.
+A runtime must prepare a memory region and point `gp`/`x3` to the region before executing the code.
+
+The following targets support ShadowCallStack.
+
+* `riscv64imac-unknown-none-elf`
+* `riscv64gc-unknown-none-elf`
+* `riscv64gc-unknown-fuchsia`
+
 # ThreadSanitizer
 
 ThreadSanitizer is a data race detection tool. It is supported on the following
@@ -912,3 +937,4 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
 [linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html
 [llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html
+[riscv-zicfiss]: https://github.com/riscv/riscv-cfi/blob/3f8e450c481ac303bd5643444f7a89672f24476e/src/cfi_backward.adoc
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index f46ffea830e..577b10a31ae 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -341,7 +341,7 @@ fn clean_region_outlives_constraints<'tcx>(
                 .map(|&region| {
                     let lifetime = early_bound_region_name(region)
                         .inspect(|name| assert!(region_params.contains(name)))
-                        .map(|name| Lifetime(name))
+                        .map(Lifetime)
                         .unwrap_or(Lifetime::statik());
                     clean::GenericBound::Outlives(lifetime)
                 })
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 48c3fb65203..96e7f5c61c3 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -24,7 +24,7 @@ pub(crate) fn synthesize_blanket_impls(
     let mut blanket_impls = Vec::new();
     for trait_def_id in tcx.all_traits() {
         if !cx.cache.effective_visibilities.is_reachable(tcx, trait_def_id)
-            || cx.generated_synthetics.get(&(ty.skip_binder(), trait_def_id)).is_some()
+            || cx.generated_synthetics.contains(&(ty.skip_binder(), trait_def_id))
         {
             continue;
         }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index f8953f0ebcf..962a5a05737 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -54,7 +54,7 @@ pub(crate) fn try_inline(
     debug!("attrs={attrs:?}");
 
     let attrs_without_docs = attrs.map(|(attrs, def_id)| {
-        (attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id)
+        (attrs.iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id)
     });
     let attrs_without_docs =
         attrs_without_docs.as_ref().map(|(attrs, def_id)| (&attrs[..], *def_id));
@@ -288,10 +288,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
     clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
 }
 
-pub(crate) fn build_function<'tcx>(
-    cx: &mut DocContext<'tcx>,
-    def_id: DefId,
-) -> Box<clean::Function> {
+pub(crate) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
     let sig = cx.tcx.fn_sig(def_id).instantiate_identity();
     // The generics need to be cleaned before the signature.
     let mut generics =
@@ -425,7 +422,7 @@ pub(crate) fn merge_attrs(
             both.cfg(cx.tcx, &cx.cache.hidden_cfg),
         )
     } else {
-        (Attributes::from_ast(&old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
+        (Attributes::from_ast(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
     }
 }
 
@@ -791,16 +788,15 @@ fn build_macro(
 /// implementation for `AssociatedType`
 fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
     for pred in &mut g.where_predicates {
-        match *pred {
-            clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => {
-                bounds.retain(|bound| match bound {
-                    clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
-                        trait_.def_id() != trait_did
-                    }
-                    _ => true,
-                });
-            }
-            _ => {}
+        if let clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } =
+            *pred
+        {
+            bounds.retain(|bound| match bound {
+                clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
+                    trait_.def_id() != trait_did
+                }
+                _ => true,
+            });
         }
     }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5260e363dd6..3cb02f379e4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -266,7 +266,7 @@ fn clean_poly_trait_ref_with_constraints<'tcx>(
     )
 }
 
-fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
+fn clean_lifetime(lifetime: &hir::Lifetime, cx: &mut DocContext<'_>) -> Lifetime {
     if let Some(
         rbv::ResolvedArg::EarlyBound(did)
         | rbv::ResolvedArg::LateBound(_, _, did)
@@ -274,7 +274,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
     ) = cx.tcx.named_bound_var(lifetime.hir_id)
         && let Some(lt) = cx.args.get(&did.to_def_id()).and_then(|arg| arg.as_lt())
     {
-        return lt.clone();
+        return *lt;
     }
     Lifetime(lifetime.ident.name)
 }
@@ -285,7 +285,7 @@ pub(crate) fn clean_const<'tcx>(
 ) -> ConstantKind {
     match &constant.kind {
         hir::ConstArgKind::Path(qpath) => {
-            ConstantKind::Path { path: qpath_to_string(&qpath).into() }
+            ConstantKind::Path { path: qpath_to_string(qpath).into() }
         }
         hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
     }
@@ -299,7 +299,7 @@ pub(crate) fn clean_middle_const<'tcx>(
     ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }
 }
 
-pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
+pub(crate) fn clean_middle_region(region: ty::Region<'_>) -> Option<Lifetime> {
     match *region {
         ty::ReStatic => Some(Lifetime::statik()),
         _ if !region.has_name() => None,
@@ -389,8 +389,8 @@ fn clean_poly_trait_predicate<'tcx>(
     })
 }
 
-fn clean_region_outlives_predicate<'tcx>(
-    pred: ty::RegionOutlivesPredicate<'tcx>,
+fn clean_region_outlives_predicate(
+    pred: ty::RegionOutlivesPredicate<'_>,
 ) -> Option<WherePredicate> {
     let ty::OutlivesPredicate(a, b) = pred;
 
@@ -513,10 +513,10 @@ fn projection_to_path_segment<'tcx>(
     }
 }
 
-fn clean_generic_param_def<'tcx>(
+fn clean_generic_param_def(
     def: &ty::GenericParamDef,
     defaults: ParamDefaults,
-    cx: &mut DocContext<'tcx>,
+    cx: &mut DocContext<'_>,
 ) -> GenericParamDef {
     let (name, kind) = match def.kind {
         ty::GenericParamDefKind::Lifetime => {
@@ -1303,10 +1303,7 @@ pub(crate) fn clean_impl_item<'tcx>(
     })
 }
 
-pub(crate) fn clean_middle_assoc_item<'tcx>(
-    assoc_item: &ty::AssocItem,
-    cx: &mut DocContext<'tcx>,
-) -> Item {
+pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocContext<'_>) -> Item {
     let tcx = cx.tcx;
     let kind = match assoc_item.kind {
         ty::AssocKind::Const => {
@@ -1459,7 +1456,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                                 // which only has one associated type, which is not a GAT, so whatever.
                             }
                         }
-                        bounds.extend(mem::replace(pred_bounds, Vec::new()));
+                        bounds.extend(mem::take(pred_bounds));
                         false
                     }
                     _ => true,
@@ -1661,7 +1658,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
                 expanded
             } else {
                 // First we check if it's a private re-export.
-                let path = if let Some(path) = first_non_private(cx, hir_id, &path) {
+                let path = if let Some(path) = first_non_private(cx, hir_id, path) {
                     path
                 } else {
                     clean_path(path, cx)
@@ -1796,7 +1793,7 @@ fn maybe_expand_private_type_alias<'tcx>(
     }
 
     Some(cx.enter_alias(args, def_id.to_def_id(), |cx| {
-        cx.with_param_env(def_id.to_def_id(), |cx| clean_ty(&ty, cx))
+        cx.with_param_env(def_id.to_def_id(), |cx| clean_ty(ty, cx))
     }))
 }
 
@@ -1806,8 +1803,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
     match ty.kind {
         TyKind::Never => Primitive(PrimitiveType::Never),
         TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))),
-        TyKind::Ref(ref l, ref m) => {
-            let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) };
+        TyKind::Ref(l, ref m) => {
+            let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(l, cx)) };
             BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
         }
         TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),
@@ -1843,17 +1840,17 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
         TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
         TyKind::OpaqueDef(item_id, _, _) => {
             let item = cx.tcx.hir().item(item_id);
-            if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
+            if let hir::ItemKind::OpaqueTy(ty) = item.kind {
                 ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
             } else {
                 unreachable!()
             }
         }
         TyKind::Path(_) => clean_qpath(ty, cx),
-        TyKind::TraitObject(bounds, ref lifetime, _) => {
+        TyKind::TraitObject(bounds, lifetime, _) => {
             let bounds = bounds.iter().map(|(bound, _)| clean_poly_trait_ref(bound, cx)).collect();
             let lifetime =
-                if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
+                if !lifetime.is_elided() { Some(clean_lifetime(lifetime, cx)) } else { None };
             DynTrait(bounds, lifetime)
         }
         TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
@@ -2355,7 +2352,7 @@ pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext
     clean_field_with_def_id(field.def_id.to_def_id(), field.ident.name, clean_ty(field.ty, cx), cx)
 }
 
-pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext<'tcx>) -> Item {
+pub(crate) fn clean_middle_field(field: &ty::FieldDef, cx: &mut DocContext<'_>) -> Item {
     clean_field_with_def_id(
         field.did,
         field.name,
@@ -2378,7 +2375,7 @@ pub(crate) fn clean_field_with_def_id(
     Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx)
 }
 
-pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
+pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_>) -> Item {
     let discriminant = match variant.discr {
         ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
         ty::VariantDiscr::Relative(_) => None,
@@ -2526,7 +2523,7 @@ fn clean_generic_args<'tcx>(
             .filter_map(|arg| {
                 Some(match arg {
                     hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
-                        GenericArg::Lifetime(clean_lifetime(*lt, cx))
+                        GenericArg::Lifetime(clean_lifetime(lt, cx))
                     }
                     hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
                     hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
@@ -2579,11 +2576,11 @@ fn clean_bare_fn_ty<'tcx>(
     BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params }
 }
 
-pub(crate) fn reexport_chain<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(crate) fn reexport_chain(
+    tcx: TyCtxt<'_>,
     import_def_id: LocalDefId,
     target_def_id: DefId,
-) -> &'tcx [Reexport] {
+) -> &[Reexport] {
     for child in tcx.module_children_local(tcx.local_parent(import_def_id)) {
         if child.res.opt_def_id() == Some(target_def_id)
             && child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id())
@@ -2803,7 +2800,7 @@ fn clean_maybe_renamed_item<'tcx>(
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
             }),
             ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
-            ItemKind::Macro(ref macro_def, MacroKind::Bang) => {
+            ItemKind::Macro(macro_def, MacroKind::Bang) => {
                 let ty_vis = cx.tcx.visibility(def_id);
                 MacroItem(Macro {
                     // FIXME this shouldn't be false
@@ -3134,9 +3131,7 @@ fn clean_assoc_item_constraint<'tcx>(
     }
 }
 
-fn clean_bound_vars<'tcx>(
-    bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
-) -> Vec<GenericParamDef> {
+fn clean_bound_vars(bound_vars: &ty::List<ty::BoundVariableKind>) -> Vec<GenericParamDef> {
     bound_vars
         .into_iter()
         .filter_map(|var| match var {
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 1d81ae3eb8b..b59f939025e 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -70,7 +70,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec<WP>) -> ThinVe
 
 pub(crate) fn merge_bounds(
     cx: &clean::DocContext<'_>,
-    bounds: &mut Vec<clean::GenericBound>,
+    bounds: &mut [clean::GenericBound],
     trait_did: DefId,
     assoc: clean::PathSegment,
     rhs: &clean::Term,
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 63d71a73cdf..51da252da24 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -368,11 +368,11 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 }
 
 impl Item {
-    pub(crate) fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
+    pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
         self.def_id().and_then(|did| tcx.lookup_stability(did))
     }
 
-    pub(crate) fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
+    pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
         self.def_id().and_then(|did| tcx.lookup_const_stability(did))
     }
 
@@ -945,9 +945,9 @@ pub(crate) trait AttributesExt {
     where
         Self: 'a;
 
-    fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a>;
+    fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_>;
 
-    fn iter<'a>(&'a self) -> Self::Attributes<'a>;
+    fn iter(&self) -> Self::Attributes<'_>;
 
     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
         let sess = tcx.sess;
@@ -1043,15 +1043,15 @@ impl AttributesExt for [ast::Attribute] {
     type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a;
     type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a;
 
-    fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> {
+    fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
         self.iter()
             .filter(move |attr| attr.has_name(name))
             .filter_map(ast::Attribute::meta_item_list)
             .flatten()
     }
 
-    fn iter<'a>(&'a self) -> Self::Attributes<'a> {
-        self.into_iter()
+    fn iter(&self) -> Self::Attributes<'_> {
+        self.iter()
     }
 }
 
@@ -1061,15 +1061,15 @@ impl AttributesExt for [(Cow<'_, ast::Attribute>, Option<DefId>)] {
     type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a
         where Self: 'a;
 
-    fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> {
+    fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
         AttributesExt::iter(self)
             .filter(move |attr| attr.has_name(name))
             .filter_map(ast::Attribute::meta_item_list)
             .flatten()
     }
 
-    fn iter<'a>(&'a self) -> Self::Attributes<'a> {
-        self.into_iter().map(move |(attr, _)| match attr {
+    fn iter(&self) -> Self::Attributes<'_> {
+        self.iter().map(move |(attr, _)| match attr {
             Cow::Borrowed(attr) => *attr,
             Cow::Owned(attr) => attr,
         })
@@ -1389,7 +1389,7 @@ pub(crate) struct FnDecl {
 
 impl FnDecl {
     pub(crate) fn receiver_type(&self) -> Option<&Type> {
-        self.inputs.values.get(0).and_then(|v| v.to_receiver())
+        self.inputs.values.first().and_then(|v| v.to_receiver())
     }
 }
 
@@ -1502,7 +1502,7 @@ impl Type {
     pub(crate) fn without_borrowed_ref(&self) -> &Type {
         let mut result = self;
         while let Type::BorrowedRef { type_, .. } = result {
-            result = &*type_;
+            result = type_;
         }
         result
     }
@@ -1631,10 +1631,7 @@ impl Type {
     }
 
     pub(crate) fn is_self_type(&self) -> bool {
-        match *self {
-            SelfTy => true,
-            _ => false,
-        }
+        matches!(*self, Type::SelfTy)
     }
 
     pub(crate) fn generic_args(&self) -> Option<&GenericArgs> {
@@ -1673,7 +1670,7 @@ impl Type {
     pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
         let t: PrimitiveType = match *self {
             Type::Path { ref path } => return Some(path.def_id()),
-            DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()),
+            DynTrait(ref bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
             Primitive(p) => return cache.primitive_locations.get(&p).cloned(),
             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
             BorrowedRef { ref type_, .. } => return type_.def_id(cache),
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 68266f3506a..d826171aa61 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -321,9 +321,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
             "({})",
             elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ")
         ),
-        PatKind::Box(p) => return name_from_pat(&*p),
-        PatKind::Deref(p) => format!("deref!({})", name_from_pat(&*p)),
-        PatKind::Ref(p, _) => return name_from_pat(&*p),
+        PatKind::Box(p) => return name_from_pat(p),
+        PatKind::Deref(p) => format!("deref!({})", name_from_pat(p)),
+        PatKind::Ref(p, _) => return name_from_pat(p),
         PatKind::Lit(..) => {
             warn!(
                 "tried to get argument name from PatKind::Lit, which is silly in function arguments"
@@ -333,7 +333,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
         PatKind::Range(..) => return kw::Underscore,
         PatKind::Slice(begin, ref mid, end) => {
             let begin = begin.iter().map(|p| name_from_pat(p).to_string());
-            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
+            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(p))).into_iter();
             let end = end.iter().map(|p| name_from_pat(p).to_string());
             format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
         }
@@ -344,7 +344,7 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
     match n.kind() {
         ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
             let s = if let Some(def) = def.as_local() {
-                rendered_const(cx.tcx, &cx.tcx.hir().body_owned_by(def), def)
+                rendered_const(cx.tcx, cx.tcx.hir().body_owned_by(def), def)
             } else {
                 inline::print_inlined_const(cx.tcx, def)
             };
@@ -383,7 +383,7 @@ pub(crate) fn print_evaluated_const(
 
 fn format_integer_with_underscore_sep(num: &str) -> String {
     let num_chars: Vec<_> = num.chars().collect();
-    let mut num_start_index = if num_chars.get(0) == Some(&'-') { 1 } else { 0 };
+    let mut num_start_index = if num_chars.first() == Some(&'-') { 1 } else { 0 };
     let chunk_size = match num[num_start_index..].as_bytes() {
         [b'0', b'b' | b'x', ..] => {
             num_start_index += 2;
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 9e9d8f02a2e..9e7b69ec45f 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -360,7 +360,7 @@ impl Options {
             return None;
         }
 
-        if rustc_driver::describe_flag_categories(early_dcx, &matches) {
+        if rustc_driver::describe_flag_categories(early_dcx, matches) {
             return None;
         }
 
@@ -374,7 +374,7 @@ impl Options {
         let codegen_options = CodegenOptions::build(early_dcx, matches);
         let unstable_opts = UnstableOptions::build(early_dcx, matches);
 
-        let remap_path_prefix = match parse_remap_path_prefix(&matches) {
+        let remap_path_prefix = match parse_remap_path_prefix(matches) {
             Ok(prefix_mappings) => prefix_mappings,
             Err(err) => {
                 early_dcx.early_fatal(err);
@@ -486,7 +486,7 @@ impl Options {
                 _ => dcx.fatal("too many file operands"),
             }
         };
-        let input = make_input(early_dcx, &input);
+        let input = make_input(early_dcx, input);
 
         let externs = parse_externs(early_dcx, matches, &unstable_opts);
         let extern_html_root_urls = match parse_extern_html_roots(matches) {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 08a4a3f3fb2..760514f40fd 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -288,7 +288,7 @@ pub(crate) fn create_config(
                 let hir = tcx.hir();
                 let body = hir.body_owned_by(def_id);
                 debug!("visiting body for {def_id:?}");
-                EmitIgnoredResolutionErrors::new(tcx).visit_body(&body);
+                EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
                 (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
             };
         }),
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 743c1ed507e..1ae66fddda6 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -272,7 +272,7 @@ pub(crate) fn run_tests(
         let mut tests_runner = runner::DocTestRunner::new();
 
         let rustdoc_test_options = IndividualTestOptions::new(
-            &rustdoc_options,
+            rustdoc_options,
             &Some(format!("merged_doctest_{edition}")),
             PathBuf::from(format!("doctest_{edition}.rs")),
         );
@@ -307,7 +307,7 @@ pub(crate) fn run_tests(
                 doctest,
                 scraped_test,
                 opts.clone(),
-                Arc::clone(&rustdoc_options),
+                Arc::clone(rustdoc_options),
                 unused_extern_reports.clone(),
             ));
         }
@@ -316,7 +316,7 @@ pub(crate) fn run_tests(
     // We need to call `test_main` even if there is no doctest to run to get the output
     // `running 0 tests...`.
     if ran_edition_tests == 0 || !standalone_tests.is_empty() {
-        standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
+        standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(b.desc.name.as_slice()));
         test::test_main(&test_args, standalone_tests, None);
     }
     if nb_errors != 0 {
@@ -421,7 +421,7 @@ fn add_exe_suffix(input: String, target: &TargetTriple) -> String {
 }
 
 fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command {
-    let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary].into_iter());
+    let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary]);
 
     let exe = args.next().expect("unable to create rustc command");
     let mut command = Command::new(exe);
@@ -452,7 +452,7 @@ pub(crate) struct RunnableDocTest {
 
 impl RunnableDocTest {
     fn path_for_merged_doctest(&self) -> PathBuf {
-        self.test_opts.outdir.path().join(&format!("doctest_{}.rs", self.edition))
+        self.test_opts.outdir.path().join(format!("doctest_{}.rs", self.edition))
     }
 }
 
@@ -477,13 +477,13 @@ fn run_test(
         .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
     let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
 
-    compiler.arg(&format!("@{}", doctest.global_opts.args_file.display()));
+    compiler.arg(format!("@{}", doctest.global_opts.args_file.display()));
 
     if let Some(sysroot) = &rustdoc_options.maybe_sysroot {
         compiler.arg(format!("--sysroot={}", sysroot.display()));
     }
 
-    compiler.arg("--edition").arg(&doctest.edition.to_string());
+    compiler.arg("--edition").arg(doctest.edition.to_string());
     if !doctest.is_multiple_tests {
         // Setting these environment variables is unneeded if this is a merged doctest.
         compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path);
@@ -692,7 +692,7 @@ impl IndividualTestOptions {
     fn new(options: &RustdocOptions, test_id: &Option<String>, test_path: PathBuf) -> Self {
         let outdir = if let Some(ref path) = options.persist_doctests {
             let mut path = path.clone();
-            path.push(&test_id.as_deref().unwrap_or_else(|| "<doctest>"));
+            path.push(&test_id.as_deref().unwrap_or("<doctest>"));
 
             if let Err(err) = std::fs::create_dir_all(&path) {
                 eprintln!("Couldn't create directory for doctest executables: {err}");
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index aed079e5887..9de312a413a 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -311,7 +311,7 @@ fn parse_source(
             }
             ast::ItemKind::ExternCrate(original) => {
                 if !info.found_extern_crate
-                    && let Some(ref crate_name) = crate_name
+                    && let Some(crate_name) = crate_name
                 {
                     info.found_extern_crate = match original {
                         Some(name) => name.as_str() == *crate_name,
diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs
index 4806d865589..9a237f8684d 100644
--- a/src/librustdoc/doctest/markdown.rs
+++ b/src/librustdoc/doctest/markdown.rs
@@ -73,7 +73,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
     use rustc_session::config::Input;
     let input_str = match &options.input {
         Input::File(path) => {
-            read_to_string(&path).map_err(|err| format!("{}: {err}", path.display()))?
+            read_to_string(path).map_err(|err| format!("{}: {err}", path.display()))?
         }
         Input::Str { name: _, input } => input.clone(),
     };
diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs
index d49fa3ac5ac..9cb220ef7ba 100644
--- a/src/librustdoc/doctest/runner.rs
+++ b/src/librustdoc/doctest/runner.rs
@@ -98,8 +98,10 @@ impl DocTestRunner {
 
         code.push_str("extern crate test;\n");
 
-        let test_args =
-            test_args.iter().map(|arg| format!("{arg:?}.to_string(),")).collect::<String>();
+        let test_args = test_args.iter().fold(String::new(), |mut x, arg| {
+            write!(x, "{arg:?}.to_string(),").unwrap();
+            x
+        });
         write!(
             code,
             "\
diff --git a/src/librustdoc/error.rs b/src/librustdoc/error.rs
index 6ed7eab1aba..7876125f7fd 100644
--- a/src/librustdoc/error.rs
+++ b/src/librustdoc/error.rs
@@ -39,7 +39,7 @@ macro_rules! try_none {
         match $e {
             Some(e) => e,
             None => {
-                return Err(<crate::error::Error as crate::docfs::PathError>::new(
+                return Err(<$crate::error::Error as $crate::docfs::PathError>::new(
                     io::Error::new(io::ErrorKind::Other, "not found"),
                     $file,
                 ));
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 947bae99305..90942d87f72 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -274,7 +274,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
             None
         };
         if let Some(name) = search_name {
-            add_item_to_search_index(self.tcx, &mut self.cache, &item, name)
+            add_item_to_search_index(self.tcx, self.cache, &item, name)
         }
 
         // Keep track of the fully qualified path for this item.
@@ -452,7 +452,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
             // or if item is tuple struct/variant field (name is a number -> not useful for search).
             if cache.stripped_mod
                 || item.type_() == ItemType::StructField
-                    && name.as_str().chars().all(|c| c.is_digit(10))
+                    && name.as_str().chars().all(|c| c.is_ascii_digit())
             {
                 return;
             }
@@ -463,7 +463,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
         }
         clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
             let last = cache.parent_stack.last().expect("parent_stack is empty 2");
-            let parent_did = match &*last {
+            let parent_did = match last {
                 // impl Trait for &T { fn method(self); }
                 //
                 // When generating a function index with the above shape, we want it
@@ -471,9 +471,9 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
                 // show up as `T::method`, rather than `reference::method`, in the search
                 // results page.
                 ParentStackItem::Impl { for_: clean::Type::BorrowedRef { type_, .. }, .. } => {
-                    type_.def_id(&cache)
+                    type_.def_id(cache)
                 }
-                ParentStackItem::Impl { for_, .. } => for_.def_id(&cache),
+                ParentStackItem::Impl { for_, .. } => for_.def_id(cache),
                 ParentStackItem::Type(item_id) => item_id.as_def_id(),
             };
             let Some(parent_did) = parent_did else { return };
@@ -538,7 +538,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
         None
     };
     let search_type = get_function_type_for_search(
-        &item,
+        item,
         tcx,
         clean_impl_generics(cache.parent_stack.last()).as_ref(),
         parent_did,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 5cbf8c5e19f..530241f9a13 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -633,7 +633,7 @@ fn generate_item_def_id_path(
     let module_fqp = to_module_fqp(shortty, &fqp);
     let mut is_remote = false;
 
-    let url_parts = url_parts(cx.cache(), def_id, &module_fqp, &cx.current, &mut is_remote)?;
+    let url_parts = url_parts(cx.cache(), def_id, module_fqp, &cx.current, &mut is_remote)?;
     let (url_parts, shortty, fqp) = make_href(root_path, shortty, url_parts, &fqp, is_remote)?;
     if def_id == original_def_id {
         return Ok((url_parts, shortty, fqp));
@@ -811,7 +811,7 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
         // primitives are documented in a crate, but not actually part of it
         &fqp[fqp.len() - 1..]
     } else {
-        &fqp
+        fqp
     };
     if let &Some(UrlFragment::Item(id)) = fragment {
         write!(buf, "{} ", cx.tcx().def_descr(id));
@@ -820,7 +820,7 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
         }
         write!(buf, "{}", cx.tcx().item_name(id));
     } else if !fqp.is_empty() {
-        let mut fqp_it = fqp.into_iter();
+        let mut fqp_it = fqp.iter();
         write!(buf, "{shortty} {}", fqp_it.next().unwrap());
         for component in fqp_it {
             write!(buf, "::{component}");
@@ -830,13 +830,13 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
 }
 
 /// Used to render a [`clean::Path`].
-fn resolved_path<'cx>(
+fn resolved_path(
     w: &mut fmt::Formatter<'_>,
     did: DefId,
     path: &clean::Path,
     print_all: bool,
     use_absolute: bool,
-    cx: &'cx Context<'_>,
+    cx: &Context<'_>,
 ) -> fmt::Result {
     let last = path.segments.last().unwrap();
 
@@ -996,11 +996,11 @@ pub(crate) fn anchor<'a, 'cx: 'a>(
     })
 }
 
-fn fmt_type<'cx>(
+fn fmt_type(
     t: &clean::Type,
     f: &mut fmt::Formatter<'_>,
     use_absolute: bool,
-    cx: &'cx Context<'_>,
+    cx: &Context<'_>,
 ) -> fmt::Result {
     trace!("fmt_type(t = {t:?})");
 
@@ -1493,9 +1493,8 @@ impl clean::FnDecl {
                     }
                     clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => {
                         write!(f, "{amp}")?;
-                        match lifetime {
-                            Some(lt) => write!(f, "{lt} ", lt = lt.print())?,
-                            None => {}
+                        if let Some(lt) = lifetime {
+                            write!(f, "{lt} ", lt = lt.print())?;
                         }
                         write!(f, "{mutability}self", mutability = mutability.print_with_space())?;
                     }
diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs
index 34e52d38bbe..db76aae3dd0 100644
--- a/tests/codegen/cast-target-abi.rs
+++ b/tests/codegen/cast-target-abi.rs
@@ -1,7 +1,7 @@
 // ignore-tidy-linelength
 //@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64
-// FIXME: Add `-Cllvm-args=--lint-abort-on-error` after LLVM 19
-//@ compile-flags: -O -C no-prepopulate-passes -C passes=lint
+//@ min-llvm-version: 19
+//@ compile-flags: -O -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error
 
 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
 //@[aarch64] needs-llvm-components: arm
diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
index a4b7c0caa6d..ae8d8383f5b 100644
--- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
+++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
@@ -1,5 +1,6 @@
 //@ revisions: linux apple
-//@ compile-flags: -C opt-level=0 -C no-prepopulate-passes -C passes=lint
+//@ min-llvm-version: 19
+//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error
 
 //@[linux] compile-flags: --target x86_64-unknown-linux-gnu
 //@[linux] needs-llvm-components: x86
diff --git a/tests/codegen/sanitizer/riscv64-shadow-call-stack.rs b/tests/codegen/sanitizer/riscv64-shadow-call-stack.rs
new file mode 100644
index 00000000000..5833b832ba4
--- /dev/null
+++ b/tests/codegen/sanitizer/riscv64-shadow-call-stack.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: --target riscv64imac-unknown-none-elf -Zsanitizer=shadow-call-stack
+//@ needs-llvm-components: riscv
+
+#![allow(internal_features)]
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+// CHECK: ; Function Attrs:{{.*}}shadowcallstack
+// CHECK: define dso_local void @foo() unnamed_addr #0
+#[no_mangle]
+pub fn foo() {}
+
+// CHECK: attributes #0 = {{.*}}shadowcallstack{{.*}}
diff --git a/tests/run-make/dos-device-input/rmake.rs b/tests/run-make/dos-device-input/rmake.rs
index dee3b86f095..f5911d78fd9 100644
--- a/tests/run-make/dos-device-input/rmake.rs
+++ b/tests/run-make/dos-device-input/rmake.rs
@@ -1,13 +1,11 @@
 //@ only-windows
 // Reason: dos devices are a Windows thing
 
-use std::path::Path;
-
-use run_make_support::{rustc, static_lib_name};
+use run_make_support::{path, rustc, static_lib_name};
 
 fn main() {
     rustc().input(r"\\.\NUL").crate_type("staticlib").run();
     rustc().input(r"\\?\NUL").crate_type("staticlib").run();
 
-    assert!(Path::new(&static_lib_name("rust_out")).exists());
+    assert!(path(&static_lib_name("rust_out")).exists());
 }
diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs
index 483f298776c..c8c113ce944 100644
--- a/tests/run-make/emit-shared-files/rmake.rs
+++ b/tests/run-make/emit-shared-files/rmake.rs
@@ -5,9 +5,7 @@
 // `all-shared` should only emit files that can be shared between crates.
 // See https://github.com/rust-lang/rust/pull/83478
 
-use std::path::Path;
-
-use run_make_support::{has_extension, has_prefix, rustdoc, shallow_find_files};
+use run_make_support::{has_extension, has_prefix, path, rustdoc, shallow_find_files};
 
 fn main() {
     rustdoc()
@@ -19,18 +17,18 @@ fn main() {
         .args(&["--extend-css", "z.css"])
         .input("x.rs")
         .run();
-    assert!(Path::new("invocation-only/search-index-xxx.js").exists());
-    assert!(Path::new("invocation-only/crates-xxx.js").exists());
-    assert!(Path::new("invocation-only/settings.html").exists());
-    assert!(Path::new("invocation-only/x/all.html").exists());
-    assert!(Path::new("invocation-only/x/index.html").exists());
-    assert!(Path::new("invocation-only/theme-xxx.css").exists()); // generated from z.css
-    assert!(!Path::new("invocation-only/storage-xxx.js").exists());
-    assert!(!Path::new("invocation-only/SourceSerif4-It.ttf.woff2").exists());
+    assert!(path("invocation-only/search-index-xxx.js").exists());
+    assert!(path("invocation-only/crates-xxx.js").exists());
+    assert!(path("invocation-only/settings.html").exists());
+    assert!(path("invocation-only/x/all.html").exists());
+    assert!(path("invocation-only/x/index.html").exists());
+    assert!(path("invocation-only/theme-xxx.css").exists()); // generated from z.css
+    assert!(!path("invocation-only/storage-xxx.js").exists());
+    assert!(!path("invocation-only/SourceSerif4-It.ttf.woff2").exists());
     // FIXME: this probably shouldn't have a suffix
-    assert!(Path::new("invocation-only/y-xxx.css").exists());
+    assert!(path("invocation-only/y-xxx.css").exists());
     // FIXME: this is technically incorrect (see `write_shared`)
-    assert!(!Path::new("invocation-only/main-xxx.js").exists());
+    assert!(!path("invocation-only/main-xxx.js").exists());
 
     rustdoc()
         .arg("-Zunstable-options")
@@ -61,10 +59,10 @@ fn main() {
         .len(),
         1
     );
-    assert!(!Path::new("toolchain-only/search-index-xxx.js").exists());
-    assert!(!Path::new("toolchain-only/x/index.html").exists());
-    assert!(!Path::new("toolchain-only/theme.css").exists());
-    assert!(!Path::new("toolchain-only/y-xxx.css").exists());
+    assert!(!path("toolchain-only/search-index-xxx.js").exists());
+    assert!(!path("toolchain-only/x/index.html").exists());
+    assert!(!path("toolchain-only/theme.css").exists());
+    assert!(!path("toolchain-only/y-xxx.css").exists());
 
     rustdoc()
         .arg("-Zunstable-options")
@@ -88,11 +86,11 @@ fn main() {
         .len(),
         1
     );
-    assert!(!Path::new("all-shared/search-index-xxx.js").exists());
-    assert!(!Path::new("all-shared/settings.html").exists());
-    assert!(!Path::new("all-shared/x").exists());
-    assert!(!Path::new("all-shared/src").exists());
-    assert!(!Path::new("all-shared/theme.css").exists());
+    assert!(!path("all-shared/search-index-xxx.js").exists());
+    assert!(!path("all-shared/settings.html").exists());
+    assert!(!path("all-shared/x").exists());
+    assert!(!path("all-shared/src").exists());
+    assert!(!path("all-shared/theme.css").exists());
     assert_eq!(
         shallow_find_files("all-shared/static.files", |path| {
             has_prefix(path, "main-") && has_extension(path, "js")
@@ -100,5 +98,5 @@ fn main() {
         .len(),
         1
     );
-    assert!(!Path::new("all-shared/y-xxx.css").exists());
+    assert!(!path("all-shared/y-xxx.css").exists());
 }
diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs
index be0eeaf1717..5decd802b34 100644
--- a/tests/run-make/libtest-thread-limit/rmake.rs
+++ b/tests/run-make/libtest-thread-limit/rmake.rs
@@ -11,6 +11,9 @@
 // Reason: thread limit modification
 //@ ignore-cross-compile
 // Reason: this test fails armhf-gnu, reasons unknown
+//@ needs-unwind
+// Reason: this should be ignored in cg_clif (Cranelift) CI and anywhere
+// else that uses panic=abort.
 
 use std::ffi::{self, CStr, CString};
 use std::path::PathBuf;
diff --git a/tests/run-make/manual-crate-name/rmake.rs b/tests/run-make/manual-crate-name/rmake.rs
index 9085b6c7bc2..9f480ec6b6a 100644
--- a/tests/run-make/manual-crate-name/rmake.rs
+++ b/tests/run-make/manual-crate-name/rmake.rs
@@ -1,8 +1,6 @@
-use std::path::Path;
-
-use run_make_support::rustc;
+use run_make_support::{path, rustc};
 
 fn main() {
     rustc().input("bar.rs").crate_name("foo").run();
-    assert!(Path::new("libfoo.rlib").is_file());
+    assert!(path("libfoo.rlib").is_file());
 }
diff --git a/tests/run-make/pretty-print-with-dep-file/rmake.rs b/tests/run-make/pretty-print-with-dep-file/rmake.rs
index 5d422085834..24ae6bc2456 100644
--- a/tests/run-make/pretty-print-with-dep-file/rmake.rs
+++ b/tests/run-make/pretty-print-with-dep-file/rmake.rs
@@ -5,14 +5,12 @@
 // does not get an unexpected dep-info file.
 // See https://github.com/rust-lang/rust/issues/112898
 
-use std::path::Path;
-
-use run_make_support::{invalid_utf8_contains, rfs, rustc};
+use run_make_support::{invalid_utf8_contains, path, rfs, rustc};
 
 fn main() {
     rustc().emit("dep-info").arg("-Zunpretty=expanded").input("with-dep.rs").run();
     invalid_utf8_contains("with-dep.d", "with-dep.rs");
     rfs::remove_file("with-dep.d");
     rustc().emit("dep-info").arg("-Zunpretty=normal").input("with-dep.rs").run();
-    assert!(!Path::new("with-dep.d").exists());
+    assert!(!path("with-dep.d").exists());
 }
diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs
index 4c6f9c19091..4287ab0a931 100644
--- a/tests/run-make/profile/rmake.rs
+++ b/tests/run-make/profile/rmake.rs
@@ -8,16 +8,14 @@
 //@ ignore-cross-compile
 //@ needs-profiler-support
 
-use std::path::Path;
-
-use run_make_support::{run, rustc};
+use run_make_support::{path, run, rustc};
 
 fn main() {
     rustc().arg("-g").arg("-Zprofile").input("test.rs").run();
     run("test");
-    assert!(Path::new("test.gcno").exists(), "no .gcno file");
-    assert!(Path::new("test.gcda").exists(), "no .gcda file");
+    assert!(path("test.gcno").exists(), "no .gcno file");
+    assert!(path("test.gcda").exists(), "no .gcda file");
     rustc().arg("-g").arg("-Zprofile").arg("-Zprofile-emit=abc/abc.gcda").input("test.rs").run();
     run("test");
-    assert!(Path::new("abc/abc.gcda").exists(), "gcda file not emitted to defined path");
+    assert!(path("abc/abc.gcda").exists(), "gcda file not emitted to defined path");
 }
diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs
index 118b3a666ad..bdc90e39f9e 100644
--- a/tests/run-make/reset-codegen-1/rmake.rs
+++ b/tests/run-make/reset-codegen-1/rmake.rs
@@ -7,9 +7,7 @@
 
 //@ ignore-cross-compile
 
-use std::path::Path;
-
-use run_make_support::{bin_name, rustc};
+use run_make_support::{bin_name, path, rustc};
 
 fn compile(output_file: &str, emit: Option<&str>) {
     let mut rustc = rustc();
@@ -34,10 +32,10 @@ fn main() {
         // In the None case, bin_name is required for successful Windows compilation.
         let output_file = &bin_name(output_file);
         compile(output_file, emit);
-        assert!(Path::new(output_file).is_file());
+        assert!(path(output_file).is_file());
     }
 
     compile("multi-output", Some("asm,obj"));
-    assert!(Path::new("multi-output.s").is_file());
-    assert!(Path::new("multi-output.o").is_file());
+    assert!(path("multi-output.s").is_file());
+    assert!(path("multi-output.o").is_file());
 }
diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs
index ce088508178..5a030c6f496 100644
--- a/tests/run-make/rustdoc-determinism/rmake.rs
+++ b/tests/run-make/rustdoc-determinism/rmake.rs
@@ -1,16 +1,14 @@
 // Assert that the search index is generated deterministically, regardless of the
 // order that crates are documented in.
 
-use std::path::Path;
-
-use run_make_support::{diff, rustdoc};
+use run_make_support::{diff, path, rustdoc};
 
 fn main() {
-    let foo_first = Path::new("foo_first");
+    let foo_first = path("foo_first");
     rustdoc().input("foo.rs").out_dir(&foo_first).run();
     rustdoc().input("bar.rs").out_dir(&foo_first).run();
 
-    let bar_first = Path::new("bar_first");
+    let bar_first = path("bar_first");
     rustdoc().input("bar.rs").out_dir(&bar_first).run();
     rustdoc().input("foo.rs").out_dir(&bar_first).run();
 
diff --git a/tests/run-make/rustdoc-output-path/rmake.rs b/tests/run-make/rustdoc-output-path/rmake.rs
index 181239eac4d..7f6accf26c2 100644
--- a/tests/run-make/rustdoc-output-path/rmake.rs
+++ b/tests/run-make/rustdoc-output-path/rmake.rs
@@ -1,11 +1,9 @@
 // Checks that if the output folder doesn't exist, rustdoc will create it.
 
-use std::path::Path;
-
-use run_make_support::rustdoc;
+use run_make_support::{path, rustdoc};
 
 fn main() {
-    let out_dir = Path::new("foo/bar/doc");
+    let out_dir = path("foo/bar/doc");
     rustdoc().input("foo.rs").out_dir(&out_dir).run();
     assert!(out_dir.exists());
 }
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.fmt_debug_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.fmt_debug_.stderr
new file mode 100644
index 00000000000..a0d7fa5c3c9
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.fmt_debug_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg fmt_debug="shallow"` flag
+   |
+   = note: config `fmt_debug` is only supposed to be controlled by `-Z fmt-debug`
+   = note: manually setting a built-in cfg can and does create incoherent behaviors
+   = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs
index 714c01f4bc6..3c9ee87f28a 100644
--- a/tests/ui/cfg/disallowed-cli-cfgs.rs
+++ b/tests/ui/cfg/disallowed-cli-cfgs.rs
@@ -6,6 +6,7 @@
 //@ revisions: target_pointer_width_ target_vendor_ target_has_atomic_
 //@ revisions: target_has_atomic_equal_alignment_ target_has_atomic_load_store_
 //@ revisions: target_thread_local_ relocation_model_
+//@ revisions: fmt_debug_
 
 //@ [overflow_checks_]compile-flags: --cfg overflow_checks
 //@ [debug_assertions_]compile-flags: --cfg debug_assertions
@@ -31,5 +32,6 @@
 //@ [target_has_atomic_load_store_]compile-flags: --cfg target_has_atomic_load_store="32"
 //@ [target_thread_local_]compile-flags: --cfg target_thread_local
 //@ [relocation_model_]compile-flags: --cfg relocation_model="a"
+//@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow"
 
 fn main() {}
diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr
index b311a80c8fd..b1a9c5810d8 100644
--- a/tests/ui/check-cfg/allow-same-level.stderr
+++ b/tests/ui/check-cfg/allow-same-level.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE`
 LL | #[cfg(FALSE)]
    |       ^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(FALSE)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cargo-build-script.stderr b/tests/ui/check-cfg/cargo-build-script.stderr
index 9ab3290ef22..0b01b1da5a7 100644
--- a/tests/ui/check-cfg/cargo-build-script.stderr
+++ b/tests/ui/check-cfg/cargo-build-script.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `has_foo`
 LL | #[cfg(has_foo)]
    |       ^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr
index 9d3117ed54d..6de6e9a6851 100644
--- a/tests/ui/check-cfg/cargo-feature.none.stderr
+++ b/tests/ui/check-cfg/cargo-feature.none.stderr
@@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr
index 14e24cb1429..d4a7f6defb2 100644
--- a/tests/ui/check-cfg/cargo-feature.some.stderr
+++ b/tests/ui/check-cfg/cargo-feature.some.stderr
@@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
index 08bd43832ea..831722a12e2 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value`
 LL | #[cfg(value)]
    |       ^^^^^
    |
-   = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
index 6db1144eada..a35a8d68def 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value`
 LL | #[cfg(my_value)]
    |       ^^^^^^^^
    |
-   = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(my_value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
index a5f8176343a..65a73ffcd1d 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `linux`
 LL | #[cfg(linux)]
    |       ^^^^^ help: found config with similar value: `target_os = "linux"`
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(linux)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr
index 6fecdb52362..536c992ee92 100644
--- a/tests/ui/check-cfg/compact-names.stderr
+++ b/tests/ui/check-cfg/compact-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture`
 LL | #[cfg(target(os = "linux", architecture = "arm"))]
    |                            ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(target_architecture, values("arm"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index 2497864e87e..6c26a8b11d9 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index a7d4c6d4df6..b7ccf5e5f83 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index a7d4c6d4df6..b7ccf5e5f83 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr
index 7ac3241db5f..5350534f3e8 100644
--- a/tests/ui/check-cfg/exhaustive-names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 9b6448fe5a0..a163728b51d 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu`
 LL | #[cfg_attr(uu, test)]
    |            ^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(uu)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr
index e8b61d808fe..98f09a648bc 100644
--- a/tests/ui/check-cfg/stmt-no-ice.stderr
+++ b/tests/ui/check-cfg/stmt-no-ice.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom`
 LL |     #[cfg(crossbeam_loom)]
    |           ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(crossbeam_loom)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr
index 41130210df1..abcf53cfe30 100644
--- a/tests/ui/check-cfg/well-known-names.stderr
+++ b/tests/ui/check-cfg/well-known-names.stderr
@@ -18,7 +18,7 @@ warning: unexpected `cfg` condition name: `features`
 LL | #[cfg(features = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(features, values("foo"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs
index d5fe7464792..1fda4b2089e 100644
--- a/tests/ui/check-cfg/well-known-values.rs
+++ b/tests/ui/check-cfg/well-known-values.rs
@@ -16,6 +16,7 @@
 #![feature(cfg_target_has_atomic_equal_alignment)]
 #![feature(cfg_target_thread_local)]
 #![feature(cfg_ub_checks)]
+#![feature(fmt_debug)]
 
 // This part makes sure that none of the well known names are
 // unexpected.
@@ -33,6 +34,8 @@
     //~^ WARN unexpected `cfg` condition value
     doctest = "_UNEXPECTED_VALUE",
     //~^ WARN unexpected `cfg` condition value
+    fmt_debug = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
     miri = "_UNEXPECTED_VALUE",
     //~^ WARN unexpected `cfg` condition value
     overflow_checks = "_UNEXPECTED_VALUE",
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 56423d8c307..0530e1c34c9 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:28:5
+  --> $DIR/well-known-values.rs:29:5
    |
 LL |     clippy = "_UNEXPECTED_VALUE",
    |     ^^^^^^----------------------
@@ -11,7 +11,7 @@ LL |     clippy = "_UNEXPECTED_VALUE",
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:30:5
+  --> $DIR/well-known-values.rs:31:5
    |
 LL |     debug_assertions = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^----------------------
@@ -22,7 +22,7 @@ LL |     debug_assertions = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:32:5
+  --> $DIR/well-known-values.rs:33:5
    |
 LL |     doc = "_UNEXPECTED_VALUE",
    |     ^^^----------------------
@@ -33,7 +33,7 @@ LL |     doc = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:34:5
+  --> $DIR/well-known-values.rs:35:5
    |
 LL |     doctest = "_UNEXPECTED_VALUE",
    |     ^^^^^^^----------------------
@@ -44,7 +44,16 @@ LL |     doctest = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:36:5
+  --> $DIR/well-known-values.rs:37:5
+   |
+LL |     fmt_debug = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `fmt_debug` are: `full`, `none`, and `shallow`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:39:5
    |
 LL |     miri = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -55,7 +64,7 @@ LL |     miri = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:38:5
+  --> $DIR/well-known-values.rs:41:5
    |
 LL |     overflow_checks = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^----------------------
@@ -66,7 +75,7 @@ LL |     overflow_checks = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:40:5
+  --> $DIR/well-known-values.rs:43:5
    |
 LL |     panic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -75,7 +84,7 @@ LL |     panic = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:42:5
+  --> $DIR/well-known-values.rs:45:5
    |
 LL |     proc_macro = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^----------------------
@@ -86,7 +95,7 @@ LL |     proc_macro = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:44:5
+  --> $DIR/well-known-values.rs:47:5
    |
 LL |     relocation_model = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +104,7 @@ LL |     relocation_model = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:46:5
+  --> $DIR/well-known-values.rs:49:5
    |
 LL |     rustfmt = "_UNEXPECTED_VALUE",
    |     ^^^^^^^----------------------
@@ -106,7 +115,7 @@ LL |     rustfmt = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:48:5
+  --> $DIR/well-known-values.rs:51:5
    |
 LL |     sanitize = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -115,7 +124,7 @@ LL |     sanitize = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:50:5
+  --> $DIR/well-known-values.rs:53:5
    |
 LL |     target_abi = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -124,7 +133,7 @@ LL |     target_abi = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:52:5
+  --> $DIR/well-known-values.rs:55:5
    |
 LL |     target_arch = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -133,7 +142,7 @@ LL |     target_arch = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:54:5
+  --> $DIR/well-known-values.rs:57:5
    |
 LL |     target_endian = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -142,7 +151,7 @@ LL |     target_endian = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:56:5
+  --> $DIR/well-known-values.rs:59:5
    |
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -151,7 +160,7 @@ LL |     target_env = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:58:5
+  --> $DIR/well-known-values.rs:61:5
    |
 LL |     target_family = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -160,7 +169,7 @@ LL |     target_family = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:60:5
+  --> $DIR/well-known-values.rs:63:5
    |
 LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -169,7 +178,7 @@ LL |     target_feature = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:62:5
+  --> $DIR/well-known-values.rs:65:5
    |
 LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -178,7 +187,7 @@ LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:64:5
+  --> $DIR/well-known-values.rs:67:5
    |
 LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -187,7 +196,7 @@ LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:66:5
+  --> $DIR/well-known-values.rs:69:5
    |
 LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -196,7 +205,7 @@ LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:68:5
+  --> $DIR/well-known-values.rs:71:5
    |
 LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -205,7 +214,7 @@ LL |     target_os = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:70:5
+  --> $DIR/well-known-values.rs:73:5
    |
 LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -214,7 +223,7 @@ LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:72:5
+  --> $DIR/well-known-values.rs:75:5
    |
 LL |     target_thread_local = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^----------------------
@@ -225,7 +234,7 @@ LL |     target_thread_local = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:74:5
+  --> $DIR/well-known-values.rs:77:5
    |
 LL |     target_vendor = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -234,7 +243,7 @@ LL |     target_vendor = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:76:5
+  --> $DIR/well-known-values.rs:79:5
    |
 LL |     test = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -245,7 +254,7 @@ LL |     test = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:78:5
+  --> $DIR/well-known-values.rs:81:5
    |
 LL |     ub_checks = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^----------------------
@@ -256,7 +265,7 @@ LL |     ub_checks = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:80:5
+  --> $DIR/well-known-values.rs:83:5
    |
 LL |     unix = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -267,7 +276,7 @@ LL |     unix = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:82:5
+  --> $DIR/well-known-values.rs:85:5
    |
 LL |     windows = "_UNEXPECTED_VALUE",
    |     ^^^^^^^----------------------
@@ -278,7 +287,7 @@ LL |     windows = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `linuz`
-  --> $DIR/well-known-values.rs:88:7
+  --> $DIR/well-known-values.rs:91:7
    |
 LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |       ^^^^^^^^^^^^-------
@@ -288,5 +297,5 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
-warning: 29 warnings emitted
+warning: 30 warnings emitted
 
diff --git a/tests/ui/feature-gates/feature-gate-fmt-debug.rs b/tests/ui/feature-gates/feature-gate-fmt-debug.rs
new file mode 100644
index 00000000000..f30befbd19c
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-fmt-debug.rs
@@ -0,0 +1,5 @@
+#[cfg(fmt_debug = "full")]
+//~^ ERROR is experimental
+fn main() {
+
+}
diff --git a/tests/ui/feature-gates/feature-gate-fmt-debug.stderr b/tests/ui/feature-gates/feature-gate-fmt-debug.stderr
new file mode 100644
index 00000000000..9ced0b8facf
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-fmt-debug.stderr
@@ -0,0 +1,13 @@
+error[E0658]: `cfg(fmt_debug)` is experimental and subject to change
+  --> $DIR/feature-gate-fmt-debug.rs:1:7
+   |
+LL | #[cfg(fmt_debug = "full")]
+   |       ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #129709 <https://github.com/rust-lang/rust/issues/129709> for more information
+   = help: add `#![feature(fmt_debug)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/fmt/fmt_debug/full.rs b/tests/ui/fmt/fmt_debug/full.rs
new file mode 100644
index 00000000000..4e9384d2c52
--- /dev/null
+++ b/tests/ui/fmt/fmt_debug/full.rs
@@ -0,0 +1,15 @@
+//@ compile-flags: -Zfmt-debug=full
+//@ run-pass
+#![feature(fmt_debug)]
+#![allow(dead_code)]
+#![allow(unused)]
+
+#[derive(Debug)]
+struct Foo {
+    bar: u32,
+}
+
+fn main() {
+    let s = format!("Still works: {:?} '{:?}'", cfg!(fmt_debug = "full"), Foo { bar: 1 });
+    assert_eq!("Still works: true 'Foo { bar: 1 }'", s);
+}
diff --git a/tests/ui/fmt/fmt_debug/invalid.rs b/tests/ui/fmt/fmt_debug/invalid.rs
new file mode 100644
index 00000000000..09cb46f1ea6
--- /dev/null
+++ b/tests/ui/fmt/fmt_debug/invalid.rs
@@ -0,0 +1,4 @@
+//@ compile-flags: -Zfmt-debug=invalid-value
+//@ failure-status: 1
+fn main() {
+}
diff --git a/tests/ui/fmt/fmt_debug/invalid.stderr b/tests/ui/fmt/fmt_debug/invalid.stderr
new file mode 100644
index 00000000000..fa6c9380744
--- /dev/null
+++ b/tests/ui/fmt/fmt_debug/invalid.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `invalid-value` for unstable option `fmt-debug` - either `full`, `shallow`, or `none` was expected
+
diff --git a/tests/ui/fmt/fmt_debug/none.rs b/tests/ui/fmt/fmt_debug/none.rs
new file mode 100644
index 00000000000..f45d37d9da2
--- /dev/null
+++ b/tests/ui/fmt/fmt_debug/none.rs
@@ -0,0 +1,37 @@
+//@ compile-flags: -Zfmt-debug=none
+//@ run-pass
+#![feature(fmt_debug)]
+#![allow(dead_code)]
+#![allow(unused)]
+
+#[derive(Debug)]
+struct Foo {
+    bar: u32,
+}
+
+#[derive(Debug)]
+enum Baz {
+    Quz,
+}
+
+#[cfg(fmt_debug = "full")]
+compile_error!("nope");
+
+#[cfg(fmt_debug = "none")]
+struct Custom;
+
+impl std::fmt::Debug for Custom {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str("custom_fmt")
+    }
+}
+
+fn main() {
+    let c = Custom;
+    let s = format!("Debug is '{:?}', '{:#?}', and '{c:?}'", Foo { bar: 1 }, Baz::Quz);
+    assert_eq!("Debug is '', '', and ''", s);
+
+    let f = 3.0;
+    let s = format_args!("{:?}x{:#?}y{f:?}", 1234, "can't debug this").to_string();
+    assert_eq!("xy", s);
+}
diff --git a/tests/ui/fmt/fmt_debug/shallow.rs b/tests/ui/fmt/fmt_debug/shallow.rs
new file mode 100644
index 00000000000..479cd1b8875
--- /dev/null
+++ b/tests/ui/fmt/fmt_debug/shallow.rs
@@ -0,0 +1,33 @@
+//@ compile-flags: -Zfmt-debug=shallow
+//@ run-pass
+#![feature(fmt_debug)]
+#![allow(dead_code)]
+#![allow(unused)]
+
+#[derive(Debug)]
+struct Foo {
+    bar: u32,
+    bomb: Bomb,
+}
+
+#[derive(Debug)]
+enum Baz {
+    Quz,
+}
+
+struct Bomb;
+
+impl std::fmt::Debug for Bomb {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        panic!()
+    }
+}
+
+fn main() {
+    let s = format!("Debug is '{:?}' and '{:#?}'", Foo { bar: 1, bomb: Bomb }, Baz::Quz);
+    assert_eq!("Debug is 'Foo' and 'Quz'", s);
+
+    let f = 3.0;
+    let s = format_args!("{:?}{:#?}{f:?}", 1234, cfg!(fmt_debug = "shallow")).to_string();
+    assert_eq!("1234true3.0", s);
+}