about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-02-26 17:17:25 +0000
committerbors <bors@rust-lang.org>2023-02-26 17:17:25 +0000
commit56ac6bfc87cce22feffc079c0540c8774b00a5ca (patch)
treee430c91fb4e29070945f79df7a47639e5cf4f9b1 /src
parentffd12f67cfa28891bbd1fa81d5e80a128f346ace (diff)
parentcb45103358c0fef99d7659e0949b3c65b3eabdd6 (diff)
downloadrust-56ac6bfc87cce22feffc079c0540c8774b00a5ca.tar.gz
rust-56ac6bfc87cce22feffc079c0540c8774b00a5ca.zip
Auto merge of #2803 - RalfJung:rustup, r=RalfJung
Rustup
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/builder.rs9
-rw-r--r--src/bootstrap/compile.rs66
-rw-r--r--src/bootstrap/config.rs3
-rw-r--r--src/bootstrap/download.rs19
-rw-r--r--src/bootstrap/flags.rs13
-rw-r--r--src/bootstrap/format.rs4
-rw-r--r--src/bootstrap/lib.rs11
-rw-r--r--src/bootstrap/native.rs2
-rw-r--r--src/bootstrap/setup.rs120
-rw-r--r--src/bootstrap/tool.rs6
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py82
-rw-r--r--src/doc/index.md228
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md94
-rw-r--r--src/librustdoc/Cargo.toml1
-rw-r--r--src/librustdoc/clean/cfg/tests.rs5
-rw-r--r--src/librustdoc/clean/mod.rs34
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs3
-rw-r--r--src/librustdoc/clean/utils.rs6
-rw-r--r--src/librustdoc/core.rs7
-rw-r--r--src/librustdoc/doctest.rs13
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/markdown.rs5
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs6
-rw-r--r--src/librustdoc/visit_ast.rs20
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/vec_box.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs2
-rw-r--r--src/tools/clippy/src/driver.rs5
-rw-r--r--src/tools/clippy/tests/ui/missing_doc_impl.stderr4
-rw-r--r--src/tools/compiletest/Cargo.toml4
-rw-r--r--src/tools/compiletest/src/errors.rs8
-rw-r--r--src/tools/compiletest/src/main.rs3
-rw-r--r--src/tools/compiletest/src/runtest.rs71
-rw-r--r--src/tools/error_index_generator/Cargo.toml1
-rw-r--r--src/tools/error_index_generator/main.rs58
-rw-r--r--src/tools/jsondoclint/src/validator.rs28
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/eval.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs2
-rw-r--r--src/tools/rustfmt/src/chains.rs4
-rw-r--r--src/tools/rustfmt/src/closures.rs3
-rw-r--r--src/tools/rustfmt/src/lib.rs1
-rw-r--r--src/tools/rustfmt/src/modules.rs13
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs3
-rw-r--r--src/tools/rustfmt/src/parse/session.rs6
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--src/tools/tidy/src/error_codes.rs26
79 files changed, 719 insertions, 427 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 952c70cec1c..b33fc02f49c 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -792,7 +792,7 @@ impl<'a> Builder<'a> {
                 run::CollectLicenseMetadata,
                 run::GenerateCopyright,
             ),
-            Kind::Setup => describe!(setup::Profile),
+            Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
             Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
             // special-cased in Build::build()
             Kind::Format => vec![],
@@ -1915,6 +1915,13 @@ impl<'a> Builder<'a> {
             }
         }
 
+        if matches!(mode, Mode::Std) {
+            if let Some(mir_opt_level) = self.config.rust_validate_mir_opts {
+                rustflags.arg("-Zvalidate-mir");
+                rustflags.arg(&format!("-Zmir-opt-level={}", mir_opt_level));
+            }
+        }
+
         Cargo { command: cargo, rustflags, rustdocflags, allow_features }
     }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index f0fcdf0d5a0..348d22a9ce6 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -459,72 +459,6 @@ impl Step for StdLink {
         let libdir = builder.sysroot_libdir(target_compiler, target);
         let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
         add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
-
-        if compiler.stage == 0 {
-            // special handling for stage0, to make `rustup toolchain link` and `x dist --stage 0`
-            // work for stage0-sysroot
-            let sysroot = builder.out.join(&compiler.host.triple).join("stage0-sysroot");
-
-            let host_lib_dir = builder.initial_rustc.ancestors().nth(2).unwrap().join("lib");
-            let host_bin_dir = builder.out.join(&builder.initial_rustc.parent().unwrap());
-            let host_codegen_backends =
-                host_lib_dir.join("rustlib").join(&compiler.host.triple).join("codegen-backends");
-            let sysroot_bin_dir = sysroot.join("bin");
-            let sysroot_lib_dir = sysroot.join("lib");
-            let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
-
-            // Create the `bin` directory in stage0-sysroot
-            t!(fs::create_dir_all(&sysroot_bin_dir));
-
-            // copy bin files from `builder.initial_rustc/./` to `stage0-sysroot/bin`
-            if let Ok(files) = fs::read_dir(&host_bin_dir) {
-                for file in files {
-                    let file = t!(file);
-                    if file.file_name() == "rustfmt" {
-                        // This is when `rustc` and `cargo` are set in `config.toml`
-                        if !file.path().starts_with(&builder.out) {
-                            builder.copy(
-                                &file.path().into_boxed_path(),
-                                &sysroot_bin_dir.join(file.file_name()),
-                            );
-                        } else {
-                            builder.copy(
-                                &builder
-                                    .out
-                                    .join(&compiler.host.triple)
-                                    .join("rustfmt/bin/rustfmt"),
-                                &sysroot_bin_dir.join(file.file_name()),
-                            );
-                        }
-                    } else {
-                        builder.copy(
-                            &file.path().into_boxed_path(),
-                            &sysroot_bin_dir.join(file.file_name()),
-                        );
-                    }
-                }
-            }
-
-            // copy dylib files from `builder.initial_rustc/../lib/*` while excluding the `rustlib` directory to `stage0-sysroot/lib`
-            if let Ok(files) = fs::read_dir(&host_lib_dir) {
-                for file in files {
-                    let file = t!(file);
-                    let path = file.path();
-                    if path.is_file()
-                        && is_dylib(&file.file_name().into_string().unwrap())
-                        && !path.starts_with(sysroot_lib_dir.join("rustlib").into_boxed_path())
-                    {
-                        builder.copy(&path, &sysroot_lib_dir.join(path.file_name().unwrap()));
-                    }
-                }
-            }
-
-            t!(fs::create_dir_all(&sysroot_codegen_backends));
-            // copy `codegen-backends` from `host_lib_dir/rustlib/codegen_backends` to `stage0-sysroot/lib/rustlib/host-triple/codegen-backends` if it exists.
-            if host_codegen_backends.exists() {
-                builder.cp_r(&host_codegen_backends, &sysroot_codegen_backends);
-            }
-        }
     }
 }
 
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 56f96734bbb..4a563bc396d 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -173,6 +173,7 @@ pub struct Config {
     pub rust_profile_use: Option<String>,
     pub rust_profile_generate: Option<String>,
     pub rust_lto: RustcLto,
+    pub rust_validate_mir_opts: Option<u32>,
     pub llvm_profile_use: Option<String>,
     pub llvm_profile_generate: bool,
     pub llvm_libunwind_default: Option<LlvmLibunwind>,
@@ -770,6 +771,7 @@ define_config! {
         // ignored; this is set from an env var set by bootstrap.py
         download_rustc: Option<StringOrBool> = "download-rustc",
         lto: Option<String> = "lto",
+        validate_mir_opts: Option<u32> = "validate-mir-opts",
     }
 }
 
@@ -1149,6 +1151,7 @@ impl Config {
                 .as_deref()
                 .map(|value| RustcLto::from_str(value).unwrap())
                 .unwrap_or_default();
+            config.rust_validate_mir_opts = rust.validate_mir_opts;
         } else {
             config.rust_profile_use = flags.rust_profile_use;
             config.rust_profile_generate = flags.rust_profile_generate;
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index d6592d2d771..d1e2149d3f9 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -2,7 +2,7 @@ use std::{
     env,
     ffi::{OsStr, OsString},
     fs::{self, File},
-    io::{self, BufRead, BufReader, ErrorKind},
+    io::{BufRead, BufReader, ErrorKind},
     path::{Path, PathBuf},
     process::{Command, Stdio},
 };
@@ -26,14 +26,6 @@ impl Config {
         self.verbose > 0
     }
 
-    pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(&self, src: P, link: Q) -> io::Result<()> {
-        #[cfg(unix)]
-        use std::os::unix::fs::symlink as symlink_file;
-        #[cfg(windows)]
-        use std::os::windows::fs::symlink_file;
-        if !self.dry_run() { symlink_file(src.as_ref(), link.as_ref()) } else { Ok(()) }
-    }
-
     pub(crate) fn create(&self, path: &Path, s: &str) {
         if self.dry_run() {
             return;
@@ -338,15 +330,6 @@ impl Config {
         let bin_root = self.out.join(host.triple).join("rustfmt");
         let rustfmt_path = bin_root.join("bin").join(exe("rustfmt", host));
         let rustfmt_stamp = bin_root.join(".rustfmt-stamp");
-
-        #[cfg(not(windows))]
-        {
-            let legacy_rustfmt = self.initial_rustc.with_file_name(exe("rustfmt", host));
-            if !legacy_rustfmt.exists() {
-                t!(self.symlink_file(&rustfmt_path, &legacy_rustfmt));
-            }
-        }
-
         if rustfmt_path.exists() && !program_out_of_date(&rustfmt_stamp, &channel) {
             return Some(rustfmt_path);
         }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index f07e710a9e6..9d1504c34e8 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -554,7 +554,8 @@ Arguments:
             Kind::Setup => {
                 subcommand_help.push_str(&format!(
                     "\n
-x.py setup creates a `config.toml` which changes the defaults for x.py itself.
+x.py setup creates a `config.toml` which changes the defaults for x.py itself,
+as well as setting up a git pre-push hook, VS code config and toolchain link.
 
 Arguments:
     This subcommand accepts a 'profile' to use for builds. For example:
@@ -564,7 +565,13 @@ Arguments:
     The profile is optional and you will be prompted interactively if it is not given.
     The following profiles are available:
 
-{}",
+{}
+
+    To only set up the git hook, VS code or toolchain link, you may use
+        ./x.py setup hook
+        ./x.py setup vscode
+        ./x.py setup link
+",
                     Profile::all_for_help("        ").trim_end()
                 ));
             }
@@ -638,7 +645,7 @@ Arguments:
             }
             Kind::Setup => {
                 let profile = if paths.len() > 1 {
-                    eprintln!("\nerror: At most one profile can be passed to setup\n");
+                    eprintln!("\nerror: At most one option can be passed to setup\n");
                     usage(1, &opts, verbose, &subcommand_help)
                 } else if let Some(path) = paths.pop() {
                     let profile_string = t!(path.into_os_string().into_string().map_err(
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index 615794958d0..ae72a42973c 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -218,7 +218,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
                     WalkBuilder::new(first)
                 }
             } else {
-                WalkBuilder::new(first)
+                WalkBuilder::new(src.join(first))
             };
 
             for path in &paths[1..] {
@@ -229,7 +229,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
                         walker.add(path);
                     }
                 } else {
-                    walker.add(path);
+                    walker.add(src.join(path));
                 }
             }
 
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index f753720b353..f4abdf1cc57 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -20,6 +20,7 @@ use std::cell::{Cell, RefCell};
 use std::collections::{HashMap, HashSet};
 use std::env;
 use std::fs::{self, File};
+use std::io;
 use std::io::ErrorKind;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
@@ -1406,7 +1407,7 @@ impl Build {
                 src = t!(fs::canonicalize(src));
             } else {
                 let link = t!(fs::read_link(src));
-                t!(self.config.symlink_file(link, dst));
+                t!(self.symlink_file(link, dst));
                 return;
             }
         }
@@ -1524,6 +1525,14 @@ impl Build {
         iter.map(|e| t!(e)).collect::<Vec<_>>().into_iter()
     }
 
+    fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(&self, src: P, link: Q) -> io::Result<()> {
+        #[cfg(unix)]
+        use std::os::unix::fs::symlink as symlink_file;
+        #[cfg(windows)]
+        use std::os::windows::fs::symlink_file;
+        if !self.config.dry_run() { symlink_file(src.as_ref(), link.as_ref()) } else { Ok(()) }
+    }
+
     /// Returns if config.ninja is enabled, and checks for ninja existence,
     /// exiting with a nicer error message if not.
     fn ninja(&self) -> bool {
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index d6e63fb937e..21157b02a78 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -516,7 +516,7 @@ impl Step for Llvm {
 
             let lib_llvm = out_dir.join("build").join("lib").join(lib_name);
             if !lib_llvm.exists() {
-                t!(builder.build.config.symlink_file("libLLVM.dylib", &lib_llvm));
+                t!(builder.symlink_file("libLLVM.dylib", &lib_llvm));
             }
         }
 
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index a027139df23..4480bce99d7 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -21,6 +21,7 @@ pub enum Profile {
     Library,
     Tools,
     User,
+    None,
 }
 
 /// A list of historical hashes of `src/etc/vscode_settings.json`.
@@ -41,7 +42,7 @@ impl Profile {
     pub fn all() -> impl Iterator<Item = Self> {
         use Profile::*;
         // N.B. these are ordered by how they are displayed, not alphabetically
-        [Library, Compiler, Codegen, Tools, User].iter().copied()
+        [Library, Compiler, Codegen, Tools, User, None].iter().copied()
     }
 
     pub fn purpose(&self) -> String {
@@ -52,6 +53,7 @@ impl Profile {
             Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
             Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
             User => "Install Rust from source",
+            None => "Do not modify `config.toml`"
         }
         .to_string()
     }
@@ -71,6 +73,7 @@ impl Profile {
             Profile::Library => "library",
             Profile::Tools => "tools",
             Profile::User => "user",
+            Profile::None => "none",
         }
     }
 }
@@ -87,6 +90,7 @@ impl FromStr for Profile {
             "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
                 Ok(Profile::Tools)
             }
+            "none" => Ok(Profile::None),
             _ => Err(format!("unknown profile: '{}'", s)),
         }
     }
