about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-04-17 05:08:05 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-04-17 05:08:05 +0000
commite8739886f2b01758f1a1cc0b068001607389d08c (patch)
treea83b09d0fec77ac55542f95ac9a560a44f8c6a66 /src
parentaf28716f190813e6adb82018401aa99c075f6f22 (diff)
parentb7581490aaf964d4a34121d75be0fc49a2445911 (diff)
downloadrust-e8739886f2b01758f1a1cc0b068001607389d08c.tar.gz
rust-e8739886f2b01758f1a1cc0b068001607389d08c.zip
Merge from rustc
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/src/bin/main.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs113
-rw-r--r--src/bootstrap/src/core/build_steps/clippy.rs330
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs7
-rw-r--r--src/bootstrap/src/core/build_steps/mod.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs7
-rw-r--r--src/bootstrap/src/core/builder.rs33
-rw-r--r--src/bootstrap/src/core/config/config.rs16
-rw-r--r--src/bootstrap/src/core/config/tests.rs2
-rw-r--r--src/bootstrap/src/lib.rs22
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/tarball.rs7
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile2
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/check-cfg.md (renamed from src/doc/unstable-book/src/compiler-flags/check-cfg.md)8
-rw-r--r--src/doc/rustc/src/codegen-options/index.md20
-rw-r--r--src/doc/rustc/src/command-line-arguments.md10
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md14
-rw-r--r--src/doc/rustdoc/src/unstable-features.md16
-rw-r--r--src/librustdoc/clean/mod.rs24
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/doctest.rs7
-rw-r--r--src/librustdoc/html/render/mod.rs6
-rw-r--r--src/librustdoc/html/render/type_layout.rs5
-rw-r--r--src/librustdoc/html/static/js/main.js3
-rw-r--r--src/librustdoc/html/templates/page.html2
-rw-r--r--src/librustdoc/lib.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs11
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs4
-rw-r--r--src/tools/compiletest/src/header.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs4
-rw-r--r--src/tools/lint-docs/src/lib.rs1
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs13
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs2
-rw-r--r--src/tools/miri/src/diagnostics.rs4
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/src/machine.rs15
-rw-r--r--src/tools/miri/src/shims/os_str.rs8
-rw-r--r--src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr2
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-3473.rs28
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs12
-rw-r--r--src/tools/run-make-support/Cargo.toml1
-rw-r--r--src/tools/run-make-support/src/lib.rs1
-rw-r--r--src/tools/run-make-support/src/rustc.rs9
-rw-r--r--src/tools/rustfmt/src/macros.rs2
-rw-r--r--src/tools/rustfmt/src/types.rs9
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt2
71 files changed, 676 insertions, 266 deletions
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 340a5c87f0b..4cb67b7aa62 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -131,10 +131,6 @@ fn main() {
 fn check_version(config: &Config) -> Option<String> {
     let mut msg = String::new();
 
-    if config.changelog_seen.is_some() {
-        msg.push_str("WARNING: The use of `changelog-seen` is deprecated. Please refer to `change-id` option in `config.example.toml` instead.\n");
-    }
-
     let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
     let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id");
 
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 37d91b14ca1..927d72e8ccb 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -11,6 +11,16 @@ use crate::core::config::TargetSelection;
 use crate::{Compiler, Mode, Subcommand};
 use std::path::{Path, PathBuf};
 
+pub fn cargo_subcommand(kind: Kind) -> &'static str {
+    match kind {
+        Kind::Check
+        // We ensure check steps for both std and rustc from build_steps/clippy, so handle `Kind::Clippy` as well.
+        | Kind::Clippy => "check",
+        Kind::Fix => "fix",
+        _ => unreachable!(),
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
     pub target: TargetSelection,
@@ -22,97 +32,6 @@ pub struct Std {
     crates: Vec<String>,
 }
 
-/// Returns args for the subcommand itself (not for cargo)
-fn args(builder: &Builder<'_>) -> Vec<String> {
-    fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
-        arr.iter().copied().map(String::from)
-    }
-
-    if let Subcommand::Clippy { fix, allow_dirty, allow_staged, allow, deny, warn, forbid } =
-        &builder.config.cmd
-    {
-        // disable the most spammy clippy lints
-        let ignored_lints = [
-            "many_single_char_names", // there are a lot in stdarch
-            "collapsible_if",
-            "type_complexity",
-            "missing_safety_doc", // almost 3K warnings
-            "too_many_arguments",
-            "needless_lifetimes", // people want to keep the lifetimes
-            "wrong_self_convention",
-        ];
-        let mut args = vec![];
-        if *fix {
-            #[rustfmt::skip]
-            args.extend(strings(&[
-                "--fix", "-Zunstable-options",
-                // FIXME: currently, `--fix` gives an error while checking tests for libtest,
-                // possibly because libtest is not yet built in the sysroot.
-                // As a workaround, avoid checking tests and benches when passed --fix.
-                "--lib", "--bins", "--examples",
-            ]));
-
-            if *allow_dirty {
-                args.push("--allow-dirty".to_owned());
-            }
-
-            if *allow_staged {
-                args.push("--allow-staged".to_owned());
-            }
-        }
-
-        args.extend(strings(&["--"]));
-
-        if deny.is_empty() && forbid.is_empty() {
-            args.extend(strings(&["--cap-lints", "warn"]));
-        }
-
-        let all_args = std::env::args().collect::<Vec<_>>();
-        args.extend(get_clippy_rules_in_order(&all_args, allow, deny, warn, forbid));
-
-        args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
-        args.extend(builder.config.free_args.clone());
-        args
-    } else {
-        builder.config.free_args.clone()
-    }
-}
-
-/// We need to keep the order of the given clippy lint rules before passing them.
-/// Since clap doesn't offer any useful interface for this purpose out of the box,
-/// we have to handle it manually.
-pub(crate) fn get_clippy_rules_in_order(
-    all_args: &[String],
-    allow_rules: &[String],
-    deny_rules: &[String],
-    warn_rules: &[String],
-    forbid_rules: &[String],
-) -> Vec<String> {
-    let mut result = vec![];
-
-    for (prefix, item) in
-        [("-A", allow_rules), ("-D", deny_rules), ("-W", warn_rules), ("-F", forbid_rules)]
-    {
-        item.iter().for_each(|v| {
-            let rule = format!("{prefix}{v}");
-            let position = all_args.iter().position(|t| t == &rule).unwrap();
-            result.push((position, rule));
-        });
-    }
-
-    result.sort_by_key(|&(position, _)| position);
-    result.into_iter().map(|v| v.1).collect()
-}
-
-fn cargo_subcommand(kind: Kind) -> &'static str {
-    match kind {
-        Kind::Check => "check",
-        Kind::Clippy => "clippy",
-        Kind::Fix => "fix",
-        _ => unreachable!(),
-    }
-}
-
 impl Std {
     pub fn new(target: TargetSelection) -> Self {
         Self { target, crates: vec![] }
@@ -164,7 +83,7 @@ impl Step for Std {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &libstd_stamp(builder, compiler, target),
             vec![],
             true,
@@ -221,7 +140,7 @@ impl Step for Std {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &libstd_test_stamp(builder, compiler, target),
             vec![],
             true,
@@ -318,7 +237,7 @@ impl Step for Rustc {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &librustc_stamp(builder, compiler, target),
             vec![],
             true,
@@ -384,7 +303,7 @@ impl Step for CodegenBackend {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &codegen_backend_stamp(builder, compiler, target, backend),
             vec![],
             true,
@@ -450,7 +369,7 @@ impl Step for RustAnalyzer {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &stamp(builder, compiler, target),
             vec![],
             true,
@@ -513,7 +432,7 @@ macro_rules! tool_check_step {
                 run_cargo(
                     builder,
                     cargo,
-                    args(builder),
+                    builder.config.free_args.clone(),
                     &stamp(builder, compiler, target),
                     vec![],
                     true,
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
new file mode 100644
index 00000000000..33323ec1e5d
--- /dev/null
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -0,0 +1,330 @@
+//! Implementation of running clippy on the compiler, standard library and various tools.
+
+use std::path::Path;
+
+use crate::builder::Builder;
+use crate::builder::ShouldRun;
+use crate::core::builder;
+use crate::core::builder::crate_description;
+use crate::core::builder::Alias;
+use crate::core::builder::Kind;
+use crate::core::builder::RunConfig;
+use crate::core::builder::Step;
+use crate::Mode;
+use crate::Subcommand;
+use crate::TargetSelection;
+
+use super::check;
+use super::compile;
+use super::compile::librustc_stamp;
+use super::compile::libstd_stamp;
+use super::compile::run_cargo;
+use super::compile::rustc_cargo;
+use super::compile::std_cargo;
+use super::tool::prepare_tool_cargo;
+use super::tool::SourceType;
+
+// Disable the most spammy clippy lints
+const IGNORED_RULES_FOR_STD_AND_RUSTC: &[&str] = &[
+    "many_single_char_names", // there are a lot in stdarch
+    "collapsible_if",
+    "type_complexity",
+    "missing_safety_doc", // almost 3K warnings
+    "too_many_arguments",
+    "needless_lifetimes", // people want to keep the lifetimes
+    "wrong_self_convention",
+];
+
+fn lint_args(builder: &Builder<'_>, ignored_rules: &[&str]) -> Vec<String> {
+    fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
+        arr.iter().copied().map(String::from)
+    }
+
+    let Subcommand::Clippy { fix, allow_dirty, allow_staged, allow, deny, warn, forbid } =
+        &builder.config.cmd
+    else {
+        unreachable!("clippy::lint_args can only be called from `clippy` subcommands.");
+    };
+
+    let mut args = vec![];
+    if *fix {
+        #[rustfmt::skip]
+            args.extend(strings(&[
+                "--fix", "-Zunstable-options",
+                // FIXME: currently, `--fix` gives an error while checking tests for libtest,
+                // possibly because libtest is not yet built in the sysroot.
+                // As a workaround, avoid checking tests and benches when passed --fix.
+                "--lib", "--bins", "--examples",
+            ]));
+
+        if *allow_dirty {
+            args.push("--allow-dirty".to_owned());
+        }
+
+        if *allow_staged {
+            args.push("--allow-staged".to_owned());
+        }
+    }
+
+    args.extend(strings(&["--"]));
+
+    if deny.is_empty() && forbid.is_empty() {
+        args.extend(strings(&["--cap-lints", "warn"]));
+    }
+
+    let all_args = std::env::args().collect::<Vec<_>>();
+    args.extend(get_clippy_rules_in_order(&all_args, allow, deny, warn, forbid));
+
+    args.extend(ignored_rules.iter().map(|lint| format!("-Aclippy::{}", lint)));
+    args.extend(builder.config.free_args.clone());
+    args
+}
+
+/// We need to keep the order of the given clippy lint rules before passing them.
+/// Since clap doesn't offer any useful interface for this purpose out of the box,
+/// we have to handle it manually.
+pub(crate) fn get_clippy_rules_in_order(
+    all_args: &[String],
+    allow_rules: &[String],
+    deny_rules: &[String],
+    warn_rules: &[String],
+    forbid_rules: &[String],
+) -> Vec<String> {
+    let mut result = vec![];
+
+    for (prefix, item) in
+        [("-A", allow_rules), ("-D", deny_rules), ("-W", warn_rules), ("-F", forbid_rules)]
+    {
+        item.iter().for_each(|v| {
+            let rule = format!("{prefix}{v}");
+            let position = all_args.iter().position(|t| t == &rule).unwrap();
+            result.push((position, rule));
+        });
+    }
+
+    result.sort_by_key(|&(position, _)| position);
+    result.into_iter().map(|v| v.1).collect()
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Std {
+    pub target: TargetSelection,
+    /// Whether to lint only a subset of crates.
+    crates: Vec<String>,
+}
+
+impl Step for Std {
+    type Output = ();
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.crate_or_deps("sysroot").path("library")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        let crates = run.make_run_crates(Alias::Library);
+        run.builder.ensure(Std { target: run.target, crates });
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        builder.update_submodule(&Path::new("library").join("stdarch"));
+
+        let target = self.target;
+        let compiler = builder.compiler(builder.top_stage, builder.config.build);
+
+        let mut cargo =
+            builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, "clippy");
+
+        std_cargo(builder, target, compiler.stage, &mut cargo);
+
+        for krate in &*self.crates {
+            cargo.arg("-p").arg(krate);
+        }
+
+        let _guard =
+            builder.msg_clippy(format_args!("library{}", crate_description(&self.crates)), target);
+
+        run_cargo(
+            builder,
+            cargo,
+            lint_args(builder, IGNORED_RULES_FOR_STD_AND_RUSTC),
+            &libstd_stamp(builder, compiler, target),
+            vec![],
+            true,
+            false,
+        );
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Rustc {
+    pub target: TargetSelection,
+    /// Whether to lint only a subset of crates.
+    crates: Vec<String>,
+}
+
+impl Step for Rustc {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.crate_or_deps("rustc-main").path("compiler")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        let crates = run.make_run_crates(Alias::Compiler);
+        run.builder.ensure(Rustc { target: run.target, crates });
+    }
+
+    /// Lints the compiler.
+    ///
+    /// This will lint the compiler for a particular stage of the build using
+    /// the `compiler` targeting the `target` architecture.
+    fn run(self, builder: &Builder<'_>) {
+        let compiler = builder.compiler(builder.top_stage, builder.config.build);
+        let target = self.target;
+
+        if compiler.stage != 0 {
+            // If we're not in stage 0, then we won't have a std from the beta
+            // compiler around. That means we need to make sure there's one in
+            // the sysroot for the compiler to find. Otherwise, we're going to
+            // fail when building crates that need to generate code (e.g., build
+            // scripts and their dependencies).
+            builder.ensure(compile::Std::new(compiler, compiler.host));
+            builder.ensure(compile::Std::new(compiler, target));
+        } else {
+            builder.ensure(check::Std::new(target));
+        }
+
+        let mut cargo = builder::Cargo::new(
+            builder,
+            compiler,
+            Mode::Rustc,
+            SourceType::InTree,
+            target,
+            "clippy",
+        );
+
+        rustc_cargo(builder, &mut cargo, target, &compiler);
+
+        // Explicitly pass -p for all compiler crates -- this will force cargo
+        // to also lint the tests/benches/examples for these crates, rather
+        // than just the leaf crate.
+        for krate in &*self.crates {
+            cargo.arg("-p").arg(krate);
+        }
+
+        let _guard =
+            builder.msg_clippy(format_args!("compiler{}", crate_description(&self.crates)), target);
+
+        run_cargo(
+            builder,
+            cargo,
+            lint_args(builder, IGNORED_RULES_FOR_STD_AND_RUSTC),
+            &librustc_stamp(builder, compiler, target),
+            vec![],
+            true,
+            false,
+        );
+    }
+}
+
+macro_rules! lint_any {
+    ($(
+        $name:ident, $path:expr, $readable_name:expr
+        $(,lint_by_default = $lint_by_default:expr)*
+        ;
+    )+) => {
+        $(
+
+        #[derive(Debug, Clone, Hash, PartialEq, Eq)]
+        pub struct $name {
+            pub target: TargetSelection,
+        }
+
+        impl Step for $name {
+            type Output = ();
+            const DEFAULT: bool = if false $(|| $lint_by_default)* { true } else { false };
+
+            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+                run.path($path)
+            }
+
+            fn make_run(run: RunConfig<'_>) {
+                run.builder.ensure($name {
+                    target: run.target,
+                });
+            }
+
+            fn run(self, builder: &Builder<'_>) -> Self::Output {
+                let compiler = builder.compiler(builder.top_stage, builder.config.build);
+                let target = self.target;
+
+                builder.ensure(check::Rustc::new(target, builder));
+
+                let cargo = prepare_tool_cargo(
+                    builder,
+                    compiler,
+                    Mode::ToolRustc,
+                    target,
+                    "clippy",
+                    $path,
+                    SourceType::InTree,
+                    &[],
+                );
+
+                let _guard = builder.msg_tool(
+                    Kind::Clippy,
+                    Mode::ToolRustc,
+                    $readable_name,
+                    compiler.stage,
+                    &compiler.host,
+                    &target,
+                );
+
+                let stamp = builder
+                    .cargo_out(compiler, Mode::ToolRustc, target)
+                    .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()));
+
+                run_cargo(
+                    builder,
+                    cargo,
+                    lint_args(builder, &[]),
+                    &stamp,
+                    vec![],
+                    true,
+                    false,
+                );
+            }
+        }
+        )+
+    }
+}
+
+lint_any!(
+    Bootstrap, "src/bootstrap", "bootstrap";
+    BuildHelper, "src/tools/build_helper", "build_helper";
+    BuildManifest, "src/tools/build-manifest", "build-manifest";
+    CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri";
+    Clippy, "src/tools/clippy", "clippy";
+    CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
+    Compiletest, "src/tools/compiletest", "compiletest";
+    CoverageDump, "src/tools/coverage-dump", "coverage-dump";
+    Jsondocck, "src/tools/jsondocck", "jsondocck";
+    Jsondoclint, "src/tools/jsondoclint", "jsondoclint";
+    LintDocs, "src/tools/lint-docs", "lint-docs";
+    LlvmBitcodeLinker, "src/tools/llvm-bitcode-linker", "llvm-bitcode-linker";
+    Miri, "src/tools/miri", "miri";
+    MiroptTestTools, "src/tools/miropt-test-tools", "miropt-test-tools";
+    OptDist, "src/tools/opt-dist", "opt-dist";
+    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
+    RemoteTestServer, "src/tools/remote-test-server", "remote-test-server";
+    Rls, "src/tools/rls", "rls";
+    RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer";
+    RustDemangler, "src/tools/rust-demangler", "rust-demangler";
+    Rustdoc, "src/tools/rustdoc", "clippy";
+    Rustfmt, "src/tools/rustfmt", "rustfmt";
+    RustInstaller, "src/tools/rust-installer", "rust-installer";
+    Tidy, "src/tools/tidy", "tidy";
+);
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 420336fee14..7cb15fe5590 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -76,6 +76,9 @@ pub fn prebuilt_llvm_config(
     builder: &Builder<'_>,
     target: TargetSelection,
 ) -> Result<LlvmResult, Meta> {
+    // If we have llvm submodule initialized already, sync it.
+    builder.update_existing_submodule(&Path::new("src").join("llvm-project"));
+
     builder.config.maybe_download_ci_llvm();
 
     // If we're using a custom LLVM bail out here, but we can only use a
@@ -94,6 +97,9 @@ pub fn prebuilt_llvm_config(
         }
     }
 
+    // Initialize the llvm submodule if not initialized already.
+    builder.update_submodule(&Path::new("src").join("llvm-project"));
+
     let root = "src/llvm-project/llvm";
     let out_dir = builder.llvm_out(target);
 
@@ -280,7 +286,6 @@ impl Step for Llvm {
             Err(m) => m,
         };
 
-        builder.update_submodule(&Path::new("src").join("llvm-project"));
         if builder.llvm_link_shared() && target.is_windows() {
             panic!("shared linking to LLVM is not currently supported on {}", target.triple);
         }
diff --git a/src/bootstrap/src/core/build_steps/mod.rs b/src/bootstrap/src/core/build_steps/mod.rs
index 50d83789be8..9b7378165de 100644
--- a/src/bootstrap/src/core/build_steps/mod.rs
+++ b/src/bootstrap/src/core/build_steps/mod.rs
@@ -1,5 +1,6 @@
 pub(crate) mod check;
 pub(crate) mod clean;
+pub(crate) mod clippy;
 pub(crate) mod compile;
 pub(crate) mod dist;
 pub(crate) mod doc;
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 8d1ff2fcb24..45b1d5a05f3 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -36,8 +36,9 @@ struct ToolBuild {
 
 impl Builder<'_> {
     #[track_caller]
-    fn msg_tool(
+    pub(crate) fn msg_tool(
         &self,
+        kind: Kind,
         mode: Mode,
         tool: &str,
         build_stage: u32,
@@ -47,7 +48,7 @@ impl Builder<'_> {
         match mode {
             // depends on compiler stage, different to host compiler
             Mode::ToolRustc => self.msg_sysroot_tool(
-                Kind::Build,
+                kind,
                 build_stage,
                 format_args!("tool {tool}"),
                 *host,
@@ -100,6 +101,7 @@ impl Step for ToolBuild {
             cargo.allow_features(self.allow_features);
         }
         let _guard = builder.msg_tool(
+            Kind::Build,
             self.mode,
             self.tool,
             self.compiler.stage,
@@ -481,6 +483,7 @@ impl Step for Rustdoc {
         );
 
         let _guard = builder.msg_tool(
+            Kind::Build,
             Mode::ToolRustc,
             "rustdoc",
             build_compiler.stage,
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index f31bc46d25f..499a74be6b1 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -13,9 +13,9 @@ use std::process::Command;
 use std::sync::OnceLock;
 use std::time::{Duration, Instant};
 
-use crate::core::build_steps::llvm;
 use crate::core::build_steps::tool::{self, SourceType};
 use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, setup, test};
+use crate::core::build_steps::{clippy, llvm};
 use crate::core::config::flags::{Color, Subcommand};
 use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection};
 use crate::prepare_behaviour_dump_dir;
@@ -672,6 +672,7 @@ impl Kind {
             Kind::Doc => "Documenting",
             Kind::Run => "Running",
             Kind::Suggest => "Suggesting",
+            Kind::Clippy => "Linting",
             _ => {
                 let title_letter = self.as_str()[0..1].to_ascii_uppercase();
                 return format!("{title_letter}{}ing", &self.as_str()[1..]);
@@ -726,7 +727,35 @@ impl<'a> Builder<'a> {
                 tool::CoverageDump,
                 tool::LlvmBitcodeLinker
             ),
-            Kind::Check | Kind::Clippy | Kind::Fix => describe!(
+            Kind::Clippy => describe!(
+                clippy::Std,
+                clippy::Rustc,
+                clippy::Bootstrap,
+                clippy::BuildHelper,
+                clippy::BuildManifest,
+                clippy::CargoMiri,
+                clippy::Clippy,
+                clippy::CollectLicenseMetadata,
+                clippy::Compiletest,
+                clippy::CoverageDump,
+                clippy::Jsondocck,
+                clippy::Jsondoclint,
+                clippy::LintDocs,
+                clippy::LlvmBitcodeLinker,
+                clippy::Miri,
+                clippy::MiroptTestTools,
+                clippy::OptDist,
+                clippy::RemoteTestClient,
+                clippy::RemoteTestServer,
+                clippy::Rls,
+                clippy::RustAnalyzer,
+                clippy::RustDemangler,
+                clippy::Rustdoc,
+                clippy::Rustfmt,
+                clippy::RustInstaller,
+                clippy::Tidy,
+            ),
+            Kind::Check | Kind::Fix => describe!(
                 check::Std,
                 check::Rustc,
                 check::Rustdoc,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index c84eb8a684f..a272d8bff00 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -145,7 +145,6 @@ impl LldMode {
 /// `config.example.toml`.
 #[derive(Default, Clone)]
 pub struct Config {
-    pub changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
     pub change_id: Option<usize>,
     pub bypass_bootstrap_lock: bool,
     pub ccache: Option<String>,
@@ -605,7 +604,6 @@ impl Target {
 #[derive(Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 pub(crate) struct TomlConfig {
-    changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
     #[serde(flatten)]
     change_id: ChangeIdWrapper,
     build: Option<Build>,
@@ -645,17 +643,7 @@ trait Merge {
 impl Merge for TomlConfig {
     fn merge(
         &mut self,
-        TomlConfig {
-            build,
-            install,
-            llvm,
-            rust,
-            dist,
-            target,
-            profile: _,
-            changelog_seen,
-            change_id,
-        }: Self,
+        TomlConfig { build, install, llvm, rust, dist, target, profile: _, change_id }: Self,
         replace: ReplaceOpt,
     ) {
         fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
@@ -667,7 +655,6 @@ impl Merge for TomlConfig {
                 }
             }
         }
-        self.changelog_seen.merge(changelog_seen, replace);
         self.change_id.inner.merge(change_id.inner, replace);
         do_merge(&mut self.build, build, replace);
         do_merge(&mut self.install, install, replace);
@@ -1400,7 +1387,6 @@ impl Config {
         }
         toml.merge(override_toml, ReplaceOpt::Override);
 
-        config.changelog_seen = toml.changelog_seen;
         config.change_id = toml.change_id.inner;
 
         let Build {
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 8cd538953c5..59e16b65427 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -1,5 +1,5 @@
 use super::{flags::Flags, ChangeIdWrapper, Config};
-use crate::core::build_steps::check::get_clippy_rules_in_order;
+use crate::core::build_steps::clippy::get_clippy_rules_in_order;
 use crate::core::config::{LldMode, TomlConfig};
 
 use clap::CommandFactory;
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 1a8322c0dfd..f37b0f10437 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -630,6 +630,18 @@ impl Build {
         }
     }
 
+    /// Updates the given submodule only if it's initialized already; nothing happens otherwise.
+    pub fn update_existing_submodule(&self, submodule: &Path) {
+        // Avoid running git when there isn't a git checkout.
+        if !self.config.submodules(self.rust_info()) {
+            return;
+        }
+
+        if GitInfo::new(false, submodule).is_managed_git_subrepository() {
+            self.update_submodule(submodule);
+        }
+    }
+
     /// Executes the entire build, as configured by the flags and configuration.
     pub fn build(&mut self) {
         unsafe {
@@ -1080,6 +1092,16 @@ impl Build {
 
     #[must_use = "Groups should not be dropped until the Step finishes running"]
     #[track_caller]
+    fn msg_clippy(
+        &self,
+        what: impl Display,
+        target: impl Into<Option<TargetSelection>>,
+    ) -> Option<gha::Group> {
+        self.msg(Kind::Clippy, self.config.stage, what, self.config.build, target)
+    }
+
+    #[must_use = "Groups should not be dropped until the Step finishes running"]
+    #[track_caller]
     fn msg_check(
         &self,
         what: impl Display,
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 277ec00fa62..db3df598a0c 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -170,4 +170,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "`rust.split-debuginfo` has been moved to `target.<triple>.split-debuginfo` and its default value is determined for each target individually.",
     },
+    ChangeInfo {
+        change_id: 123711,
+        severity: ChangeSeverity::Warning,
+        summary: "The deprecated field `changelog-seen` has been removed. Using that field in `config.toml` from now on will result in breakage.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 89fcac2a84b..cc86e3bab0c 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -1,3 +1,10 @@
+//! Facilitates the management and generation of tarballs.
+//!
+//! Tarballs efficiently hold Rust compiler build artifacts and
+//! capture a snapshot of each boostrap stage.
+//! In uplifting, a tarball from Stage N captures essential components
+//! to assemble Stage N + 1 compiler.
+
 use std::{
     path::{Path, PathBuf},
     process::Command,
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 6918574814f..ae8dfadec73 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -46,7 +46,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs.
            python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
-           python3 ../x.py clippy compiler -Aclippy::all -Dclippy::correctness && \
+           python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
            python3 ../x.py test --stage 0 core alloc std test proc_macro && \
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index db85753145d..31096b6df92 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -77,6 +77,7 @@
 - [Profile-guided Optimization](profile-guided-optimization.md)
 - [Instrumentation-based Code Coverage](instrument-coverage.md)
 - [Linker-plugin-based LTO](linker-plugin-lto.md)
+- [Checking conditional configurations](check-cfg.md)
 - [Exploit Mitigations](exploit-mitigations.md)
 - [Symbol Mangling](symbol-mangling/index.md)
     - [v0 Symbol Format](symbol-mangling/v0.md)
diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/rustc/src/check-cfg.md
index 836929aba0b..37708bda1f3 100644
--- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md
+++ b/src/doc/rustc/src/check-cfg.md
@@ -1,10 +1,4 @@
-# `check-cfg`
-
-The tracking issue for this feature is: [#82450](https://github.com/rust-lang/rust/issues/82450).
-
-------------------------
-
-This feature enables checking of conditional configuration.
+# Checking conditional configurations
 
 `rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
 check them. The `--check-cfg` option takes a value, called the _check cfg specification_.
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index c8f5d649570..35bf2c27ff1 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -479,6 +479,26 @@ then `-C target-feature=+crt-static` "wins" over `-C relocation-model=pic`,
 and the linker is instructed (`-static`) to produce a statically linked
 but not position-independent executable.
 
+## relro-level
+
+This flag controls what level of RELRO (Relocation Read-Only) is enabled. RELRO is an exploit
+mitigation which makes the Global Offset Table (GOT) read-only.
+
+Supported values for this option are:
+
+- `off`: Dynamically linked functions are resolved lazily and the GOT is writable.
+- `partial`: Dynamically linked functions are resolved lazily and written into the Procedure
+  Linking Table (PLT) part of the GOT (`.got.plt`). The non-PLT part of the GOT (`.got`) is made
+  read-only and both are moved to prevent writing from buffer overflows.
+- `full`: Dynamically linked functions are resolved at the start of program execution and the
+  Global Offset Table (`.got`/`.got.plt`) is populated eagerly and then made read-only. The GOT is
+  also moved to prevent writing from buffer overflows. Full RELRO uses more memory and increases
+  process startup time.
+
+This flag is ignored on platforms where RELRO is not supported (targets which do not use the ELF
+binary format), such as Windows or macOS. Each rustc target has its own default for RELRO. rustc
+enables Full RELRO by default on platforms where it is supported.
+
 ## remark
 
 This flag lets you print remarks for optimization passes.
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 5e02453e236..7c605333c25 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -18,6 +18,16 @@ The value can either be a single identifier or two identifiers separated by `=`.
 For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond
 to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
 
+<a id="option-check-cfg"></a>
+## `--check-cfg`: enables checking conditional configurations
+
+This flag will enable checking conditional configurations.
+Refer to the [Checking conditional configurations](check-cfg.md) of this book
+for further details and explanation.
+
+For examples, `--check-cfg 'cfg(verbose)'` or `--check-cfg 'cfg(feature, values("serde"))'`.
+These correspond to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
+
 <a id="option-l-search-path"></a>
 ## `-L`: add a directory to the library search path
 
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index fe5cb529c26..822f341b370 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -131,6 +131,20 @@ This flag accepts the same values as `rustc --cfg`, and uses it to configure
 compilation. The example above uses `feature`, but any of the `cfg` values
 are acceptable.
 
+## `--check-cfg`: check configuration flags
+
+This flag accepts the same values as `rustc --check-cfg`, and uses it to
+check configuration flags.
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs --check-cfg='cfg(my_cfg, values("foo", "bar"))'
+```
+
+The example above check every well known names and values (`target_os`, `doc`, `test`, ...)
+and check the values of `my_cfg`: `foo` and `bar`.
+
 ## `--extern`: specify a dependency's location
 
 Using this flag looks like this:
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 41602dec44c..bdb55de8d63 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -618,22 +618,6 @@ crate being documented (`foobar`) and a path to output the calls
 To scrape examples from test code, e.g. functions marked `#[test]`, then
 add the `--scrape-tests` flag.
 
-### `--check-cfg`: check configuration flags
-
- * Tracking issue: [#82450](https://github.com/rust-lang/rust/issues/82450)
-
-This flag accepts the same values as `rustc --check-cfg`, and uses it to check configuration flags.
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options \
-    --check-cfg='cfg(feature, values("foo", "bar"))'
-```
-
-The example above check every well known names and values (`target_os`, `doc`, `test`, ...)
-and check the values of `feature`: `foo` and `bar`.
-
 ### `--generate-link-to-definition`: Generate links on types in source code
 
  * Tracking issue: [#89095](https://github.com/rust-lang/rust/issues/89095)
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 925d41e67f8..fc4f48262e5 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1,5 +1,25 @@
-//! This module contains the "cleaned" pieces of the AST, and the functions
-//! that clean them.
+//! This module defines the primary IR[^1] used in rustdoc together with the procedures that
+//! transform rustc data types into it.
+//!
+//! This IR — commonly referred to as the *cleaned AST* — is modeled after the [AST][ast].
+//!
+//! There are two kinds of transformation — *cleaning* — procedures:
+//!
+//! 1. Cleans [HIR][hir] types. Used for user-written code and inlined local re-exports
+//!    both found in the local crate.
+//! 2. Cleans [`rustc_middle::ty`] types. Used for inlined cross-crate re-exports and anything
+//!    output by the trait solver (e.g., when synthesizing blanket and auto-trait impls).
+//!    They usually have `ty` or `middle` in their name.
+//!
+//! Their name is prefixed by `clean_`.
+//!
+//! Both the HIR and the `rustc_middle::ty` IR are quite removed from the source code.
+//! The cleaned AST on the other hand is closer to it which simplifies the rendering process.
+//! Furthermore, operating on a single IR instead of two avoids duplicating efforts down the line.
+//!
+//! This IR is consumed by both the HTML and the JSON backend.
+//!
+//! [^1]: Intermediate representation.
 
 mod auto_trait;
 mod blanket_impl;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index b592bd76e4c..aeb7137b722 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -408,7 +408,7 @@ impl Item {
 
     pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
         span_of_fragments(&self.attrs.doc_strings)
-            .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
+            .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
     }
 
     /// Combine all doc strings into a single value handling indentation and newlines as needed.
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 22a3cf4d44d..0ad4c9c2346 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -60,11 +60,8 @@ pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) ->
     for cfg in &options.cfgs {
         content.push(format!("--cfg={cfg}"));
     }
-    if !options.check_cfgs.is_empty() {
-        content.push("-Zunstable-options".to_string());
-        for check_cfg in &options.check_cfgs {
-            content.push(format!("--check-cfg={check_cfg}"));
-        }
+    for check_cfg in &options.check_cfgs {
+        content.push(format!("--check-cfg={check_cfg}"));
     }
 
     for lib_str in &options.lib_strs {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 4e46f847fd7..a949f795753 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -56,7 +56,7 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::RustcVersion;
 use rustc_span::{
     symbol::{sym, Symbol},
-    BytePos, FileName, RealFileName,
+    BytePos, FileName, RealFileName, DUMMY_SP,
 };
 use serde::ser::SerializeMap;
 use serde::{Serialize, Serializer};
@@ -2414,7 +2414,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
         let contents = match fs::read_to_string(&path) {
             Ok(contents) => contents,
             Err(err) => {
-                let span = item.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner());
+                let span = item.span(tcx).map_or(DUMMY_SP, |span| span.inner());
                 tcx.dcx().span_err(span, format!("failed to read file {}: {err}", path.display()));
                 return false;
             }
@@ -2495,7 +2495,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
                 file.start_pos + BytePos(byte_max),
             ))
         })()
-        .unwrap_or(rustc_span::DUMMY_SP);
+        .unwrap_or(DUMMY_SP);
 
         let mut decoration_info = FxHashMap::default();
         decoration_info.insert("highlight focus", vec![byte_ranges.remove(0)]);
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index 738ea0aee7e..a27e327f235 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -3,8 +3,7 @@ use askama::Template;
 use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
-use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::Adt;
+use rustc_middle::ty::{self, layout::LayoutError};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::{Primitive, TagEncoding, Variants};
 
@@ -57,7 +56,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
             variants
                 .iter_enumerated()
                 .map(|(variant_idx, variant_layout)| {
-                    let Adt(adt, _) = type_layout.ty.kind() else {
+                    let ty::Adt(adt, _) = type_layout.ty.kind() else {
                         span_bug!(tcx.def_span(ty_def_id), "not an adt")
                     };
                     let name = adt.variant(variant_idx).name;
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 940b62be0c9..ee7d19634b4 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -462,6 +462,7 @@ function preLoadCss(cssUrl) {
 
             case "s":
             case "S":
+            case "/":
                 ev.preventDefault();
                 searchState.focus();
                 break;
@@ -1334,7 +1335,7 @@ function preLoadCss(cssUrl) {
 
         const shortcuts = [
             ["?", "Show this help dialog"],
-            ["S", "Focus the search field"],
+            ["S / /", "Focus the search field"],
             ["↑", "Move up in search results"],
             ["↓", "Move down in search results"],
             ["← / →", "Switch result tab (when results focused)"],
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 1dc9041658e..1e01cd70b96 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -129,7 +129,7 @@
                         aria-label="Run search in the documentation" {#+ #}
                         autocomplete="off" {#+ #}
                         spellcheck="false" {#+ #}
-                        placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {#+ #}
+                        placeholder="Type ‘S’ or ‘/’ to search, ‘?’ for more options…" {#+ #}
                         type="search"> {# #}
                     <div id="help-button" tabindex="-1"> {# #}
                         <a href="{{page.root_path|safe}}help.html" title="help">?</a> {# #}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b78fb4c4eee..f2a7518b4ce 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -242,7 +242,7 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optmulti("L", "library-path", "directory to add to crate search path", "DIR")
         }),
         stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")),
-        unstable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")),
+        stable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")),
         stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")),
         unstable("extern-html-root-url", |o| {
             o.optmulti(
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 48eca1b164695022295ce466b64b44e4e0228b0
+Subproject 6f06fe908a5ee0f415c187f868ea627e82efe07
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index 68841076f77..2c168405ee2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -77,7 +77,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
 
         let (help, final_suggestion) = if let Some(method) = omit_cast.corresponding_item() {
             // don't force absolute path
-            let method = qpath_to_string(method);
+            let method = qpath_to_string(&cx.tcx, method);
             ("try call directly", format!("{method}{turbofish}()"))
         } else {
             let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index b1aa472aa03..adf6f7c4737 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -88,7 +88,7 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> {
         if !prev_is_dollar
             && let Some(span) = is_crate_keyword(curr)
             && let Some(next) = cursor.look_ahead(0)
-            && is_token(next, &TokenKind::ModSep)
+            && is_token(next, &TokenKind::PathSep)
         {
             return Some(span);
         }
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 80327586fed..0c9ad5e8d00 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -9,7 +9,7 @@ use rustc_hir::{
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
-use rustc_middle::ty::{self, Adt, AdtDef, GenericArgsRef, Ty, TypeckResults};
+use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty, TypeckResults};
 use rustc_session::impl_lint_pass;
 use rustc_span::sym;
 
@@ -79,7 +79,7 @@ fn is_path_self(e: &Expr<'_>) -> bool {
 fn contains_trait_object(ty: Ty<'_>) -> bool {
     match ty.kind() {
         ty::Ref(_, ty, _) => contains_trait_object(*ty),
-        Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
+        ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
         ty::Dynamic(..) => true,
         _ => false,
     }
@@ -198,7 +198,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
             && let ImplItemKind::Fn(_, b) = &impl_item.kind
             && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
-            && let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
+            && let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
             && let attrs = cx.tcx.hir().attrs(item.hir_id())
             && !attrs.iter().any(|attr| attr.doc_str().is_some())
             && cx.tcx.hir().attrs(impl_item_hir).is_empty()
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index e55a988321b..651f2ebaee6 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -38,7 +38,7 @@ pub fn check(
     // of all `#[test]` attributes in not ignored code examples
     fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec<Range<usize>>) {
         rustc_driver::catch_fatal_errors(|| {
-            rustc_span::create_session_globals_then(edition, || {
+            rustc_span::create_session_globals_then(edition, None, || {
                 let mut test_attr_spans = vec![];
                 let filename = FileName::anon_source_code(&code);
 
diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
index ba2495c17a2..d62d008d480 100644
--- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::RawPtr;
+use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -44,7 +44,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr {
             && seg.ident.name == sym!(from_raw)
             && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
             && let arg_kind = cx.typeck_results().expr_ty(arg).kind()
-            && let RawPtr(ty, _) = arg_kind
+            && let ty::RawPtr(ty, _) = arg_kind
             && is_c_void(cx, *ty)
         {
             let msg = format!("creating a `{type_str}` from a void raw pointer");
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 2d757883f26..995dd782cbb 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -1,4 +1,4 @@
-use rustc_hir::{self as hir, intravisit, HirIdSet};
+use rustc_hir::{self as hir, intravisit, HirId, HirIdSet};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::def_id::LocalDefId;
@@ -74,7 +74,7 @@ fn check_raw_ptr<'tcx>(
     }
 }
 
-fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<hir::HirId> {
+fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<HirId> {
     if let (&hir::PatKind::Binding(_, id, _, _), Some(&ty::RawPtr(_, _))) = (
         &arg.pat.kind,
         cx.maybe_typeck_results()
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index 93f088d3e33..c3a0b40a677 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -2,7 +2,7 @@ use rustc_errors::Diag;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
@@ -25,7 +25,7 @@ fn result_err_ty<'tcx>(
             .tcx
             .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output())
         && is_type_diagnostic_item(cx, ty, sym::Result)
-        && let Adt(_, args) = ty.kind()
+        && let ty::Adt(_, args) = ty.kind()
     {
         let err_ty = args.type_at(1);
         Some((hir_ty, err_ty))
@@ -86,7 +86,7 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
 }
 
 fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
-    if let Adt(adt, subst) = err_ty.kind()
+    if let ty::Adt(adt, subst) = err_ty.kind()
         && let Some(local_def_id) = err_ty
             .ty_adt_def()
             .expect("already checked this is adt")
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index b8d7e8f3b07..f225c6e7f04 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Int, IntTy, Ty, Uint, UintTy};
+use rustc_middle::ty::{IntTy, Ty, UintTy};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
@@ -97,6 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
 }
 
 fn get_int_max(ty: Ty<'_>) -> Option<u128> {
+    use rustc_middle::ty::{Int, Uint};
     match ty.peel_refs().kind() {
         Int(IntTy::I8) => i8::MAX.try_into().ok(),
         Int(IntTy::I16) => i16::MAX.try_into().ok(),
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 4d1f89b1d9d..6ddc8346511 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -7,6 +7,7 @@ use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::HirId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
@@ -87,9 +88,9 @@ impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
     extract_msrv_attr!(LateContext);
 }
 
-fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir::HirId, SliceLintInformation> {
-    let mut removed_pat: FxHashSet<hir::HirId> = FxHashSet::default();
-    let mut slices: FxIndexMap<hir::HirId, SliceLintInformation> = FxIndexMap::default();
+fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<HirId, SliceLintInformation> {
+    let mut removed_pat: FxHashSet<HirId> = FxHashSet::default();
+    let mut slices: FxIndexMap<HirId, SliceLintInformation> = FxIndexMap::default();
     pat.walk_always(|pat| {
         // We'll just ignore mut and ref mut for simplicity sake right now
         if let hir::PatKind::Binding(
@@ -206,10 +207,10 @@ impl SliceLintInformation {
 
 fn filter_lintable_slices<'tcx>(
     cx: &LateContext<'tcx>,
-    slice_lint_info: FxIndexMap<hir::HirId, SliceLintInformation>,
+    slice_lint_info: FxIndexMap<HirId, SliceLintInformation>,
     max_suggested_slice: u64,
     scope: &'tcx hir::Expr<'tcx>,
-) -> FxIndexMap<hir::HirId, SliceLintInformation> {
+) -> FxIndexMap<HirId, SliceLintInformation> {
     let mut visitor = SliceIndexLintingVisitor {
         cx,
         slice_lint_info,
@@ -223,7 +224,7 @@ fn filter_lintable_slices<'tcx>(
 
 struct SliceIndexLintingVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    slice_lint_info: FxIndexMap<hir::HirId, SliceLintInformation>,
+    slice_lint_info: FxIndexMap<HirId, SliceLintInformation>,
     max_suggested_slice: u64,
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index 6feb1885576..0bf7389ef9c 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
@@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
         }
         if let ItemKind::Enum(ref def, _) = item.kind {
             let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            let Adt(adt, subst) = ty.kind() else {
+            let ty::Adt(adt, subst) = ty.kind() else {
                 panic!("already checked whether this is an enum")
             };
             if adt.variants().len() <= 1 {
@@ -167,7 +167,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
 }
 
 fn maybe_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    if let Adt(_def, args) = ty.kind()
+    if let ty::Adt(_def, args) = ty.kind()
         && args.types().next().is_some()
         && let Some(copy_trait) = cx.tcx.lang_items().copy_trait()
     {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
index d1f637ec78c..310675d01a2 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
     if is_type_diagnostic_item(cx, ex_ty, sym::Result) {
         for arm in arms {
             if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind {
-                let path_str = rustc_hir_pretty::qpath_to_string(path);
+                let path_str = rustc_hir_pretty::qpath_to_string(&cx.tcx, path);
                 if path_str == "Err" {
                     let mut matching_wild = inner.iter().any(is_wild);
                     let mut ident_bind_name = kw::Underscore;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
index c3ad4db3875..efd1a718504 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
@@ -4,7 +4,7 @@ use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{Ref, Slice};
+use rustc_middle::ty;
 use rustc_span::Span;
 
 use super::UNNECESSARY_JOIN;
@@ -18,9 +18,9 @@ pub(super) fn check<'tcx>(
 ) {
     let applicability = Applicability::MachineApplicable;
     let collect_output_adjusted_type = cx.typeck_results().expr_ty_adjusted(join_self_arg);
-    if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind()
+    if let ty::Ref(_, ref_type, _) = collect_output_adjusted_type.kind()
         // the turbofish for collect is ::<Vec<String>>
-        && let Slice(slice) = ref_type.kind()
+        && let ty::Slice(slice) = ref_type.kind()
         && is_type_lang_item(cx, *slice, LangItem::String)
         // the argument for join is ""
         && let ExprKind::Lit(spanned) = &join_arg.kind
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 79f0a398d55..8c2f43c97f4 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -4,7 +4,7 @@ use clippy_utils::{def_path_def_ids, trait_ref_of_method};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
@@ -153,7 +153,7 @@ impl MutableKeyType {
     // generics (because the compiler cannot ensure immutability for unknown types).
     fn check_ty_<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
         let ty = ty.peel_refs();
-        if let Adt(def, args) = ty.kind() {
+        if let ty::Adt(def, args) = ty.kind() {
             let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
                 .iter()
                 .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 6867f76a723..0a3b769c3e6 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
                         cx,
                         arguments.iter().collect(),
                         cx.typeck_results().expr_ty(fn_expr),
-                        &rustc_hir_pretty::qpath_to_string(path),
+                        &rustc_hir_pretty::qpath_to_string(&cx.tcx, path),
                         "function",
                     );
                 }
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 73fc34c2450..5ca388d67a1 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, InnerSpan, Span};
+use rustc_span::{sym, DUMMY_SP, InnerSpan, Span};
 use rustc_target::abi::VariantIdx;
 
 // FIXME: this is a correctness problem but there's no suitable
@@ -290,9 +290,7 @@ impl NonCopyConst {
             promoted: None,
         };
         let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx);
-        let result = cx
-            .tcx
-            .const_eval_global_id_for_typeck(param_env, cid, rustc_span::DUMMY_SP);
+        let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP);
         self.is_value_unfrozen_raw(cx, result, ty)
     }
 
@@ -303,7 +301,7 @@ impl NonCopyConst {
             cx.tcx,
             cx.param_env,
             ty::UnevaluatedConst::new(def_id, args),
-            rustc_span::DUMMY_SP,
+            DUMMY_SP,
         );
         self.is_value_unfrozen_raw(cx, result, ty)
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 2f85130fba1..435eb9048f5 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -6,6 +6,7 @@ use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::{HirId, HirIdSet};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
@@ -98,10 +99,10 @@ pub(super) fn check<'tcx>(
     }
 }
 
-fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
-    struct S(hir::HirIdSet);
+fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
+    struct S(HirIdSet);
     impl Delegate<'_> for S {
-        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
             if matches!(kind, BorrowKind::ImmBorrow | BorrowKind::UniqueImmBorrow) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
@@ -111,13 +112,13 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
             }
         }
 
-        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
-        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
     }
 
-    let mut s = S(hir::HirIdSet::default());
+    let mut s = S(HirIdSet::default());
     let infcx = cx.tcx.infer_ctxt().build();
     let mut v = ExprUseVisitor::new(
         &mut s,
@@ -130,10 +131,10 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
     s.0
 }
 
-fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
-    struct S(hir::HirIdSet);
+fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
+    struct S(HirIdSet);
     impl Delegate<'_> for S {
-        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
             if matches!(kind, BorrowKind::MutBorrow) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
@@ -143,13 +144,13 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
             }
         }
 
-        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
-        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
     }
 
-    let mut s = S(hir::HirIdSet::default());
+    let mut s = S(HirIdSet::default());
     let infcx = cx.tcx.infer_ctxt().build();
     let mut v = ExprUseVisitor::new(
         &mut s,
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 83b32000a9f..d6592622f0b 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -8,7 +8,7 @@ use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_i
 use hir::LifetimeName;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::def_id::DefId;
-use rustc_hir::hir_id::HirIdMap;
+use rustc_hir::hir_id::{HirId, HirIdMap};
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{
     self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
@@ -324,7 +324,7 @@ struct PtrArgReplacement {
 
 struct PtrArg<'tcx> {
     idx: usize,
-    emission_id: hir::HirId,
+    emission_id: HirId,
     span: Span,
     ty_did: DefId,
     ty_name: Symbol,
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index d3540bc8e1c..038eb92d652 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{self as hir};
+use rustc_hir::{self as hir, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::{GenericArgKind, Ty};
 use rustc_session::impl_lint_pass;
@@ -55,7 +55,7 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
 
 #[derive(Default)]
 pub struct SignificantDropTightening<'tcx> {
-    apas: FxIndexMap<hir::HirId, AuxParamsAttr>,
+    apas: FxIndexMap<HirId, AuxParamsAttr>,
     /// Auxiliary structure used to avoid having to verify the same type multiple times.
     seen_types: FxHashSet<Ty<'tcx>>,
     type_cache: FxHashMap<Ty<'tcx>, bool>,
@@ -359,9 +359,9 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o
 /// Auxiliary parameters used on each block check of an item
 struct AuxParams<'others, 'stmt, 'tcx> {
     //// See [AuxParamsAttr].
-    apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>,
+    apas: &'others mut FxIndexMap<HirId, AuxParamsAttr>,
     /// The current block identifier that is being visited.
-    curr_block_hir_id: hir::HirId,
+    curr_block_hir_id: HirId,
     /// The current block span that is being visited.
     curr_block_span: Span,
     /// The current statement that is being visited.
@@ -369,10 +369,10 @@ struct AuxParams<'others, 'stmt, 'tcx> {
 }
 
 impl<'others, 'stmt, 'tcx> AuxParams<'others, 'stmt, 'tcx> {
-    fn new(apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self {
+    fn new(apas: &'others mut FxIndexMap<HirId, AuxParamsAttr>, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self {
         Self {
             apas,
-            curr_block_hir_id: hir::HirId::INVALID,
+            curr_block_hir_id: HirId::INVALID,
             curr_block_span: DUMMY_SP,
             curr_stmt: Cow::Borrowed(curr_stmt),
         }
@@ -389,7 +389,7 @@ struct AuxParamsAttr {
     has_expensive_expr_after_last_attr: bool,
 
     /// The identifier of the block that involves the first `#[has_significant_drop]`.
-    first_block_hir_id: hir::HirId,
+    first_block_hir_id: HirId,
     /// The span of the block that involves the first `#[has_significant_drop]`.
     first_block_span: Span,
     /// The binding or variable that references the initial construction of the type marked with
@@ -414,7 +414,7 @@ impl Default for AuxParamsAttr {
         Self {
             counter: 0,
             has_expensive_expr_after_last_attr: false,
-            first_block_hir_id: hir::HirId::INVALID,
+            first_block_hir_id: HirId::INVALID,
             first_bind_ident: Ident::empty(),
             first_block_span: DUMMY_SP,
             first_method_span: DUMMY_SP,
@@ -428,7 +428,7 @@ impl Default for AuxParamsAttr {
 
 fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
     hir::Stmt {
-        hir_id: hir::HirId::INVALID,
+        hir_id: HirId::INVALID,
         kind: hir::StmtKind::Expr(expr),
         span: DUMMY_SP,
     }
diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
index d1f7c6417c7..e14480b8655 100644
--- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
@@ -4,7 +4,7 @@ use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf as _;
-use rustc_middle::ty::{Adt, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -49,7 +49,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
             && !in_trait_impl(cx, hir_ty.hir_id)
             && let ty = ty_from_hir_ty(cx, hir_ty)
             && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
-            && let Adt(_, args) = ty.kind()
+            && let ty::Adt(_, args) = ty.kind()
             && let ty = args.type_at(1)
             // Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of
             // https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/sty.rs#L968
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index f594a40ff59..9f0bd4ea7e2 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -709,7 +709,8 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
         (Tup(l), Tup(r)) => over(l, r, |l, r| eq_ty(l, r)),
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
         (TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, eq_generic_bound),
-        (ImplTrait(_, lg), ImplTrait(_, rg)) => over(lg, rg, eq_generic_bound),
+        (ImplTrait(_, lg, lc), ImplTrait(_, rg, rc)) =>
+            over(lg, rg, eq_generic_bound) && both(lc, rc, |lc, rc| over(lc.0.as_slice(), rc.0.as_slice(), eq_precise_capture)),
         (Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
         _ => false,
@@ -770,6 +771,14 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool {
     }
 }
 
+pub fn eq_precise_capture(l: &PreciseCapturingArg, r: &PreciseCapturingArg) -> bool {
+    match (l, r) {
+        (PreciseCapturingArg::Lifetime(l), PreciseCapturingArg::Lifetime(r)) => l.ident == r.ident,
+        (PreciseCapturingArg::Arg(l, _), PreciseCapturingArg::Arg(r, _)) => l.segments[0].ident == r.segments[0].ident,
+        _ => false,
+    }
+}
+
 fn eq_term(l: &Term, r: &Term) -> bool {
     match (l, r) {
         (Term::Ty(l), Term::Ty(r)) => eq_ty(l, r),
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index ab1be66dc78..1afc5ed0157 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::{TypeVariableOrigin};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::Scalar;
@@ -276,8 +276,8 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
         .map(|arg| {
             arg.into().unwrap_or_else(|| {
                 let orig = TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
                     span: DUMMY_SP,
+                    param_def_id: None,
                 };
                 infcx.next_ty_var(orig).into()
             })
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index f78e0363f55..f5d7ce1c5f9 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -265,7 +265,10 @@ impl TestProps {
             aux_bins: vec![],
             aux_crates: vec![],
             revisions: vec![],
-            rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())],
+            rustc_env: vec![
+                ("RUSTC_ICE".to_string(), "0".to_string()),
+                ("RUST_BACKTRACE".to_string(), "short".to_string()),
+            ],
             unset_rustc_env: vec![("RUSTC_LOG_COLOR".to_string())],
             exec_env: vec![],
             unset_exec_env: vec![],
@@ -839,6 +842,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-profiler-support",
     "needs-relocation-model-pic",
     "needs-run-enabled",
+    "needs-rust-lld",
     "needs-rust-lldb",
     "needs-sanitizer-address",
     "needs-sanitizer-cfi",
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 38d22fef113..1dd639a8918 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2173,8 +2173,8 @@ impl<'test> TestCx<'test> {
         let aux_dir = self.aux_output_dir();
         self.build_all_auxiliary(&self.testpaths, &aux_dir, &mut rustc);
 
-        self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
         rustc.envs(self.props.rustc_env.clone());
+        self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
         self.compose_and_run(
             rustc,
             self.config.compile_lib_path.to_str().unwrap(),
@@ -2220,10 +2220,10 @@ impl<'test> TestCx<'test> {
         );
         aux_cx.build_all_auxiliary(of, &aux_dir, &mut aux_rustc);
 
+        aux_rustc.envs(aux_props.rustc_env.clone());
         for key in &aux_props.unset_rustc_env {
             aux_rustc.env_remove(key);
         }
-        aux_rustc.envs(aux_props.rustc_env.clone());
 
         let (aux_type, crate_type) = if is_bin {
             (AuxType::Bin, Some("bin"))
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index b7c8b9ed2e3..2566124a037 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -270,7 +270,6 @@ impl<'a> LintExtractor<'a> {
         if matches!(
             lint.name.as_str(),
             "unused_features" // broken lint
-            | "unstable_features" // deprecated
         ) {
             return Ok(());
         }
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index ca8b35a17be..b774ca8fa72 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -412,8 +412,11 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
     // Arguments are treated very differently depending on whether this crate is
     // for interpretation by Miri, or for use by a build script / proc macro.
     if target_crate {
-        // Set the sysroot.
-        cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
+        if phase != RustcPhase::Setup {
+            // Set the sysroot -- except during setup, where we don't have an existing sysroot yet
+            // and where the bootstrap wrapper adds its own `--sysroot` flag so we can't set ours.
+            cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
+        }
 
         // Forward arguments, but patched.
         let emit_flag = "--emit";
@@ -578,9 +581,9 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
     }
 
     if phase != RunnerPhase::Rustdoc {
-        // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot when invoking
-        // rustdoc itself, which will forward that flag when invoking rustc (i.e., us), so the flag
-        // is present in `info.args`.
+        // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot in
+        // `phase_rustdoc`. rustdoc will forward that flag when invoking rustc (i.e., us), so the
+        // flag is present in `info.args`.
         cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
     }
     // Forward rustc arguments.
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index 8d76a488269..f21315790a5 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -260,7 +260,7 @@ impl GlobalStateInner {
         &mut self,
         id: AllocId,
         alloc_size: Size,
-        kind: MemoryKind<machine::MiriMemoryKind>,
+        kind: MemoryKind,
         machine: &MiriMachine<'_, '_>,
     ) -> AllocState {
         match self.borrow_tracker_method {
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 96ff298402d..b4005515d9d 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -509,7 +509,7 @@ impl Stacks {
         id: AllocId,
         size: Size,
         state: &mut GlobalStateInner,
-        kind: MemoryKind<MiriMemoryKind>,
+        kind: MemoryKind,
         machine: &MiriMachine<'_, '_>,
     ) -> Self {
         let (base_tag, perm) = match kind {
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index a3d49756e4c..492e324de45 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -34,7 +34,7 @@ impl<'tcx> Tree {
         id: AllocId,
         size: Size,
         state: &mut GlobalStateInner,
-        _kind: MemoryKind<machine::MiriMemoryKind>,
+        _kind: MemoryKind,
         machine: &MiriMachine<'_, 'tcx>,
     ) -> Self {
         let tag = state.base_ptr_tag(id, machine); // Fresh tag for the root
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index d51160b2831..95049b91cba 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -844,7 +844,7 @@ impl VClockAlloc {
         global: &GlobalState,
         thread_mgr: &ThreadManager<'_, '_>,
         len: Size,
-        kind: MemoryKind<MiriMemoryKind>,
+        kind: MemoryKind,
         current_span: Span,
     ) -> VClockAlloc {
         let (alloc_timestamp, alloc_index) = match kind {
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index dfbcaaac5c6..d44d04e9bf8 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -115,7 +115,7 @@ pub enum NonHaltingDiagnostic {
     /// This `Item` was popped from the borrow stack. The string explains the reason.
     PoppedPointerTag(Item, String),
     CreatedCallId(CallId),
-    CreatedAlloc(AllocId, Size, Align, MemoryKind<MiriMemoryKind>),
+    CreatedAlloc(AllocId, Size, Align, MemoryKind),
     FreedAlloc(AllocId),
     AccessedAlloc(AllocId, AccessKind),
     RejectedIsolatedOp(String),
@@ -447,7 +447,7 @@ pub fn report_error<'tcx, 'mir>(
 
 pub fn report_leaks<'mir, 'tcx>(
     ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
-    leaks: Vec<(AllocId, MemoryKind<MiriMemoryKind>, Allocation<Provenance, AllocExtra<'tcx>>)>,
+    leaks: Vec<(AllocId, MemoryKind, Allocation<Provenance, AllocExtra<'tcx>>)>,
 ) {
     let mut any_pruned = false;
     for (id, kind, mut alloc) in leaks {
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index fbe4c9c6760..2e19c9ff713 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -128,7 +128,7 @@ pub use crate::eval::{
 };
 pub use crate::helpers::{AccessKind, EvalContextExt as _};
 pub use crate::machine::{
-    AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
+    AllocExtra, FrameExtra, MemoryKind, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
     PrimitiveLayouts, Provenance, ProvenanceExtra,
 };
 pub use crate::mono_hash_map::MonoHashMap;
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index ff081328a72..1d06d5c69d3 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -135,9 +135,9 @@ pub enum MiriMemoryKind {
     Mmap,
 }
 
-impl From<MiriMemoryKind> for MemoryKind<MiriMemoryKind> {
+impl From<MiriMemoryKind> for MemoryKind {
     #[inline(always)]
-    fn from(kind: MiriMemoryKind) -> MemoryKind<MiriMemoryKind> {
+    fn from(kind: MiriMemoryKind) -> MemoryKind {
         MemoryKind::Machine(kind)
     }
 }
@@ -185,6 +185,8 @@ impl fmt::Display for MiriMemoryKind {
     }
 }
 
+pub type MemoryKind = interpret::MemoryKind<MiriMemoryKind>;
+
 /// Pointer provenance.
 #[derive(Clone, Copy)]
 pub enum Provenance {
@@ -863,10 +865,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     type ProvenanceExtra = ProvenanceExtra;
     type Bytes = Box<[u8]>;
 
-    type MemoryMap = MonoHashMap<
-        AllocId,
-        (MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra, Self::Bytes>),
-    >;
+    type MemoryMap =
+        MonoHashMap<AllocId, (MemoryKind, Allocation<Provenance, Self::AllocExtra, Self::Bytes>)>;
 
     const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global);
 
@@ -1088,7 +1088,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx: &MiriInterpCx<'mir, 'tcx>,
         id: AllocId,
         alloc: Cow<'b, Allocation>,
-        kind: Option<MemoryKind<Self::MemoryKind>>,
+        kind: Option<MemoryKind>,
     ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>> {
         let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
         if ecx.machine.tracked_alloc_ids.contains(&id) {
@@ -1280,6 +1280,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra),
         size: Size,
         align: Align,
+        _kind: MemoryKind,
     ) -> InterpResult<'tcx> {
         if machine.tracked_alloc_ids.contains(&alloc_id) {
             machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id));
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index 0157c4845c5..0409e31d65a 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -137,7 +137,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_os_str_as_c_str(
         &mut self,
         os_str: &OsStr,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
         let this = self.eval_context_mut();
@@ -153,7 +153,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_os_str_as_wide_str(
         &mut self,
         os_str: &OsStr,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
         let this = self.eval_context_mut();
@@ -230,7 +230,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_path_as_c_str(
         &mut self,
         path: &Path,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let this = self.eval_context_mut();
         let os_str =
@@ -243,7 +243,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_path_as_wide_str(
         &mut self,
         path: &Path,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let this = self.eval_context_mut();
         let os_str =
diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr
index 867907e98e6..c26c7f397b0 100644
--- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr
@@ -6,7 +6,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
-help: <TAG> was created by a Unique retag at offsets [0x0..0x4]
+help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL |     let ptr = Box::into_raw(Box::new(0i32));
diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr
index 56715938e97..ae54da70fe2 100644
--- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr
@@ -6,7 +6,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
-help: <TAG> was created by a Unique retag at offsets [0x0..0x4]
+help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL |     let ptr = Box::into_raw(Box::new(0i32));
diff --git a/src/tools/miri/tests/pass/issues/issue-miri-3473.rs b/src/tools/miri/tests/pass/issues/issue-miri-3473.rs
new file mode 100644
index 00000000000..77b960c1cdc
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-miri-3473.rs
@@ -0,0 +1,28 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+use std::cell::UnsafeCell;
+
+#[repr(C)]
+#[derive(Default)]
+struct Node {
+    _meta: UnsafeCell<usize>,
+    value: usize,
+}
+
+impl Node {
+    fn value(&self) -> &usize {
+        &self.value
+    }
+}
+
+/// This used to cause Stacked Borrows errors because of trouble around conversion
+/// from Box to raw pointer.
+fn main() {
+    unsafe {
+        let a = Box::into_raw(Box::new(Node::default()));
+        let ptr = &*a;
+        *UnsafeCell::raw_get(a.cast::<UnsafeCell<usize>>()) = 2;
+        assert_eq!(*ptr.value(), 0);
+        drop(Box::from_raw(a));
+    }
+}
diff --git a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
index 734411ccc72..43ba490d5bb 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
@@ -20,6 +20,7 @@ fn main() {
     wide_raw_ptr_in_tuple();
     not_unpin_not_protected();
     write_does_not_invalidate_all_aliases();
+    box_into_raw_allows_interior_mutable_alias();
 }
 
 // Make sure that reading from an `&mut` does, like reborrowing to `&`,
@@ -263,3 +264,14 @@ fn write_does_not_invalidate_all_aliases() {
     other::lib2();
     assert_eq!(*x, 1337); // oops, the value changed! I guess not all pointers were invalidated
 }
+
+fn box_into_raw_allows_interior_mutable_alias() { unsafe {
+    let b = Box::new(std::cell::Cell::new(42));
+    let raw = Box::into_raw(b);
+    let c = &*raw;
+    let d = raw.cast::<i32>(); // bypassing `Cell` -- only okay in Miri tests
+    // `c` and `d` should permit arbitrary aliasing with each other now.
+    *d = 1;
+    c.set(2);
+    drop(Box::from_raw(raw));
+} }
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index d8bb8c643d1..3ea35c7940c 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -6,3 +6,4 @@ edition = "2021"
 [dependencies]
 object = "0.34.0"
 wasmparser = "0.118.2"
+regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 47b46a0a699..9a4fdff5d15 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
 use std::process::{Command, Output};
 
 pub use object;
+pub use regex;
 pub use wasmparser;
 
 pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index ebda151b908..9bf41c6e2e9 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -128,9 +128,8 @@ impl Rustc {
         self
     }
 
-    /// Specify target triple.
+    /// Specify the target triple, or a path to a custom target json spec file.
     pub fn target(&mut self, target: &str) -> &mut Self {
-        assert!(!target.contains(char::is_whitespace), "target triple cannot contain spaces");
         self.cmd.arg(format!("--target={target}"));
         self
     }
@@ -149,6 +148,12 @@ impl Rustc {
         self
     }
 
+    /// Add an extra argument to the linker invocation, via `-Clink-arg`.
+    pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
+        self.cmd.arg(format!("-Clink-arg={link_arg}"));
+        self
+    }
+
     #[track_caller]
     pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
         let caller_location = std::panic::Location::caller();
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 8d77d2b3254..6b24b1aec5d 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -1091,7 +1091,7 @@ fn next_space(tok: &TokenKind) -> SpaceState {
         | TokenKind::DotDotEq
         | TokenKind::Question => SpaceState::Punctuation,
 
-        TokenKind::ModSep
+        TokenKind::PathSep
         | TokenKind::Pound
         | TokenKind::Dollar
         | TokenKind::OpenDelim(_)
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 10a87f6e698..fe2d28ae1b9 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -843,7 +843,11 @@ impl Rewrite for ast::Ty {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Expression)
             }
             ast::TyKind::ImplicitSelf => Some(String::from("")),
-            ast::TyKind::ImplTrait(_, ref it) => {
+            ast::TyKind::ImplTrait(_, ref it, ref captures) => {
+                // FIXME(precise_capturing): Implement formatting.
+                if captures.is_some() {
+                    return None;
+                }
                 // Empty trait is not a parser error.
                 if it.is_empty() {
                     return Some("impl".to_owned());
@@ -1106,7 +1110,8 @@ fn join_bounds_inner(
 
 pub(crate) fn opaque_ty(ty: &Option<ptr::P<ast::Ty>>) -> Option<&ast::GenericBounds> {
     ty.as_ref().and_then(|t| match &t.kind {
-        ast::TyKind::ImplTrait(_, bounds) => Some(bounds),
+        // FIXME(precise_capturing): Implement support here
+        ast::TyKind::ImplTrait(_, bounds, _) => Some(bounds),
         _ => None,
     })
 }
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 3914feb3499..f0ed0ae806f 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -249,8 +249,6 @@ run-make/rlib-format-packed-bundled-libs-2/Makefile
 run-make/rlib-format-packed-bundled-libs-3/Makefile
 run-make/rlib-format-packed-bundled-libs/Makefile
 run-make/rmeta-preferred/Makefile
-run-make/rust-lld-custom-target/Makefile
-run-make/rust-lld/Makefile
 run-make/rustc-macro-dep-files/Makefile
 run-make/rustdoc-determinism/Makefile
 run-make/rustdoc-error-lines/Makefile