@@ -144,17 +148,8 @@ impl Step for Profile {
 }
 
 pub fn setup(config: &Config, profile: Profile) {
-    let stage_path =
-        ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
-
-    if !rustup_installed() && profile != Profile::User {
-        eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
-    } else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
-        attempt_toolchain_link(&stage_path[..]);
-    }
-
-    let suggestions = match profile {
-        Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
+    let suggestions: &[&str] = match profile {
+        Profile::Codegen | Profile::Compiler | Profile::None => &["check", "build", "test"],
         Profile::Tools => &[
             "check",
             "build",
@@ -167,11 +162,6 @@ pub fn setup(config: &Config, profile: Profile) {
         Profile::User => &["dist", "build"],
     };
 
-    if !config.dry_run() {
-        t!(install_git_hook_maybe(&config));
-        t!(create_vscode_settings_maybe(&config));
-    }
-
     println!();
 
     println!("To get started, try one of the following commands:");
@@ -190,6 +180,9 @@ pub fn setup(config: &Config, profile: Profile) {
 }
 
 fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
+    if profile == Profile::None {
+        return;
+    }
     if path.exists() {
         eprintln!();
         eprintln!(
@@ -217,6 +210,41 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
     println!("`x.py` will now use the configuration at {}", include_path.display());
 }
 
+/// Creates a toolchain link for stage1 using `rustup`
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub struct Link;
+impl Step for Link {
+    type Output = ();
+    const DEFAULT: bool = true;
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.alias("link")
+    }
+    fn make_run(run: RunConfig<'_>) {
+        if run.builder.config.dry_run() {
+            return;
+        }
+        if let [cmd] = &run.paths[..] {
+            if cmd.assert_single_path().path.as_path().as_os_str() == "link" {
+                run.builder.ensure(Link);
+            }
+        }
+    }
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let config = &builder.config;
+        if config.dry_run() {
+            return;
+        }
+        let stage_path =
+            ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
+
+        if !rustup_installed() {
+            eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
+        } else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
+            attempt_toolchain_link(&stage_path[..]);
+        }
+    }
+}
+
 fn rustup_installed() -> bool {
     Command::new("rustup")
         .arg("--version")
@@ -394,6 +422,35 @@ fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> {
     }
 }
 
+/// Installs `src/etc/pre-push.sh` as a Git hook
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub struct Hook;
+
+impl Step for Hook {
+    type Output = ();
+    const DEFAULT: bool = true;
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.alias("hook")
+    }
+    fn make_run(run: RunConfig<'_>) {
+        if run.builder.config.dry_run() {
+            return;
+        }
+        if let [cmd] = &run.paths[..] {
+            if cmd.assert_single_path().path.as_path().as_os_str() == "hook" {
+                run.builder.ensure(Hook);
+            }
+        }
+    }
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let config = &builder.config;
+        if config.dry_run() {
+            return;
+        }
+        t!(install_git_hook_maybe(&config));
+    }
+}
+
 // install a git hook to automatically run tidy, if they want
 fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
     let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
@@ -432,6 +489,35 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
     Ok(())
 }
 
+/// Sets up or displays `src/etc/vscode_settings.json`
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub struct Vscode;
+
+impl Step for Vscode {
+    type Output = ();
+    const DEFAULT: bool = true;
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.alias("vscode")
+    }
+    fn make_run(run: RunConfig<'_>) {
+        if run.builder.config.dry_run() {
+            return;
+        }
+        if let [cmd] = &run.paths[..] {
+            if cmd.assert_single_path().path.as_path().as_os_str() == "vscode" {
+                run.builder.ensure(Vscode);
+            }
+        }
+    }
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let config = &builder.config;
+        if config.dry_run() {
+            return;
+        }
+        t!(create_vscode_settings_maybe(&config));
+    }
+}
+
 /// Create a `.vscode/settings.json` file for rustc development, or just print it
 fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> {
     let (current_hash, historical_hashes) = SETTINGS_HASHES.split_last().unwrap();
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index d30532ef3c6..3c9a154da9a 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -595,7 +595,7 @@ impl Step for Rustdoc {
             features.push("jemalloc".to_string());
         }
 
-        let cargo = prepare_tool_cargo(
+        let mut cargo = prepare_tool_cargo(
             builder,
             build_compiler,
             Mode::ToolRustc,
@@ -606,6 +606,10 @@ impl Step for Rustdoc {
             features.as_slice(),
         );
 
+        if builder.config.rustc_parallel {
+            cargo.rustflag("--cfg=parallel_compiler");
+        }
+
         let msg = tooling_output(
             Mode::ToolRustc,
             "rustdoc",
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 4cc5d9f8a0d..98bd90210d6 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -23,6 +23,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 
 RUN curl -sL https://nodejs.org/dist/v16.9.0/node-v16.9.0-linux-x64.tar.xz | tar -xJ
 ENV PATH="/node-v16.9.0-linux-x64/bin:${PATH}"
+ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3"
+
 # Install es-check
 # Pin its version to prevent unrelated CI failures due to future es-check versions.
 RUN npm install es-check@6.1.1 eslint@8.6.0 -g
@@ -38,7 +40,7 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
 
 ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
-           python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu --all-targets && \
+           python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            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/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 94ec2401292..9c550b2d728 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.14.3
\ No newline at end of file
+0.14.4
\ No newline at end of file
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index a6d84a3c18a..c3d532c4b27 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -507,9 +507,8 @@ class TestEnvironment:
     bin/{exe_name}={bin_path}
     lib/{libstd_name}={rust_dir}/lib/rustlib/{rustlib_dir}/lib/{libstd_name}
     lib/{libtest_name}={rust_dir}/lib/rustlib/{rustlib_dir}/lib/{libtest_name}
-    lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/lib/libc.so
-    lib/libzircon.so={sdk_dir}/arch/{target_arch}/sysroot/lib/libzircon.so
-    lib/libfdio.so={sdk_dir}/arch/{target_arch}/lib/libfdio.so
+    lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/dist/lib/ld.so.1
+    lib/libfdio.so={sdk_dir}/arch/{target_arch}/dist/libfdio.so
     """
 
     TEST_ENV_VARS: ClassVar[List[str]] = [
@@ -844,23 +843,34 @@ class TestEnvironment:
             "--",
             "--build-id-dir",
             os.path.join(self.sdk_dir, ".build-id"),
-            "--build-id-dir",
-            os.path.join(self.libs_dir(), ".build-id"),
         ]
 
-        # Add rust source if it's available
-        if args.rust_src is not None:
+        libs_build_id_path = os.path.join(self.libs_dir(), ".build-id")
+        if os.path.exists(libs_build_id_path):
+            # Add .build-id symbols if installed libs have been stripped into a
+            # .build-id directory
             command += [
-                "--build-dir",
-                args.rust_src,
+                "--build-id-dir",
+                libs_build_id_path,
+            ]
+        else:
+            # If no .build-id directory is detected, then assume that the shared
+            # libs contain their debug symbols
+            command += [
+                f"--symbol-path={self.rust_dir}/lib/rustlib/{self.target}/lib",
             ]
 
+        # Add rust source if it's available
+        rust_src_map = None
+        if args.rust_src is not None:
+            # This matches the remapped prefix used by compiletest. There's no
+            # clear way that we can determine this, so it's hard coded.
+            rust_src_map = f"/rustc/FAKE_PREFIX={args.rust_src}"
+
         # Add fuchsia source if it's available
+        fuchsia_src_map = None
         if args.fuchsia_src is not None:
-            command += [
-                "--build-dir",
-                os.path.join(args.fuchsia_src, "out", "default"),
-            ]
+            fuchsia_src_map = f"./../..={args.fuchsia_src}"
 
         # Load debug symbols for the test binary and automatically attach
         if args.test is not None:
@@ -883,7 +893,28 @@ class TestEnvironment:
                 test_name,
             )
 
+            # The fake-test-src-base directory maps to the suite directory
+            # e.g. tests/ui/foo.rs has a path of rust/fake-test-src-base/foo.rs
+            fake_test_src_base = os.path.join(
+                args.rust_src,
+                "fake-test-src-base",
+            )
+            real_test_src_base = os.path.join(
+                args.rust_src,
+                "tests",
+                args.test.split(os.path.sep)[0],
+            )
+            test_src_map = f"{fake_test_src_base}={real_test_src_base}"
+
             with open(self.zxdb_script_path(), mode="w", encoding="utf-8") as f:
+                print(f"set source-map += {test_src_map}", file=f)
+
+                if rust_src_map is not None:
+                    print(f"set source-map += {rust_src_map}", file=f)
+
+                if fuchsia_src_map is not None:
+                    print(f"set source-map += {fuchsia_src_map}", file=f)
+
                 print(f"attach {test_name[:31]}", file=f)
 
             command += [
@@ -900,6 +931,20 @@ class TestEnvironment:
         # Connect to the running emulator with zxdb
         subprocess.run(command, env=self.ffx_cmd_env(), check=False)
 
+    def syslog(self, args):
+        subprocess.run(
+            [
+                self.tool_path("ffx"),
+                "--config",
+                self.ffx_user_config_path(),
+                "log",
+                "--since",
+                "now",
+            ],
+            env=self.ffx_cmd_env(),
+            check=False,
+        )
+
 
 def start(args):
     test_env = TestEnvironment.from_args(args)
@@ -933,6 +978,12 @@ def debug(args):
     return 0
 
 
+def syslog(args):
+    test_env = TestEnvironment.read_from_file()
+    test_env.syslog(args)
+    return 0
+
+
 def main():
     parser = argparse.ArgumentParser()
 
@@ -1028,6 +1079,11 @@ def main():
     )
     debug_parser.set_defaults(func=debug)
 
+    syslog_parser = subparsers.add_parser(
+        "syslog", help="prints the device syslog"
+    )
+    syslog_parser.set_defaults(func=syslog)
+
     args = parser.parse_args()
     return args.func(args)
 
diff --git a/src/doc/index.md b/src/doc/index.md
index bf08960f338..7c97c16c20b 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -4,6 +4,20 @@
 nav {
     display: none;
 }
+body {
+    font-family: serif;
+}
+h1, h2, h3, h4, h5, h6 {
+    font-family: sans-serif;
+}
+h3 {
+    font-size: 1.35rem;
+}
+h4 {
+    font-size: 1.1rem;
+}
+
+/* Formatting for docs search bar */
 #search-input {
     width: calc(100% - 58px);
 }
@@ -21,53 +35,74 @@ nav {
 #search-but:hover, #search-input:focus {
     border-color: #55a9ff;
 }
-h2 {
-    font-size: 18px;
+
+/* Formatting for external link icon */
+svg.external-link {
+  display: inline-block;
+  position: relative;
+  vertical-align: super;
+  width: 0.7rem;
+  height: 0.7rem;
+  padding-left: 2px;
+  top: 3px;
 }
 </style>
 
-Welcome to an overview of the documentation provided by the [Rust project].
-All of these projects are managed by the Docs Team; there are other
-unofficial documentation resources as well!
+Welcome to an overview of the documentation provided by the [Rust
+project]. This page contains links to various helpful references,
+most of which are available offline (if opened with `rustup doc`). Many of these
+resources take the form of "books"; we collectively call these "The Rust
+Bookshelf." Some are large, some are small.
 
-Many of these resources take the form of "books"; we collectively call these
-"The Rust Bookshelf." Some are large, some are small.
+All of these books are managed by the Rust Organization, but other unofficial
+documentation resources are included here as well!
 
-# Learn Rust
+If you're just looking for the standard library reference, here it is:
+[Rust API documentation](std/index.html)
 
-If you'd like to learn Rust, this is the spot for you! All of these resources
+
+## Learning Rust
+
+If you'd like to learn Rust, this is the section for you! All of these resources
 assume that you have programmed before, but not in any specific language:
 
-## The Rust Programming Language
+### The Rust Programming Language
 
-Affectionately nicknamed "the book," [The Rust Programming
-Language](book/index.html) will give you an overview of the language from
-first principles. You'll build a few projects along the way, and by the end,
-you'll have a solid grasp of the language.
+Affectionately nicknamed "the book," [The Rust Programming Language](book/index.html)
+will give you an overview of the language from first principles. You'll build a
+few projects along the way, and by the end, you'll have a solid grasp of how to
+use the language.
 
-## Rust By Example
+### Rust By Example
 
 If reading multiple hundreds of pages about a language isn't your style, then
-[Rust By Example](rust-by-example/index.html) has you covered. While the book talks about code with
-a lot of words, RBE shows off a bunch of code, and keeps the talking to a
-minimum. It also includes exercises!
+[Rust By Example](rust-by-example/index.html) has you covered. RBE shows off a
+bunch of code without using a lot of words. It also includes exercises!
+
+### Rustlings
+
+[Rustlings](https://github.com/rust-lang/rustlings) guides you
+through downloading and setting up the Rust toolchain, then provides an
+interactive tool that teaches you how to solve coding challenges in Rust.
+
+### Rust Playground
 
-## Rustlings
+The [Rust Playground](https://play.rust-lang.org) is a great place
+to try out and share small bits of code, or experiment with some of the most
+popular crates.
 
-[Rustlings](https://github.com/rust-lang/rustlings) guides you through downloading and setting up the Rust toolchain,
-and teaches you the basics of reading and writing Rust syntax. It's an
-alternative to Rust by Example that works with your own environment.
 
-# Use Rust
+## Using Rust
 
-Once you've gotten familiar with the language, these resources can help you
-when you're actually using it day-to-day.
+Once you've gotten familiar with the language, these resources can help you put
+it to work.
 
-## The Standard Library
+### The Standard Library
 
-Rust's standard library has [extensive API documentation](std/index.html),
-with explanations of how to use various things, as well as example code for
-accomplishing various tasks.
+Rust's standard library has [extensive API documentation](std/index.html), with
+explanations of how to use various things, as well as example code for
+accomplishing various tasks. Code examples have a "Run" button on hover that
+opens the sample in the playground.
 
 <div>
   <form action="std/index.html" method="get">
@@ -77,76 +112,143 @@ accomplishing various tasks.
   </form>
 </div>
 
-## The Edition Guide
+### Your Personal Documentation
 
-[The Edition Guide](edition-guide/index.html) describes the Rust editions.
+Whenever you are working in a crate, `cargo doc --open` will generate
+documentation for your project _and_ all its dependencies in their correct
+version, and open it in your browser. Add the flag `--document-private-items` to
+also show items not marked `pub`.
 
-## The Rustc Book
+### The Edition Guide
 
-[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.
+[The Edition Guide](edition-guide/index.html) describes the Rust editions and
+their differences.
 
-## The Cargo Book
+### The `rustc` Book
 
-[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager.
+[The `rustc` Book](rustc/index.html) describes the Rust compiler, `rustc`.
 
-## The Rustdoc Book
+### The Cargo Book
+
+[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and
+dependency manager.
+
+### The Rustdoc Book
 
 [The Rustdoc Book](rustdoc/index.html) describes our documentation tool, `rustdoc`.
 
-## The Clippy Book
+### The Clippy Book
 
 [The Clippy Book](clippy/index.html) describes our static analyzer, Clippy.
 
-## Extended Error Listing
+### Extended Error Listing
 
 Many of Rust's errors come with error codes, and you can request extended
-diagnostics from the compiler on those errors. You can also [read them
-here](error_codes/index.html), if you prefer to read them that way.
+diagnostics from the compiler on those errors (with `rustc --explain`). You can
+also read them here if you prefer: [rustc error codes](error_codes/index.html)
+
 
-# Master Rust
+## Mastering Rust
 
 Once you're quite familiar with the language, you may find these advanced
 resources useful.
 
-## The Reference
+### The Reference
 
-[The Reference](reference/index.html) is not a formal spec, but is more detailed and
-comprehensive than the book.
+[The Reference](reference/index.html) is not a formal spec, but is more detailed
+and comprehensive than the book.
 
-## The Style Guide
+### The Style Guide
 
-[The Rust Style Guide](style-guide/index.html) describes the standard formatting of Rust
-code. Most developers use rustfmt to format their code, and rustfmt's default
-formatting matches this style guide.
+[The Rust Style Guide](style-guide/index.html) describes the standard formatting
+of Rust code. Most developers use `cargo fmt` to invoke `rustfmt` and format the
+code automatically (the result matches this style guide).
 
-## The Rustonomicon
+### The Rustonomicon
 
-[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of unsafe
-Rust. It's also sometimes called "the 'nomicon."
+[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of
+unsafe Rust. It's also sometimes called "the 'nomicon."
 
-## The Unstable Book
+### The Unstable Book
 
-[The Unstable Book](unstable-book/index.html) has documentation for unstable features.
+[The Unstable Book](unstable-book/index.html) has documentation for unstable
+features.
 
-## The `rustc` Contribution Guide
+### The `rustc` Contribution Guide
 
-[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/) documents how
-the compiler works and how to contribute to it. This is useful if you want to build
-or modify the Rust compiler from source (e.g. to target something non-standard).
+[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/)
+documents how the compiler works and how to contribute to it. This is useful if
+you want to build or modify the Rust compiler from source (e.g. to target
+something non-standard).
 
-# Specialize Rust
 
-When using Rust in specific domain areas, consider using the following resources tailored to each domain.
+## Specialized Rust
 
-## Embedded Systems
+When using Rust in specific domains, consider using the following resources
+tailored to each area.
 
-When developing for Bare Metal or Embedded Linux systems, you may find these resources maintained by the [Embedded Working Group] useful.
+### Embedded Systems
+
+When developing for Bare Metal or Embedded Linux systems, you may find these
+resources maintained by the [Embedded Working Group] useful.
 
 [Embedded Working Group]: https://github.com/rust-embedded
 
-### The Embedded Rust Book
+#### The Embedded Rust Book
 
-[The Embedded Rust Book] is targeted at developers familiar with embedded development and familiar with Rust, but have not used Rust for embedded development.
+[The Embedded Rust Book] is targeted at developers familiar with embedded
+development and familiar with Rust, but have not used Rust for embedded
+development.
 
 [The Embedded Rust Book]: embedded-book/index.html
 [Rust project]: https://www.rust-lang.org
+
+<script>
+// check if a given link is external
+function isExternalLink(url) {
+  const tmp = document.createElement('a');
+  tmp.href = url;
+  return tmp.host !== window.location.host;
+}
+
+// Add the `external` class to all <a> tags with external links and append the external link SVG
+function updateExternalAnchors() {
+  /*
+    External link SVG from Font-Awesome
+    CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0
+    via Wikimedia Commons
+  */
+  const svgText = `<svg
+     class='external-link'
+     xmlns='http://www.w3.org/2000/svg'
+     viewBox='0 -256 1850 1850'
+     width='100%'
+     height='100%'>
+       <g transform='matrix(1,0,0,-1,30,1427)'>
+         <path d='M 1408,608 V 288 Q 1408,169 1323.5,84.5 1239,0 1120,
+           0 H 288 Q 169,0 84.5,84.5 0,169 0,288 v 832 Q 0,1239 84.5,1323.5 169,
+           1408 288,1408 h 704 q 14,0 23,-9 9,-9 9,-23 v -64 q 0,-14 -9,-23 -9,
+           -9 -23,-9 H 288 q -66,0 -113,-47 -47,-47 -47,-113 V 288 q 0,-66 47,
+           -113 47,-47 113,-47 h 832 q 66,0 113,47 47,47 47,113 v 320 q 0,14 9,
+           23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 384,864 V 960 q 0,
+           -26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 L 1507,1091 855,439 q -10,
+           -10 -23,-10 -13,0 -23,10 L 695,553 q -10,10 -10,23 0,13 10,23 l 652,
+           652 -176,176 q -19,19 -19,45 0,26 19,45 19,19 45,19 h 512 q 26,0 45,
+           -19 19,-19 19,-45 z' style='fill:currentColor' />
+         </g>
+     </svg>`;
+  let allAnchors = document.getElementsByTagName("a");
+
+  for (var i = 0; i < allAnchors.length; ++i) {
+    let anchor = allAnchors[i];
+    if (isExternalLink(anchor.href)) {
+      anchor.classList.add("external");
+      anchor.innerHTML += svgText;
+    }
+  }
+}
+
+// on page load, update external anchors
+document.addEventListener("DOMContentLoaded", updateExternalAnchors);
+
+</script>
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 0f165b268ba..63dde2aaedd 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -687,7 +687,9 @@ Rust compiler locally. See "[Targeting Fuchsia with a compiler built from source
 for the steps to build locally.
 
 You'll also need to download a copy of the Fuchsia SDK. The current minimum
-supported SDK version is [9.20220726.1.1](https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:9.20220726.1.1).
+supported SDK version is [10.20221207.2.89][minimum_supported_sdk_version].
+
+[minimum_supported_sdk_version]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:10.20221207.2.89
 
 Fuchsia's test runner interacts with the Fuchsia emulator and is located at
 `src/ci/docker/scripts/fuchsia-test-runner.py`. We can use it to start our
@@ -697,7 +699,7 @@ test environment with:
 src/ci/docker/scripts/fuchsia-test-runner.py start
     --rust ${RUST_SRC_PATH}/install
     --sdk ${SDK_PATH}
-    --target-triple {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia}
+    --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia}
 ```
 
 Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and
@@ -717,17 +719,11 @@ run the full `tests/ui` test suite:
     --target x86_64-unknown-fuchsia                                           \
     --run=always --jobs 1                                                     \
     --test-args --target-rustcflags                                           \
-    --test-args -L                                                            \
-    --test-args --target-rustcflags                                           \
-    --test-args ${SDK_PATH}/arch/{x64|arm64}/sysroot/lib                      \
-    --test-args --target-rustcflags                                           \
-    --test-args -L                                                            \
+    --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib             \
     --test-args --target-rustcflags                                           \
-    --test-args ${SDK_PATH}/arch/{x64|arm64}/lib                              \
+    --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/lib                     \
     --test-args --target-rustcflags                                           \
-    --test-args -Cpanic=abort                                                 \
-    --test-args --target-rustcflags                                           \
-    --test-args -Zpanic_abort_tests                                           \
+    --test-args -Clink-arg=--undefined-version                                \
     --test-args --remote-test-client                                          \
     --test-args src/ci/docker/scripts/fuchsia-test-runner.py                  \
 )
@@ -736,7 +732,18 @@ run the full `tests/ui` test suite:
 *Note: The test suite cannot be run in parallel at the moment, so `x.py`
 must be run with `--jobs 1` to ensure only one test runs at a time.*
 
-When finished, the test runner can be used to stop the test environment:
+By default, `x.py` compiles test binaries with `panic=unwind`. If you built your
+Rust toolchain with `-Cpanic=abort`, you need to tell `x.py` to compile test
+binaries with `panic=abort` as well:
+
+```sh
+    --test-args --target-rustcflags                                           \
+    --test-args -Cpanic=abort                                                 \
+    --test-args --target-rustcflags                                           \
+    --test-args -Zpanic_abort_tests                                           \
+```
+
+When finished testing, the test runner can be used to stop the test environment:
 
 ```sh
 src/ci/docker/scripts/fuchsia-test-runner.py stop
@@ -764,8 +771,9 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
 * `--symbol-path` gets required symbol paths, which are
 necessary for stepping through your program.
 
-The "[displaying source code in `zxdb`](#displaying-source-code-in-zxdb)" section describes how you can
-display Rust and/or Fuchsia source code in your debugging session.
+The "[displaying source code in `zxdb`](#displaying-source-code-in-zxdb)"
+section describes how you can display Rust and/or Fuchsia source code in your
+debugging session.
 
 ### Using `zxdb`
 
@@ -866,6 +874,64 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
  Linking to a Fuchsia checkout can help with debugging Fuchsia libraries,
  such as [fdio].
 
+### Debugging the compiler test suite
+
+Debugging the compiler test suite requires some special configuration:
+
+First, we have to properly configure zxdb so it will be able to find debug
+symbols and source information for our test. The test runner can do this for us
+with:
+
+```sh
+src/ci/docker/scripts/fuchsia-test-runner.py debug                            \
+    --rust-src ${RUST_SRC_PATH}                                               \
+    --fuchsia-src ${FUCHSIA_SRC_PATH}                                         \
+    --test ${TEST}
+```
+
+where `${TEST}` is relative to Rust's `tests` directory (e.g. `ui/abi/...`).
+
+This will start a zxdb session that is properly configured for the specific test
+being run. All three arguments are optional, so you can omit `--fuchsia-src` if
+you don't have it downloaded. Now is a good time to set any desired breakpoints,
+like `b main`.
+
+Next, we have to tell `x.py` not to optimize or strip debug symbols from our
+test suite binaries. We can do this by passing some new arguments to `rustc`
+through our `x.py` invocation. The full invocation is:
+
+```sh
+( \
+    source config-env.sh &&                                                   \
+    ./x.py                                                                    \
+    --config config.toml                                                      \
+    --stage=2                                                                 \
+    test tests/${TEST}                                                        \
+    --target x86_64-unknown-fuchsia                                           \
+    --run=always --jobs 1                                                     \
+    --test-args --target-rustcflags                                           \
+    --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib             \
+    --test-args --target-rustcflags                                           \
+    --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/lib                     \
+    --test-args --target-rustcflags                                           \
+    --test-args -Clink-arg=--undefined-version                                \
+    --test-args --target-rustcflags                                           \
+    --test-args -Cdebuginfo=2                                                 \
+    --test-args --target-rustcflags                                           \
+    --test-args -Copt-level=0                                                 \
+    --test-args --target-rustcflags                                           \
+    --test-args -Cstrip=none                                                  \
+    --test-args --remote-test-client                                          \
+    --test-args src/ci/docker/scripts/fuchsia-test-runner.py                  \
+)
+```
+
+*If you built your Rust toolchain with `panic=abort`, make sure to include the
+previous flags so your test binaries are also compiled with `panic=abort`.*
+
+Upon running this command, the test suite binary will be run and zxdb will
+attach and load any relevant debug symbols.
+
 [Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
 [Fuchsia]: https://fuchsia.dev/
 [source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 5e592227d49..c48f7998c5a 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -18,7 +18,6 @@ serde_json = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 smallvec = "1.8.1"
 tempfile = "3"
-thin-vec = "0.2.9"
 tracing = "0.1"
 tracing-tree = "0.2.0"
 
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 81f67672436..bb62660e194 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -4,6 +4,7 @@ use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
 use rustc_span::create_default_session_globals_then;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::DUMMY_SP;
+use thin_vec::thin_vec;
 
 fn word_cfg(s: &str) -> Cfg {
     Cfg::Cfg(Symbol::intern(s), None)
@@ -34,7 +35,7 @@ macro_rules! dummy_meta_item_list {
     ($name:ident, [$($list:ident),* $(,)?]) => {
         MetaItem {
             path: Path::from_ident(Ident::from_str(stringify!($name))),
-            kind: MetaItemKind::List(vec![
+            kind: MetaItemKind::List(thin_vec![
                 $(
                     NestedMetaItem::MetaItem(
                         dummy_meta_item_word(stringify!($list)),
@@ -48,7 +49,7 @@ macro_rules! dummy_meta_item_list {
     ($name:ident, [$($list:expr),* $(,)?]) => {
         MetaItem {
             path: Path::from_ident(Ident::from_str(stringify!($name))),
-            kind: MetaItemKind::List(vec![
+            kind: MetaItemKind::List(thin_vec![
                 $(
                     NestedMetaItem::MetaItem($list),
                 )*
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0c70d31ed60..0e8f0cfc518 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -22,9 +22,9 @@ use rustc_hir::PredicateOrigin;
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_bound_vars as rbv;
-use rustc_middle::ty::fold::ir::TypeFolder;
+use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
@@ -77,7 +77,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     // This covers the case where somebody does an import which should pull in an item,
     // but there's already an item with the same namespace and same name. Rust gives
     // priority to the not-imported one, so we should, too.
-    items.extend(doc.items.iter().flat_map(|(item, renamed, import_id)| {
+    items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| {
         // First, lower everything other than imports.
         if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
             return Vec::new();
@@ -90,7 +90,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
         }
         v
     }));
-    items.extend(doc.items.iter().flat_map(|(item, renamed, _)| {
+    items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
         // Now we actually lower the imports, skipping everything else.
         if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
             let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
@@ -1661,7 +1661,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
         }
         TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
         // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
-        TyKind::Infer | TyKind::Err | TyKind::Typeof(..) => Infer,
+        TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) => Infer,
     }
 }
 
@@ -2114,17 +2114,29 @@ fn get_all_import_attributes<'hir>(
     attributes: &mut Vec<ast::Attribute>,
     is_inline: bool,
 ) {
+    let mut first = true;
     let hir_map = tcx.hir();
     let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
     let mut visited = FxHashSet::default();
+
     // If the item is an import and has at least a path with two parts, we go into it.
     while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) {
-        // We add the attributes from this import into the list.
-        add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
+        if first {
+            // This is the "original" reexport so we get all its attributes without filtering them.
+            attributes.extend_from_slice(hir_map.attrs(item.hir_id()));
+            first = false;
+        } else {
+            add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
+        }
 
-        let def_id = if path.segments.len() > 1 {
-            match path.segments[path.segments.len() - 2].res {
+        let def_id = if let [.., parent_segment, _] = &path.segments {
+            match parent_segment.res {
                 hir::def::Res::Def(_, def_id) => def_id,
+                _ if parent_segment.ident.name == kw::Crate => {
+                    // In case the "parent" is the crate, it'll give `Res::Err` so we need to
+                    // circumvent it this way.
+                    tcx.parent(item.owner_id.def_id.to_def_id())
+                }
                 _ => break,
             }
         } else {
@@ -2341,9 +2353,7 @@ fn clean_maybe_renamed_item<'tcx>(
         if let Some(import_id) = import_id &&
             let Some(hir::Node::Item(use_node)) = cx.tcx.hir().find_by_def_id(import_id)
         {
-            // First, we add the attributes from the current import.
-            extra_attrs.extend_from_slice(inline::load_attrs(cx, import_id.to_def_id()));
-            let is_inline = extra_attrs.lists(sym::doc).get_word_attr(sym::inline).is_some();
+            let is_inline = inline::load_attrs(cx, import_id.to_def_id()).lists(sym::doc).get_word_attr(sym::inline).is_some();
             // Then we get all the various imports' attributes.
             get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs, is_inline);
             add_without_unwanted_attributes(&mut extra_attrs, inline::load_attrs(cx, def_id), is_inline);
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index ed7683e36fd..ef38ca3c16c 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -63,7 +63,8 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
     let snippet = source_map.span_to_snippet(span).ok()?;
 
     // Create a Parser.
-    let sess = ParseSess::new(FilePathMapping::empty());
+    let sess =
+        ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), FilePathMapping::empty());
     let file_name = source_map.span_to_filename(span);
     let mut parser =
         match rustc_parse::maybe_new_parser_from_source_str(&sess, file_name, snippet.clone()) {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 5a564c2ac1c..c9c1c2c458a 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -470,6 +470,12 @@ pub(crate) fn get_auto_trait_and_blanket_impls(
     cx: &mut DocContext<'_>,
     item_def_id: DefId,
 ) -> impl Iterator<Item = Item> {
+    // FIXME: To be removed once `parallel_compiler` bugs are fixed!
+    // More information in <https://github.com/rust-lang/rust/pull/106930>.
+    if cfg!(parallel_compiler) {
+        return vec![].into_iter().chain(vec![].into_iter());
+    }
+
     let auto_impls = cx
         .sess()
         .prof
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 5ab7056be44..fbfc58a436b 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -115,8 +115,10 @@ pub(crate) fn new_handler(
     diagnostic_width: Option<usize>,
     unstable_opts: &UnstableOptions,
 ) -> rustc_errors::Handler {
-    let fallback_bundle =
-        rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+    let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+        rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+        false,
+    );
     let emitter: Box<dyn Emitter + sync::Send> = match error_format {
         ErrorOutputType::HumanReadable(kind) => {
             let (short, color_config) = kind.unzip();
@@ -254,6 +256,7 @@ pub(crate) fn create_config(
         output_file: None,
         output_dir: None,
         file_loader: None,
+        locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES,
         lint_caps,
         parse_sess_created: None,
         register_lints: Some(Box::new(crate::lint::register_lints)),
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 0eba81c7c1e..8a73d25d3f0 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -96,6 +96,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
         output_file: None,
         output_dir: None,
         file_loader: None,
+        locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES,
         lint_caps,
         parse_sess_created: None,
         register_lints: Some(Box::new(crate::lint::register_lints)),
@@ -545,8 +546,10 @@ pub(crate) fn make_test(
             // Any errors in parsing should also appear when the doctest is compiled for real, so just
             // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-            let fallback_bundle =
-                rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+            let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+                rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+                false,
+            );
             supports_color = EmitterWriter::stderr(
                 ColorConfig::Auto,
                 None,
@@ -741,8 +744,10 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
             // Any errors in parsing should also appear when the doctest is compiled for real, so just
             // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-            let fallback_bundle =
-                rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+            let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+                rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+                false,
+            );
 
             let emitter = EmitterWriter::new(
                 Box::new(io::sink()),
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index aa406f30cbe..6bdd9db9bfa 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -775,7 +775,7 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
     let fqp = fqp.iter().map(|sym| sym.as_str()).join("::");
     if let &Some(UrlFragment::Item(id)) = fragment {
         let name = cx.tcx().item_name(id);
-        let descr = cx.tcx().def_kind(id).descr(id);
+        let descr = cx.tcx().def_descr(id);
         format!("{descr} {fqp}::{name}")
     } else {
         format!("{shortty} {fqp}")
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 9ef0b501c08..89f1ad71134 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -552,10 +552,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
 }
 
 fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
-    matches!(
-        t,
-        Tag::Paragraph | Tag::Item | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote
-    )
+    matches!(t, Tag::Paragraph | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote)
 }
 
 fn is_forbidden_tag(t: &Tag<'_>) -> bool {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 910a7190b58..4fcf0873600 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -20,6 +20,7 @@
 #![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
 #![allow(rustc::potential_query_instability)]
 
+extern crate thin_vec;
 #[macro_use]
 extern crate tracing;
 
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 03be5e79971..26fbb03a43e 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -33,8 +33,10 @@ fn check_rust_syntax(
     code_block: RustCodeBlock,
 ) {
     let buffer = Lrc::new(Lock::new(Buffer::default()));
-    let fallback_bundle =
-        rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+    let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+        rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+        false,
+    );
     let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle };
 
     let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 9c1e5f4a3cd..277201e4de9 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -1,7 +1,7 @@
 //! The Rust AST Visitor. Extracts useful information and massages it into a form
 //! usable for `clean`.
 
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
@@ -26,8 +26,12 @@ pub(crate) struct Module<'hir> {
     pub(crate) where_inner: Span,
     pub(crate) mods: Vec<Module<'hir>>,
     pub(crate) def_id: LocalDefId,
-    // (item, renamed, import_id)
-    pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>, Option<LocalDefId>)>,
+    /// The key is the item `ItemId` and the value is: (item, renamed, import_id).
+    /// We use `FxIndexMap` to keep the insert order.
+    pub(crate) items: FxIndexMap<
+        (LocalDefId, Option<Symbol>),
+        (&'hir hir::Item<'hir>, Option<Symbol>, Option<LocalDefId>),
+    >,
     pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
 }
 
@@ -38,7 +42,7 @@ impl Module<'_> {
             def_id,
             where_inner,
             mods: Vec::new(),
-            items: Vec::new(),
+            items: FxIndexMap::default(),
             foreigns: Vec::new(),
         }
     }
@@ -136,7 +140,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 inserted.insert(def_id)
             {
                     let item = self.cx.tcx.hir().expect_item(local_def_id);
-                    top_level_module.items.push((item, None, None));
+                    top_level_module.items.insert((local_def_id, Some(item.ident.name)), (item, None, None));
             }
         }
 
@@ -294,7 +298,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         renamed: Option<Symbol>,
         parent_id: Option<LocalDefId>,
     ) {
-        self.modules.last_mut().unwrap().items.push((item, renamed, parent_id))
+        self.modules
+            .last_mut()
+            .unwrap()
+            .items
+            .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
     }
 
     fn visit_item_inner(
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 17b3d0de0897e1c6b8ca347bd39f850bb0a5b9f
+Subproject 9d5b32f503fc099c4064298465add14d4bce11e
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index b4543aa2544..644604a2e3f 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -27,7 +27,7 @@ use rustc_middle::mir::{Rvalue, StatementKind};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{
     self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
-    ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
+    ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
 };
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{symbol::sym, Span, Symbol};
@@ -1022,7 +1022,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
                     ))
                     .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
             ),
-            TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
+            TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err(_) => {
                 Position::ReborrowStable(precedence)
             },
         };
@@ -1038,7 +1038,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
             if self.0
                 || matches!(
                     ty.kind,
-                    TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err
+                    TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_)
                 )
             {
                 self.0 = true;
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 1cdcccd5f14..b8428d66a5d 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -514,7 +514,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
     }
 
     ParamEnv::new(
-        tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
+        tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
             params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
                 tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
                     trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]),
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index 0b31e20fc87..6fdb7de25cc 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -704,8 +704,10 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
                 let filename = FileName::anon_source_code(&code);
 
                 let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-                let fallback_bundle =
-                    rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+                let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+                    rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+                    false
+                );
                 let emitter = EmitterWriter::new(
                     Box::new(io::sink()),
                     None,
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index ddade65c515..b2071f4dcb1 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -11,7 +11,7 @@ use rustc_hir::{Closure, Expr, ExprKind, Param, PatKind, Unsafety};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::{self, EarlyBinder, SubstsRef, Ty, TypeVisitable};
+use rustc_middle::ty::{self, EarlyBinder, SubstsRef, Ty, TypeVisitableExt};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
 
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 565c5b7af00..9011f0896a0 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -42,6 +42,7 @@ extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
+extern crate thin_vec;
 
 #[macro_use]
 extern crate clippy_utils;
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 14f161f5102..d7e00047312 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -224,7 +224,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
         | ExprKind::Path(_)
         | ExprKind::ConstBlock(_)
         | ExprKind::Lit(_)
-        | ExprKind::Err => NeverLoopResult::Otherwise,
+        | ExprKind::Err(_) => NeverLoopResult::Otherwise,
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index f587c69f730..b33a2478172 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -341,7 +341,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
             ExprKind::ConstBlock(_) |
             ExprKind::Continue(_) |
             ExprKind::DropTemps(_) |
-            ExprKind::Err |
+            ExprKind::Err(_) |
             ExprKind::InlineAsm(_) |
             ExprKind::Let(_) |
             ExprKind::Lit(_) |
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 8ddbacc3d7a..0b0c6adc504 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -173,7 +173,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
         && let Some(iter_item) = cx.tcx
             .associated_items(iter_trait)
             .find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait)
-        && let substs = cx.tcx.intern_substs(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
+        && let substs = cx.tcx.mk_substs(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
         && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs)
         && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
     {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 4e5af1c7c71..df26b36b7b3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -414,7 +414,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
                             }
                         });
 
-                        let new_subst = cx.tcx.mk_substs(
+                        let new_subst = cx.tcx.mk_substs_from_iter(
                             call_substs.iter()
                                 .enumerate()
                                 .map(|(i, t)|
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 3cc765108d7..5a533261cad 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -3,7 +3,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::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 996ea6ed723..da3b6fa9899 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -18,7 +18,7 @@ use rustc_hir_typeck::expr_use_visitor as euv;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, TypeVisitable};
+use rustc_middle::ty::{self, TypeVisitableExt};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::kw;
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index 24aeb82a37f..d3de9699fe9 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -49,10 +49,10 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
             (arg, arg.span)
         },
         ExprKind::Call(path, [arg])
-            if path_def_id(cx, path).map_or(false, |id| {
-                if match_def_path(cx, id, &paths::FROM_STR_METHOD) {
+            if path_def_id(cx, path).map_or(false, |did| {
+                if match_def_path(cx, did, &paths::FROM_STR_METHOD) {
                     true
-                } else if cx.tcx.lang_items().from_fn() == Some(id) {
+                } else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
                     !is_copy(cx, typeck.expr_ty(expr))
                 } else {
                     false
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 398329e455b..2fdd775ad48 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
                 } else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
                     if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
                         cx.param_env,
-                        cx.tcx.mk_projection(target_id, cx.tcx.intern_substs(&[GenericArg::from(indexed_ty)])),
+                        cx.tcx.mk_projection(target_id, cx.tcx.mk_substs(&[GenericArg::from(indexed_ty)])),
                     ) {
                         if deref_ty == expr_ty {
                             let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index 54ac04df1c1..6bdb9aa5a26 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -6,7 +6,7 @@ use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, Expr, GenericArg, Mutability, Path, TyKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
 /// Checks for `transmute_ptr_to_ref` lint.
 /// Returns `true` if it's triggered, otherwise returns `false`.
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index 871c3fadbba..56207fe767c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -4,7 +4,7 @@ use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
 /// Checks for `useless_transmute` lint.
 /// Returns `true` if it's triggered, otherwise returns `false`.
diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
index f9b9a66b5fa..f7adc9d3555 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_span::symbol::sym;
 
 use super::{utils, REDUNDANT_ALLOCATION};
diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
index 7a3c7cd8a99..d3062f3d2e3 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -7,7 +7,7 @@ use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_span::symbol::sym;
 
 use super::VEC_BOX;
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
index 9f207d32fcf..6e802794f5a 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
@@ -7,6 +7,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -54,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
                         );
                 } else {
                     if_chain! {
-                        if Some(fun_def_id) == cx.tcx.lang_items().from_fn();
+                        if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id);
                         if let [.., last_arg] = args;
                         if let ExprKind::Lit(spanned) = &last_arg.kind;
                         if let LitKind::Str(symbol, _) = spanned.node;
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 7355260ae4a..06d248204c1 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -12,9 +12,9 @@ use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::DUMMY_SP;
-
 use std::cell::Cell;
 use std::mem;
+use thin_vec::{thin_vec, ThinVec};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -214,7 +214,7 @@ macro_rules! always_pat {
 /// Focus on `focus_idx` in `alternatives`,
 /// attempting to extend it with elements of the same constructor `C`
 /// in `alternatives[focus_idx + 1..]`.
-fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize) -> bool {
+fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: usize) -> bool {
     // Extract the kind; we'll need to make some changes in it.
     let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, PatKind::Wild);
     // We'll focus on `alternatives[focus_idx]`,
@@ -296,7 +296,7 @@ fn extend_with_struct_pat(
     fps1: &mut [ast::PatField],
     rest1: bool,
     start: usize,
-    alternatives: &mut Vec<P<Pat>>,
+    alternatives: &mut ThinVec<P<Pat>>,
 ) -> bool {
     (0..fps1.len()).any(|idx| {
         let pos_in_2 = Cell::new(None); // The element `k`.
@@ -336,9 +336,9 @@ fn extend_with_struct_pat(
 fn extend_with_matching_product(
     targets: &mut [P<Pat>],
     start: usize,
-    alternatives: &mut Vec<P<Pat>>,
+    alternatives: &mut ThinVec<P<Pat>>,
     predicate: impl Fn(&PatKind, &[P<Pat>], usize) -> bool,
-    extract: impl Fn(PatKind) -> Vec<P<Pat>>,
+    extract: impl Fn(PatKind) -> ThinVec<P<Pat>>,
 ) -> bool {
     (0..targets.len()).any(|idx| {
         let tail_or = drain_matching(
@@ -365,14 +365,14 @@ fn take_pat(from: &mut Pat) -> Pat {
 
 /// Extend `target` as an or-pattern with the alternatives
 /// in `tail_or` if there are any and return if there were.
-fn extend_with_tail_or(target: &mut Pat, tail_or: Vec<P<Pat>>) -> bool {
-    fn extend(target: &mut Pat, mut tail_or: Vec<P<Pat>>) {
+fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<P<Pat>>) -> bool {
+    fn extend(target: &mut Pat, mut tail_or: ThinVec<P<Pat>>) {
         match target {
             // On an existing or-pattern in the target, append to it.
             Pat { kind: Or(ps), .. } => ps.append(&mut tail_or),
             // Otherwise convert the target to an or-pattern.
             target => {
-                let mut init_or = vec![P(take_pat(target))];
+                let mut init_or = thin_vec![P(take_pat(target))];
                 init_or.append(&mut tail_or);
                 target.kind = Or(init_or);
             },
@@ -391,26 +391,42 @@ fn extend_with_tail_or(target: &mut Pat, tail_or: Vec<P<Pat>>) -> bool {
 // Only elements beginning with `start` are considered for extraction.
 fn drain_matching(
     start: usize,
-    alternatives: &mut Vec<P<Pat>>,
+    alternatives: &mut ThinVec<P<Pat>>,
     predicate: impl Fn(&PatKind) -> bool,
     extract: impl Fn(PatKind) -> P<Pat>,
-) -> Vec<P<Pat>> {
-    let mut tail_or = vec![];
+) -> ThinVec<P<Pat>> {
+    let mut tail_or = ThinVec::new();
     let mut idx = 0;
-    for pat in alternatives.drain_filter(|p| {
-        // Check if we should extract, but only if `idx >= start`.
+
+    // If `ThinVec` had the `drain_filter` method, this loop could be rewritten
+    // like so:
+    // 
+    //   for pat in alternatives.drain_filter(|p| {
+    //       // Check if we should extract, but only if `idx >= start`.
+    //       idx += 1;
+    //       idx > start && predicate(&p.kind)
+    //   }) {
+    //       tail_or.push(extract(pat.into_inner().kind));
+    //   }
+    let mut i = 0;
+    while i < alternatives.len() {
         idx += 1;
-        idx > start && predicate(&p.kind)
-    }) {
-        tail_or.push(extract(pat.into_inner().kind));
+        // Check if we should extract, but only if `idx >= start`.
+	if idx > start && predicate(&alternatives[i].kind) {
+	    let pat = alternatives.remove(i);
+            tail_or.push(extract(pat.into_inner().kind));
+	} else {
+	    i += 1;
+	}
     }
+
     tail_or
 }
 
 fn extend_with_matching(
     target: &mut Pat,
     start: usize,
-    alternatives: &mut Vec<P<Pat>>,
+    alternatives: &mut ThinVec<P<Pat>>,
     predicate: impl Fn(&PatKind) -> bool,
     extract: impl Fn(PatKind) -> P<Pat>,
 ) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index a95e7b61374..fede625f72a 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         }
 
                         if_chain! {
-                            if Some(def_id) == cx.tcx.lang_items().from_fn();
+                            if cx.tcx.is_diagnostic_item(sym::from_fn, def_id);
                             if same_type_and_consts(a, b);
 
                             then {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index bd7daf0773c..c37e5bb6716 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -588,7 +588,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                     },
                 }
             },
-            ExprKind::Err => kind!("Err"),
+            ExprKind::Err(_) => kind!("Err"),
             ExprKind::DropTemps(expr) => {
                 bind!(self, expr);
                 kind!("DropTemps({expr})");
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 6cf2a955fd5..93e4b023c5c 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
@@ -5,7 +5,7 @@ use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf as _;
-use rustc_middle::ty::{Adt, Ty, TypeVisitable};
+use rustc_middle::ty::{Adt, Ty, TypeVisitableExt};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 9d0263e93be..d82098523e3 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -144,7 +144,8 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (_, Paren(r)) => eq_expr(l, r),
         (Err, Err) => true,
         (Box(l), Box(r)) | (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r),
-        (Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
+        (Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)),
+        (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
         (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
         (Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
         (
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 8b00ce2cc25..bb8890dcaf9 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -237,7 +237,7 @@ pub fn constant<'tcx>(
         typeck_results,
         param_env: lcx.param_env,
         needed_resolution: false,
-        substs: lcx.tcx.intern_substs(&[]),
+        substs: ty::List::empty(),
     };
     cx.expr(e).map(|cst| (cst, cx.needed_resolution))
 }
@@ -306,7 +306,7 @@ pub fn constant_context<'a, 'tcx>(
         typeck_results,
         param_env: lcx.param_env,
         needed_resolution: false,
-        substs: lcx.tcx.intern_substs(&[]),
+        substs: ty::List::empty(),
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 6ff7728374f..ee2f816f181 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -193,7 +193,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 | ExprKind::Ret(_)
                 | ExprKind::InlineAsm(_)
                 | ExprKind::Yield(..)
-                | ExprKind::Err => {
+                | ExprKind::Err(_) => {
                     self.eagerness = ForceNoChange;
                     return;
                 },
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 2bbe1a19b62..0603755f8a9 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -714,7 +714,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 }
                 self.hash_pat(pat);
             },
-            ExprKind::Err => {},
+            ExprKind::Err(_) => {},
             ExprKind::Lit(ref l) => {
                 l.node.hash(&mut self.s);
             },
@@ -986,7 +986,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             TyKind::Typeof(anon_const) => {
                 self.hash_body(anon_const.body);
             },
-            TyKind::Err | TyKind::Infer | TyKind::Never => {},
+            TyKind::Err(_) | TyKind::Infer | TyKind::Never => {},
         }
     }
 
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index b2edd1bbfef..f02f8ecb43d 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -104,7 +104,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType::{
     PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
 };
 use rustc_middle::ty::{
-    layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitable, UpvarCapture,
+    layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UpvarCapture,
 };
 use rustc_middle::ty::{FloatTy, IntTy, UintTy};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
index e9dc7351b58..920ce8e655b 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::{BitSet, HybridBitSet};
 use rustc_lint::LateContext;
 use rustc_middle::mir::{self, visit::Visitor as _, Mutability};
-use rustc_middle::ty::{self, visit::ir::TypeVisitor, TyCtxt};
+use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt};
 use rustc_mir_dataflow::{impls::MaybeStorageLive, Analysis, ResultsCursor};
 use std::borrow::Cow;
 use std::ops::ControlFlow;
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 78fb2e0eb7e..11ca81cfe6c 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -157,7 +157,7 @@ impl<'a> Sugg<'a> {
             | hir::ExprKind::Ret(..)
             | hir::ExprKind::Struct(..)
             | hir::ExprKind::Tup(..)
-            | hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
+            | hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
             hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
             hir::ExprKind::Assign(lhs, rhs, _) => {
                 Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 2ed301fcc22..f8ec4bb5493 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -17,8 +17,8 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
     self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate,
-    PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, ir::TypeVisitor, UintTy,
-    VariantDef, VariantDiscr,
+    PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+    VariantDef, VariantDiscr, TypeVisitableExt,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::symbol::Ident;
@@ -237,7 +237,7 @@ pub fn implements_trait_with_env<'tcx>(
         kind: TypeVariableOriginKind::MiscVariable,
         span: DUMMY_SP,
     };
-    let ty_params = tcx.mk_substs(
+    let ty_params = tcx.mk_substs_from_iter(
         ty_params
             .into_iter()
             .map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(orig).into())),
@@ -847,7 +847,7 @@ pub fn for_each_top_level_late_bound_region<B>(
                 ControlFlow::Continue(())
             }
         }
-        fn visit_binder<T: TypeVisitable<'tcx>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow<Self::BreakTy> {
+        fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow<Self::BreakTy> {
             self.index += 1;
             let res = t.super_visit_with(self);
             self.index -= 1;
@@ -1065,7 +1065,7 @@ pub fn make_projection<'tcx>(
         tcx,
         container_id,
         assoc_ty,
-        tcx.mk_substs(substs.into_iter().map(Into::into)),
+        tcx.mk_substs_from_iter(substs.into_iter().map(Into::into)),
     )
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 00073bcd82a..d27a20bd4df 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -665,7 +665,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
             | ExprKind::Path(_)
             | ExprKind::Continue(_)
             | ExprKind::InlineAsm(_)
-            | ExprKind::Err => (),
+            | ExprKind::Err(_) => (),
         }
         ControlFlow::Continue(())
     }
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index e45835efe74..9ac849aecf1 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -209,7 +209,10 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     // Separate the output with an empty line
     eprintln!();
 
-    let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+    let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+        rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+        false
+    );
     let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
         rustc_errors::ColorConfig::Auto,
         None,
diff --git a/src/tools/clippy/tests/ui/missing_doc_impl.stderr b/src/tools/clippy/tests/ui/missing_doc_impl.stderr
index f22fa19dbca..b410f56e167 100644
--- a/src/tools/clippy/tests/ui/missing_doc_impl.stderr
+++ b/src/tools/clippy/tests/ui/missing_doc_impl.stderr
@@ -51,13 +51,13 @@ LL | |     fn foo_with_impl(&self) {}
 LL | | }
    | |_^
 
-error: missing documentation for an associated function
+error: missing documentation for a method
   --> $DIR/missing_doc_impl.rs:44:5
    |
 LL |     fn foo(&self);
    |     ^^^^^^^^^^^^^^
 
-error: missing documentation for an associated function
+error: missing documentation for a method
   --> $DIR/missing_doc_impl.rs:45:5
    |
 LL |     fn foo_with_impl(&self) {}
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index deed6fbd439..0db043a4fca 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -16,7 +16,7 @@ regex = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 rustfix = "0.6.0"
-lazy_static = "1.0"
+once_cell = "1.16.0"
 walkdir = "2"
 glob = "0.3.0"
 lazycell = "1.3.0"
@@ -25,5 +25,5 @@ lazycell = "1.3.0"
 libc = "0.2"
 
 [target.'cfg(windows)'.dependencies]
-miow = "0.3"
+miow = "0.5"
 winapi = { version = "0.3", features = ["winerror"] }
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 054235ec16d..c33e66e02ac 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -7,7 +7,7 @@ use std::io::BufReader;
 use std::path::Path;
 use std::str::FromStr;
 
-use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
 use regex::Regex;
 use tracing::*;
 
@@ -117,10 +117,8 @@ fn parse_expected(
     //     //~^^^^^
     //     //[cfg1]~
     //     //[cfg1,cfg2]~^^
-    lazy_static! {
-        static ref RE: Regex =
-            Regex::new(r"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap();
-    }
+    static RE: Lazy<Regex> =
+        Lazy::new(|| Regex::new(r"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap());
 
     let captures = RE.captures(line)?;
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index c648b2f12f1..1760c29ec66 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -588,7 +588,8 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
     let full_paths = {
         let mut full_paths: Vec<PathBuf> = all_paths
             .into_iter()
-            .map(|f| fs::canonicalize(&f).unwrap().with_extension("").with_extension("rs"))
+            .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
+            .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
             .collect();
         full_paths.dedup();
         full_paths.sort_unstable();
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 51c9a27c83d..7824ef81d7a 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -32,7 +32,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio};
 use std::str;
 
 use glob::glob;
-use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
 use tracing::*;
 
 use crate::extract_gdb_version;
@@ -52,9 +52,8 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
     use winapi::um::errhandlingapi::SetErrorMode;
     use winapi::um::winbase::SEM_NOGPFAULTERRORBOX;
 
-    lazy_static! {
-        static ref LOCK: Mutex<()> = Mutex::new(());
-    }
+    static LOCK: Mutex<()> = Mutex::new(());
+
     // Error mode is a global variable, so lock it so only one thread will change it
     let _lock = LOCK.lock().unwrap();
 
@@ -2848,11 +2847,10 @@ impl<'test> TestCx<'test> {
         // the form <crate-name1>.<crate-disambiguator1>-in-<crate-name2>.<crate-disambiguator2>,
         // remove all crate-disambiguators.
         fn remove_crate_disambiguator_from_cgu(cgu: &str) -> String {
-            lazy_static! {
-                static ref RE: Regex =
-                    Regex::new(r"^[^\.]+(?P<d1>\.[[:alnum:]]+)(-in-[^\.]+(?P<d2>\.[[:alnum:]]+))?")
-                        .unwrap();
-            }
+            static RE: Lazy<Regex> = Lazy::new(|| {
+                Regex::new(r"^[^\.]+(?P<d1>\.[[:alnum:]]+)(-in-[^\.]+(?P<d2>\.[[:alnum:]]+))?")
+                    .unwrap()
+            });
 
             let captures =
                 RE.captures(cgu).unwrap_or_else(|| panic!("invalid cgu name encountered: {}", cgu));
@@ -3170,12 +3168,12 @@ impl<'test> TestCx<'test> {
                 // 'uploaded "$TEST_BUILD_DIR/<test_executable>, waiting for result"'
                 // is printed to stdout by the client and then captured in the ProcRes,
                 // so it needs to be removed when comparing the run-pass test execution output
-                lazy_static! {
-                    static ref REMOTE_TEST_RE: Regex = Regex::new(
+                static REMOTE_TEST_RE: Lazy<Regex> = Lazy::new(|| {
+                    Regex::new(
                         "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-.]+)+\", waiting for result\n"
                     )
-                    .unwrap();
-                }
+                    .unwrap()
+                });
                 REMOTE_TEST_RE
                     .replace(
                         &self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout),
@@ -3620,10 +3618,8 @@ impl<'test> TestCx<'test> {
         // with placeholders as we do not want tests needing updated when compiler source code
         // changes.
         // eg. $SRC_DIR/libcore/mem.rs:323:14 becomes $SRC_DIR/libcore/mem.rs:LL:COL
-        lazy_static! {
-            static ref SRC_DIR_RE: Regex =
-                Regex::new("SRC_DIR(.+):\\d+:\\d+(: \\d+:\\d+)?").unwrap();
-        }
+        static SRC_DIR_RE: Lazy<Regex> =
+            Lazy::new(|| Regex::new("SRC_DIR(.+):\\d+:\\d+(: \\d+:\\d+)?").unwrap());
 
         normalized = SRC_DIR_RE.replace_all(&normalized, "SRC_DIR$1:LL:COL").into_owned();
 
@@ -3634,19 +3630,17 @@ impl<'test> TestCx<'test> {
         // since they duplicate actual errors and make the output hard to read.
         // This mirrors the regex in src/tools/tidy/src/style.rs, please update
         // both if either are changed.
-        lazy_static! {
-            static ref ANNOTATION_RE: Regex = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
-        }
+        static ANNOTATION_RE: Lazy<Regex> =
+            Lazy::new(|| Regex::new("\\s*//(\\[.*\\])?~.*").unwrap());
 
         normalized = ANNOTATION_RE.replace_all(&normalized, "").into_owned();
 
         // This code normalizes various hashes in v0 symbol mangling that is
         // emitted in the ui and mir-opt tests.
-        lazy_static! {
-            static ref V0_CRATE_HASH_PREFIX_RE: Regex =
-                Regex::new(r"_R.*?Cs[0-9a-zA-Z]+_").unwrap();
-            static ref V0_CRATE_HASH_RE: Regex = Regex::new(r"Cs[0-9a-zA-Z]+_").unwrap();
-        }
+        static V0_CRATE_HASH_PREFIX_RE: Lazy<Regex> =
+            Lazy::new(|| Regex::new(r"_R.*?Cs[0-9a-zA-Z]+_").unwrap());
+        static V0_CRATE_HASH_RE: Lazy<Regex> =
+            Lazy::new(|| Regex::new(r"Cs[0-9a-zA-Z]+_").unwrap());
 
         const V0_CRATE_HASH_PLACEHOLDER: &str = r"CsCRATE_HASH_";
         if V0_CRATE_HASH_PREFIX_RE.is_match(&normalized) {
@@ -3655,10 +3649,9 @@ impl<'test> TestCx<'test> {
                 V0_CRATE_HASH_RE.replace_all(&normalized, V0_CRATE_HASH_PLACEHOLDER).into_owned();
         }
 
-        lazy_static! {
-            static ref V0_BACK_REF_PREFIX_RE: Regex = Regex::new(r"\(_R.*?B[0-9a-zA-Z]_").unwrap();
-            static ref V0_BACK_REF_RE: Regex = Regex::new(r"B[0-9a-zA-Z]_").unwrap();
-        }
+        static V0_BACK_REF_PREFIX_RE: Lazy<Regex> =
+            Lazy::new(|| Regex::new(r"\(_R.*?B[0-9a-zA-Z]_").unwrap());
+        static V0_BACK_REF_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"B[0-9a-zA-Z]_").unwrap());
 
         const V0_BACK_REF_PLACEHOLDER: &str = r"B<REF>_";
         if V0_BACK_REF_PREFIX_RE.is_match(&normalized) {
@@ -3681,21 +3674,23 @@ impl<'test> TestCx<'test> {
     /// Replaces backslashes in paths with forward slashes, and replaces CRLF line endings
     /// with LF.
     fn normalize_platform_differences(output: &str) -> String {
-        lazy_static! {
-            /// Used to find Windows paths.
-            ///
-            /// It's not possible to detect paths in the error messages generally, but this is a
-            /// decent enough heuristic.
-            static ref PATH_BACKSLASH_RE: Regex = Regex::new(r#"(?x)
+        /// Used to find Windows paths.
+        ///
+        /// It's not possible to detect paths in the error messages generally, but this is a
+        /// decent enough heuristic.
+        static PATH_BACKSLASH_RE: Lazy<Regex> = Lazy::new(|| {
+            Regex::new(
+                r#"(?x)
                 (?:
                   # Match paths that don't include spaces.
                   (?:\\[\pL\pN\.\-_']+)+\.\pL+
                 |
                   # If the path starts with a well-known root, then allow spaces.
                   \$(?:DIR|SRC_DIR|TEST_BUILD_DIR|BUILD_DIR|LIB_DIR)(?:\\[\pL\pN\.\-_' ]+)+
-                )"#
-            ).unwrap();
-        }
+                )"#,
+            )
+            .unwrap()
+        });
 
         let output = output.replace(r"\\", r"\");
 
diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml
index f4dac6e947e..76c2e330b21 100644
--- a/src/tools/error_index_generator/Cargo.toml
+++ b/src/tools/error_index_generator/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 mdbook = { version = "0.4", default-features = false, features = ["search"] }
+rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
 
 [[bin]]
 name = "error_index_generator"
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 98eda97e236..f984275b164 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -2,9 +2,6 @@
 
 extern crate rustc_driver;
 
-// We use the function we generate from `register_diagnostics!`.
-use crate::error_codes::error_codes;
-
 use std::env;
 use std::error::Error;
 use std::fs::{self, File};
@@ -17,22 +14,6 @@ use std::str::FromStr;
 use mdbook::book::{parse_summary, BookItem, Chapter};
 use mdbook::{Config, MDBook};
 
-macro_rules! register_diagnostics {
-    ($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
-        pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
-            let mut errors: Vec<(&str, Option<&str>)> = vec![
-                $((stringify!($error_code), Some($message)),)+
-                $((stringify!($undocumented), None),)+
-            ];
-            errors.sort();
-            errors
-        }
-    }
-}
-
-#[path = "../../../compiler/rustc_error_codes/src/error_codes.rs"]
-mod error_codes;
-
 enum OutputFormat {
     HTML,
     Markdown,
@@ -55,11 +36,8 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
 
     write!(output_file, "# Rust Compiler Error Index\n")?;
 
-    for (err_code, description) in error_codes().iter() {
-        match description {
-            Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
-            None => {}
-        }
+    for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
+        write!(output_file, "## {}\n{}\n", err_code, description)?
     }
 
     Ok(())
@@ -105,27 +83,23 @@ This page lists all the error codes emitted by the Rust compiler.
 "
     );
 
-    let err_codes = error_codes();
+    let err_codes = rustc_error_codes::DIAGNOSTICS;
     let mut chapters = Vec::with_capacity(err_codes.len());
 
     for (err_code, explanation) in err_codes.iter() {
-        if let Some(explanation) = explanation {
-            introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
-
-            let content = add_rust_attribute_on_codeblock(explanation);
-            chapters.push(BookItem::Chapter(Chapter {
-                name: err_code.to_string(),
-                content: format!("# Error code {}\n\n{}\n", err_code, content),
-                number: None,
-                sub_items: Vec::new(),
-                // We generate it into the `error_codes` folder.
-                path: Some(PathBuf::from(&format!("{}.html", err_code))),
-                source_path: None,
-                parent_names: Vec::new(),
-            }));
-        } else {
-            introduction.push_str(&format!(" * {}\n", err_code));
-        }
+        introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
+
+        let content = add_rust_attribute_on_codeblock(explanation);
+        chapters.push(BookItem::Chapter(Chapter {
+            name: err_code.to_string(),
+            content: format!("# Error code {}\n\n{}\n", err_code, content),
+            number: None,
+            sub_items: Vec::new(),
+            // We generate it into the `error_codes` folder.
+            path: Some(PathBuf::from(&format!("{}.html", err_code))),
+            source_path: None,
+            parent_names: Vec::new(),
+        }));
     }
 
     let mut config = Config::from_str(include_str!("book_config.toml"))?;
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index c6f55410e44..a1f675a3b40 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -71,6 +71,19 @@ impl<'a> Validator<'a> {
         }
     }
 
+    fn check_items(&mut self, id: &Id, items: &[Id]) {
+        let mut visited_ids = HashSet::with_capacity(items.len());
+
+        for item in items {
+            if !visited_ids.insert(item) {
+                self.fail(
+                    id,
+                    ErrorKind::Custom(format!("Duplicated entry in `items` field: `{item:?}`")),
+                );
+            }
+        }
+    }
+
     fn check_item(&mut self, id: &'a Id) {
         if let Some(item) = &self.krate.index.get(id) {
             item.links.values().for_each(|id| self.add_any_id(id));
@@ -83,9 +96,9 @@ impl<'a> Validator<'a> {
                 ItemEnum::Enum(x) => self.check_enum(x),
                 ItemEnum::Variant(x) => self.check_variant(x, id),
                 ItemEnum::Function(x) => self.check_function(x),
-                ItemEnum::Trait(x) => self.check_trait(x),
+                ItemEnum::Trait(x) => self.check_trait(x, id),
                 ItemEnum::TraitAlias(x) => self.check_trait_alias(x),
-                ItemEnum::Impl(x) => self.check_impl(x),
+                ItemEnum::Impl(x) => self.check_impl(x, id),
                 ItemEnum::Typedef(x) => self.check_typedef(x),
                 ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
                 ItemEnum::Constant(x) => self.check_constant(x),
@@ -94,7 +107,7 @@ impl<'a> Validator<'a> {
                 ItemEnum::Macro(x) => self.check_macro(x),
                 ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
                 ItemEnum::Primitive(x) => self.check_primitive_type(x),
-                ItemEnum::Module(x) => self.check_module(x),
+                ItemEnum::Module(x) => self.check_module(x, id),
                 // FIXME: Why don't these have their own structs?
                 ItemEnum::ExternCrate { .. } => {}
                 ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_),
@@ -112,7 +125,8 @@ impl<'a> Validator<'a> {
     }
 
     // Core checkers
-    fn check_module(&mut self, module: &'a Module) {
+    fn check_module(&mut self, module: &'a Module, id: &Id) {
+        self.check_items(id, &module.items);
         module.items.iter().for_each(|i| self.add_mod_item_id(i));
     }
 
@@ -181,7 +195,8 @@ impl<'a> Validator<'a> {
         self.check_fn_decl(&x.decl);
     }
 
-    fn check_trait(&mut self, x: &'a Trait) {
+    fn check_trait(&mut self, x: &'a Trait, id: &Id) {
+        self.check_items(id, &x.items);
         self.check_generics(&x.generics);
         x.items.iter().for_each(|i| self.add_trait_item_id(i));
         x.bounds.iter().for_each(|i| self.check_generic_bound(i));
@@ -193,7 +208,8 @@ impl<'a> Validator<'a> {
         x.params.iter().for_each(|i| self.check_generic_bound(i));
     }
 
-    fn check_impl(&mut self, x: &'a Impl) {
+    fn check_impl(&mut self, x: &'a Impl, id: &Id) {
+        self.check_items(id, &x.items);
         self.check_generics(&x.generics);
         if let Some(path) = &x.trait_ {
             self.check_path(path, PathKind::Trait);
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 461add9f508..53ec1ba0821 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-f715e430aac0de131e2ad21804013ea405722a66
+c4e0cd966062ca67daed20775f4e8a60c28e57df
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index ebb71b57ae3..8443e907938 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -363,7 +363,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
                 tcx,
                 ty::ParamEnv::reveal_all(),
                 start_id,
-                tcx.intern_substs(&[ty::subst::GenericArg::from(main_ret_ty)]),
+                tcx.mk_substs(&[ty::subst::GenericArg::from(main_ret_ty)]),
             )
             .unwrap()
             .unwrap();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index c82c274524a..f21b4f84c4c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -173,7 +173,7 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
 
             // let pointee = tcx.normalize_erasing_regions(param_env, pointee);
             // if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
-            //     return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
+            //     return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
             // }
 
             let unsized_part = struct_tail_erasing_lifetimes(db, pointee.clone());
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index 39b8d687809..cbe523c6c3c 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -74,6 +74,8 @@ use crate::utils::{
     rewrite_ident, trimmed_last_line_width, wrap_str,
 };
 
+use thin_vec::ThinVec;
+
 /// Provides the original input contents from the span
 /// of a chain element with trailing spaces trimmed.
 fn format_overflow_style(span: Span, context: &RewriteContext<'_>) -> Option<String> {
@@ -168,7 +170,7 @@ enum ChainItemKind {
     MethodCall(
         ast::PathSegment,
         Vec<ast::GenericArg>,
-        Vec<ptr::P<ast::Expr>>,
+        ThinVec<ptr::P<ast::Expr>>,
     ),
     StructField(symbol::Ident),
     TupleField(symbol::Ident, bool),
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index 8fd0fcf8f5c..340113866c4 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -1,5 +1,6 @@
 use rustc_ast::{ast, ptr};
 use rustc_span::Span;
+use thin_vec::thin_vec;
 
 use crate::attr::get_attrs_from_stmt;
 use crate::config::lists::*;
@@ -150,7 +151,7 @@ fn rewrite_closure_with_block(
     }
 
     let block = ast::Block {
-        stmts: vec![ast::Stmt {
+        stmts: thin_vec![ast::Stmt {
             id: ast::NodeId::root(),
             kind: ast::StmtKind::Expr(ptr::P(body.clone())),
             span: body.span,
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 0c27bcacfb8..b27405efdb7 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -23,6 +23,7 @@ extern crate rustc_expand;
 extern crate rustc_parse;
 extern crate rustc_session;
 extern crate rustc_span;
+extern crate thin_vec;
 
 // Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
 // files.
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 7a0d1736c59..af9a154a6ae 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -6,6 +6,7 @@ use rustc_ast::ast;
 use rustc_ast::visit::Visitor;
 use rustc_span::symbol::{self, sym, Symbol};
 use rustc_span::Span;
+use thin_vec::ThinVec;
 use thiserror::Error;
 
 use crate::attr::MetaVisitor;
@@ -25,7 +26,7 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
 #[derive(Debug, Clone)]
 pub(crate) struct Module<'a> {
     ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
-    pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+    pub(crate) items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
     inner_attr: ast::AttrVec,
     pub(crate) span: Span,
 }
@@ -34,7 +35,7 @@ impl<'a> Module<'a> {
     pub(crate) fn new(
         mod_span: Span,
         ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
-        mod_items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+        mod_items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
         mod_attrs: Cow<'a, ast::AttrVec>,
     ) -> Self {
         let inner_attr = mod_attrs
@@ -157,7 +158,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                     Module::new(
                         module_item.item.span,
                         Some(Cow::Owned(sub_mod_kind.clone())),
-                        Cow::Owned(vec![]),
+                        Cow::Owned(ThinVec::new()),
                         Cow::Owned(ast::AttrVec::new()),
                     ),
                 )?;
@@ -169,7 +170,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
     /// Visit modules defined inside macro calls.
     fn visit_mod_outside_ast(
         &mut self,
-        items: Vec<rustc_ast::ptr::P<ast::Item>>,
+        items: ThinVec<rustc_ast::ptr::P<ast::Item>>,
     ) -> Result<(), ModuleResolutionError> {
         for item in items {
             if is_cfg_if(&item) {
@@ -184,7 +185,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                     Module::new(
                         span,
                         Some(Cow::Owned(sub_mod_kind.clone())),
-                        Cow::Owned(vec![]),
+                        Cow::Owned(ThinVec::new()),
                         Cow::Owned(ast::AttrVec::new()),
                     ),
                 )?;
@@ -210,7 +211,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                     Module::new(
                         span,
                         Some(Cow::Borrowed(sub_mod_kind)),
-                        Cow::Owned(vec![]),
+                        Cow::Owned(ThinVec::new()),
                         Cow::Borrowed(&item.attrs),
                     ),
                 )?;
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index e0bd065518b..7ab042506bd 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -6,6 +6,7 @@ use rustc_ast::{ast, ptr};
 use rustc_errors::Diagnostic;
 use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
 use rustc_span::{sym, Span};
+use thin_vec::ThinVec;
 
 use crate::attr::first_attr_value_str_by_name;
 use crate::parse::session::ParseSess;
@@ -109,7 +110,7 @@ impl<'a> Parser<'a> {
         sess: &'a ParseSess,
         path: &Path,
         span: Span,
-    ) -> Result<(ast::AttrVec, Vec<ptr::P<ast::Item>>, Span), ParserError> {
+    ) -> Result<(ast::AttrVec, ThinVec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
             let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
             match parser.parse_mod(&TokenKind::Eof) {
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 9014026b0aa..a64963db6a7 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -123,8 +123,10 @@ fn default_handler(
     let emitter = if hide_parse_errors {
         silent_emitter()
     } else {
-        let fallback_bundle =
-            rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+        let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+            rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+            false,
+        );
         Box::new(EmitterWriter::stderr(
             color_cfg,
             Some(source_map.clone()),
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 4c93f8a16b6..bddfdcfaf19 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -120,6 +120,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "dissimilar",
     "dlmalloc",
     "either",
+    "elsa",
     "ena",
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index dd2fd1911f2..c60caa0d49c 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -31,7 +31,7 @@ const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E06
 
 // Error codes that don't yet have a UI test. This list will eventually be removed.
 const IGNORE_UI_TEST_CHECK: &[&str] =
-    &["E0461", "E0465", "E0476", "E0514", "E0554", "E0640", "E0717", "E0729"];
+    &["E0461", "E0465", "E0514", "E0554", "E0640", "E0717", "E0729"];
 
 macro_rules! verbose_print {
     ($verbose:expr, $($fmt:tt)*) => {
@@ -45,7 +45,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
     let mut errors = Vec::new();
 
     // Stage 1: create list
-    let error_codes = extract_error_codes(root_path, &mut errors, verbose);
+    let error_codes = extract_error_codes(root_path, &mut errors);
     println!("Found {} error codes", error_codes.len());
     println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
 
@@ -65,18 +65,17 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
 }
 
 /// Stage 1: Parses a list of error codes from `error_codes.rs`.
-fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool) -> Vec<String> {
+fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String> {
     let path = root_path.join(Path::new(ERROR_CODES_PATH));
     let file =
         fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
 
     let mut error_codes = Vec::new();
-    let mut reached_undocumented_codes = false;
 
     for line in file.lines() {
         let line = line.trim();
 
-        if !reached_undocumented_codes && line.starts_with('E') {
+        if line.starts_with('E') {
             let split_line = line.split_once(':');
 
             // Extract the error code from the line, emitting a fatal error if it is not in a correct format.
@@ -111,23 +110,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool
             }
 
             error_codes.push(err_code);
-        } else if reached_undocumented_codes && line.starts_with('E') {
-            let err_code = match line.split_once(',') {
-                None => line,
-                Some((err_code, _)) => err_code,
-            }
-            .to_string();
-
-            verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code);
-
-            if error_codes.contains(&err_code) {
-                errors.push(format!("Found duplicate error code: `{}`", err_code));
-            }
-
-            error_codes.push(err_code);
-        } else if line == ";" {
-            // Once we reach the undocumented error codes, adapt to different syntax.
-            reached_undocumented_codes = true;
         }
     }