about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-03-17 05:22:24 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-03-17 05:22:24 +0000
commit0dff16a30ccfed16ba397c2f2dbed25475329dab (patch)
treeec40433a2b051e80ba1672eeee084b1a81bc73dd /src
parent96674fce4ce73a231bae472d4e214f034eb2c4c9 (diff)
parent872781b22697882051481a4ed7c764551a8b2cf2 (diff)
downloadrust-0dff16a30ccfed16ba397c2f2dbed25475329dab.tar.gz
rust-0dff16a30ccfed16ba397c2f2dbed25475329dab.zip
Merge from rustc
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bootstrap/configure.py2
-rw-r--r--src/bootstrap/src/bin/main.rs20
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs41
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs29
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs9
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs8
-rw-r--r--src/bootstrap/src/lib.rs49
-rw-r--r--src/bootstrap/src/utils/tarball.rs4
-rwxr-xr-x[-rw-r--r--]src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh14
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile3
-rwxr-xr-xsrc/ci/docker/run.sh41
-rw-r--r--src/doc/rustc/src/platform-support.md10
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md29
-rw-r--r--src/doc/unstable-book/src/language-features/f128.md9
-rw-r--r--src/doc/unstable-book/src/language-features/f16.md9
-rw-r--r--src/etc/gdb_providers.py9
-rw-r--r--src/etc/lldb_commands2
-rw-r--r--src/etc/lldb_providers.py13
-rw-r--r--src/etc/natvis/libcore.natvis5
-rw-r--r--src/etc/rust_types.py30
-rw-r--r--src/librustdoc/clean/inline.rs16
-rw-r--r--src/librustdoc/clean/mod.rs9
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/clean/utils.rs12
-rw-r--r--src/librustdoc/config.rs7
-rw-r--r--src/librustdoc/doctest.rs16
-rw-r--r--src/librustdoc/html/format.rs31
-rw-r--r--src/librustdoc/html/render/mod.rs14
-rw-r--r--src/librustdoc/html/render/print_item.rs62
-rw-r--r--src/librustdoc/lib.rs8
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs3
m---------src/llvm-project0
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/exit.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/self_named_constructors.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/single_call_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs22
-rw-r--r--src/tools/compiletest/src/runtest.rs51
-rw-r--r--src/tools/generate-windows-sys/Cargo.toml2
-rw-r--r--src/tools/lint-docs/src/groups.rs4
-rw-r--r--src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr4
-rw-r--r--src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr4
-rw-r--r--src/tools/opt-dist/src/bolt.rs4
-rw-r--r--src/version2
55 files changed, 383 insertions, 268 deletions
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 9c43160d455..818a7daadca 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -131,6 +131,8 @@ v("musl-root-riscv32gc", "target.riscv32gc-unknown-linux-musl.musl-root",
   "riscv32gc-unknown-linux-musl install directory")
 v("musl-root-riscv64gc", "target.riscv64gc-unknown-linux-musl.musl-root",
   "riscv64gc-unknown-linux-musl install directory")
+v("musl-root-loongarch64", "target.loongarch64-unknown-linux-musl.musl-root",
+  "loongarch64-unknown-linux-musl install directory")
 v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
   "rootfs in qemu testing, you probably don't want to use this")
 v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 070d951dba9..98495f25bc6 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -7,6 +7,7 @@
 
 use std::io::Write;
 use std::process;
+use std::str::FromStr;
 use std::{
     env,
     fs::{self, OpenOptions},
@@ -136,16 +137,25 @@ fn check_version(config: &Config) -> Option<String> {
     let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
     let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id");
 
-    if let Some(id) = config.change_id {
+    if let Some(mut id) = config.change_id {
         if id == latest_change_id {
             return None;
         }
 
-        if let Ok(last_warned_id) = fs::read_to_string(&warned_id_path) {
-            if latest_change_id.to_string() == last_warned_id {
-                return None;
+        // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
+        // then use the one from the config.toml. This way we never show the same warnings
+        // more than once.
+        if let Ok(t) = fs::read_to_string(&warned_id_path) {
+            let last_warned_id =
+                usize::from_str(&t).expect(&format!("{} is corrupted.", warned_id_path.display()));
+
+            // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
+            // Otherwise, we may retrieve all the changes if it's not the highest value.
+            // For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
+            if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
+                id = last_warned_id;
             }
-        }
+        };
 
         let changes = find_recent_config_change_ids(id);
 
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 94ea2a01a40..e927b491c71 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -231,7 +231,7 @@ impl Step for Std {
                 let target_sysroot_bin =
                     builder.sysroot_libdir(compiler, target).parent().unwrap().join("bin");
                 t!(fs::create_dir_all(&target_sysroot_bin));
-                builder.cp_r(&src_sysroot_bin, &target_sysroot_bin);
+                builder.cp_link_r(&src_sysroot_bin, &target_sysroot_bin);
             }
         }
 
@@ -307,7 +307,7 @@ fn copy_and_stamp(
     dependency_type: DependencyType,
 ) {
     let target = libdir.join(name);
-    builder.copy(&sourcedir.join(name), &target);
+    builder.copy_link(&sourcedir.join(name), &target);
 
     target_deps.push((target, dependency_type));
 }
@@ -316,7 +316,7 @@ fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &
     let libunwind_path = builder.ensure(llvm::Libunwind { target });
     let libunwind_source = libunwind_path.join("libunwind.a");
     let libunwind_target = libdir.join("libunwind.a");
-    builder.copy(&libunwind_source, &libunwind_target);
+    builder.copy_link(&libunwind_source, &libunwind_target);
     libunwind_target
 }
 
@@ -385,7 +385,7 @@ fn copy_self_contained_objects(
         for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
             let src = crt_path.join(obj);
             let target = libdir_self_contained.join(obj);
-            builder.copy(&src, &target);
+            builder.copy_link(&src, &target);
             target_deps.push((target, DependencyType::TargetSelfContained));
         }
 
@@ -418,7 +418,7 @@ fn copy_self_contained_objects(
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
             let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
             let target = libdir_self_contained.join(obj);
-            builder.copy(&src, &target);
+            builder.copy_link(&src, &target);
             target_deps.push((target, DependencyType::TargetSelfContained));
         }
     }
@@ -637,7 +637,7 @@ impl Step for StdLink {
             let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
             let sysroot_bin_dir = sysroot.join("bin");
             t!(fs::create_dir_all(&sysroot_bin_dir));
-            builder.cp_r(&stage0_bin_dir, &sysroot_bin_dir);
+            builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
 
             // Copy all *.so files from stage0/lib to stage0-sysroot/lib
             let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
@@ -646,7 +646,8 @@ impl Step for StdLink {
                     let file = t!(file);
                     let path = file.path();
                     if path.is_file() && is_dylib(&file.file_name().into_string().unwrap()) {
-                        builder.copy(&path, &sysroot.join("lib").join(path.file_name().unwrap()));
+                        builder
+                            .copy_link(&path, &sysroot.join("lib").join(path.file_name().unwrap()));
                     }
                 }
             }
@@ -661,7 +662,7 @@ impl Step for StdLink {
                 .join(host)
                 .join("codegen-backends");
             if stage0_codegen_backends.exists() {
-                builder.cp_r(&stage0_codegen_backends, &sysroot_codegen_backends);
+                builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
             }
         }
     }
@@ -684,7 +685,7 @@ fn copy_sanitizers(
 
     for runtime in &runtimes {
         let dst = libdir.join(&runtime.name);
-        builder.copy(&runtime.path, &dst);
+        builder.copy_link(&runtime.path, &dst);
 
         // The `aarch64-apple-ios-macabi` and `x86_64-apple-ios-macabi` are also supported for
         // sanitizers, but they share a sanitizer runtime with `${arch}-apple-darwin`, so we do
@@ -790,7 +791,7 @@ impl Step for StartupObjects {
             }
 
             let target = sysroot_dir.join((*file).to_string() + ".o");
-            builder.copy(dst_file, &target);
+            builder.copy_link(dst_file, &target);
             target_deps.push((target, DependencyType::Target));
         }
 
@@ -812,7 +813,7 @@ fn cp_rustc_component_to_ci_sysroot(
         if src.is_dir() {
             t!(fs::create_dir_all(dst));
         } else {
-            builder.copy(&src, &dst);
+            builder.copy_link(&src, &dst);
         }
     }
 }
@@ -1443,7 +1444,7 @@ fn copy_codegen_backends_to_sysroot(
             let dot = filename.find('.').unwrap();
             format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
         };
-        builder.copy(file, &dst.join(target_filename));
+        builder.copy_link(file, &dst.join(target_filename));
     }
 }
 
@@ -1599,7 +1600,7 @@ impl Step for Sysroot {
                 OsStr::new(std::env::consts::DLL_EXTENSION),
             ];
             let ci_rustc_dir = builder.config.ci_rustc_dir();
-            builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| {
+            builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
                 if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) {
                     return true;
                 }
@@ -1791,7 +1792,7 @@ impl Step for Assemble {
             let filename = f.file_name().into_string().unwrap();
             if (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename)
             {
-                builder.copy(&f.path(), &rustc_libdir.join(&filename));
+                builder.copy_link(&f.path(), &rustc_libdir.join(&filename));
             }
         }
 
@@ -1805,7 +1806,7 @@ impl Step for Assemble {
         if let Some(lld_install) = lld_install {
             let src_exe = exe("lld", target_compiler.host);
             let dst_exe = exe("rust-lld", target_compiler.host);
-            builder.copy(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe));
+            builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe));
             let self_contained_lld_dir = libdir_bin.join("gcc-ld");
             t!(fs::create_dir_all(&self_contained_lld_dir));
             let lld_wrapper_exe = builder.ensure(crate::core::build_steps::tool::LldWrapper {
@@ -1813,7 +1814,7 @@ impl Step for Assemble {
                 target: target_compiler.host,
             });
             for name in crate::LLD_FILE_NAMES {
-                builder.copy(
+                builder.copy_link(
                     &lld_wrapper_exe,
                     &self_contained_lld_dir.join(exe(name, target_compiler.host)),
                 );
@@ -1838,7 +1839,7 @@ impl Step for Assemble {
                     // When using `download-ci-llvm`, some of the tools
                     // may not exist, so skip trying to copy them.
                     if src_path.exists() {
-                        builder.copy(&src_path, &libdir_bin.join(&tool_exe));
+                        builder.copy_link(&src_path, &libdir_bin.join(&tool_exe));
                     }
                 }
             }
@@ -1851,7 +1852,7 @@ impl Step for Assemble {
                 extra_features: vec![],
             });
             let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
-            builder.copy(&src_path, &libdir_bin.join(&tool_exe));
+            builder.copy_link(&src_path, &libdir_bin.join(&tool_exe));
         }
 
         // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
@@ -1865,7 +1866,7 @@ impl Step for Assemble {
         let bindir = sysroot.join("bin");
         t!(fs::create_dir_all(bindir));
         let compiler = builder.rustc(target_compiler);
-        builder.copy(&rustc, &compiler);
+        builder.copy_link(&rustc, &compiler);
 
         target_compiler
     }
@@ -1891,7 +1892,7 @@ pub fn add_to_sysroot(
             DependencyType::Target => sysroot_dst,
             DependencyType::TargetSelfContained => self_contained_dst,
         };
-        builder.copy(&path, &dst.join(path.file_name().unwrap()));
+        builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
     }
 }
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 3efdfc324b8..012d64e5344 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -272,7 +272,7 @@ fn make_win_dist(
     let dist_bin_dir = rust_root.join("bin/");
     fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
     for src in rustc_dlls {
-        builder.copy_to_folder(&src, &dist_bin_dir);
+        builder.copy_link_to_folder(&src, &dist_bin_dir);
     }
 
     //Copy platform tools to platform-specific bin directory
@@ -284,7 +284,7 @@ fn make_win_dist(
         .join("self-contained");
     fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
     for src in target_tools {
-        builder.copy_to_folder(&src, &target_bin_dir);
+        builder.copy_link_to_folder(&src, &target_bin_dir);
     }
 
     // Warn windows-gnu users that the bundled GCC cannot compile C files
@@ -304,7 +304,7 @@ fn make_win_dist(
         .join("self-contained");
     fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
     for src in target_libs {
-        builder.copy_to_folder(&src, &target_lib_dir);
+        builder.copy_link_to_folder(&src, &target_lib_dir);
     }
 }
 
@@ -400,7 +400,7 @@ impl Step for Rustc {
 
             // Copy rustc binary
             t!(fs::create_dir_all(image.join("bin")));
-            builder.cp_r(&src.join("bin"), &image.join("bin"));
+            builder.cp_link_r(&src.join("bin"), &image.join("bin"));
 
             // If enabled, copy rustdoc binary
             if builder
@@ -458,13 +458,13 @@ impl Step for Rustc {
             if builder.config.lld_enabled {
                 let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
                 let rust_lld = exe("rust-lld", compiler.host);
-                builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
+                builder.copy_link(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
                 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
                 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&self_contained_lld_dst_dir));
                 for name in crate::LLD_FILE_NAMES {
                     let exe_name = exe(name, compiler.host);
-                    builder.copy(
+                    builder.copy_link(
                         &self_contained_lld_src_dir.join(&exe_name),
                         &self_contained_lld_dst_dir.join(&exe_name),
                     );
@@ -609,9 +609,9 @@ fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path
     t!(fs::create_dir_all(&self_contained_dst));
     for (path, dependency_type) in builder.read_stamp_file(stamp) {
         if dependency_type == DependencyType::TargetSelfContained {
-            builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
+            builder.copy_link(&path, &self_contained_dst.join(path.file_name().unwrap()));
         } else if dependency_type == DependencyType::Target || builder.config.build == target {
-            builder.copy(&path, &dst.join(path.file_name().unwrap()));
+            builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
         }
     }
 }
@@ -865,7 +865,8 @@ fn copy_src_dirs(
     for item in src_dirs {
         let dst = &dst_dir.join(item);
         t!(fs::create_dir_all(dst));
-        builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
+        builder
+            .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
     }
 }
 
@@ -923,7 +924,7 @@ impl Step for Src {
             &dst_src,
         );
         for file in src_files.iter() {
-            builder.copy(&builder.src.join(file), &dst_src.join(file));
+            builder.copy_link(&builder.src.join(file), &dst_src.join(file));
         }
 
         tarball.generate()
@@ -979,7 +980,7 @@ impl Step for PlainSourceTarball {
 
         // Copy the files normally
         for item in &src_files {
-            builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
+            builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item));
         }
 
         // Create the version file
@@ -1608,7 +1609,7 @@ impl Step for Extended {
 
             let prepare = |name: &str| {
                 builder.create_dir(&pkg.join(name));
-                builder.cp_r(
+                builder.cp_link_r(
                     &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
                     &pkg.join(name),
                 );
@@ -1672,7 +1673,7 @@ impl Step for Extended {
                 } else {
                     name.to_string()
                 };
-                builder.cp_r(
+                builder.cp_link_r(
                     &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
                     &exe.join(name),
                 );
@@ -2040,7 +2041,7 @@ fn install_llvm_file(
         if install_symlink {
             // For download-ci-llvm, also install the symlink, to match what LLVM does. Using a
             // symlink is fine here, as this is not a rustup component.
-            builder.copy(&source, &full_dest);
+            builder.copy_link(&source, &full_dest);
         } else {
             // Otherwise, replace the symlink with an equivalent linker script. This is used when
             // projects like miri link against librustc_driver.so. We don't use a symlink, as
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 1d4d9d4c2e1..51b5cdc0565 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -520,7 +520,10 @@ impl Step for SharedAssets {
             t!(fs::write(&version_info, info));
         }
 
-        builder.copy(&builder.src.join("src").join("doc").join("rust.css"), &out.join("rust.css"));
+        builder.copy_link(
+            &builder.src.join("src").join("doc").join("rust.css"),
+            &out.join("rust.css"),
+        );
 
         SharedAssetsPaths { version_info }
     }
@@ -718,7 +721,7 @@ fn doc_std(
     let _guard = builder.msg_doc(compiler, description, target);
 
     builder.run(&mut cargo.into());
-    builder.cp_r(&out_dir, out);
+    builder.cp_link_r(&out_dir, out);
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -1151,7 +1154,7 @@ impl Step for RustcBook {
         let out_base = builder.md_doc_out(self.target).join("rustc");
         t!(fs::create_dir_all(&out_base));
         let out_listing = out_base.join("src/lints");
-        builder.cp_r(&builder.src.join("src/doc/rustc"), &out_base);
+        builder.cp_link_r(&builder.src.join("src/doc/rustc"), &out_base);
         builder.info(&format!("Generating lint docs ({})", self.target));
 
         let rustc = builder.rustc(self.compiler);
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index e9e2a881d11..690e20fb6b9 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1367,7 +1367,7 @@ impl Step for RunMakeSupport {
 
         let cargo_out =
             builder.cargo_out(self.compiler, Mode::ToolStd, self.target).join(&lib_name);
-        builder.copy(&cargo_out, &lib);
+        builder.copy_link(&cargo_out, &lib);
         lib
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 53dc1cff0ae..3c200112103 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -127,7 +127,7 @@ impl Step for ToolBuild {
             }
             let cargo_out = builder.cargo_out(compiler, self.mode, target).join(exe(tool, target));
             let bin = builder.tools_dir(compiler).join(exe(tool, target));
-            builder.copy(&cargo_out, &bin);
+            builder.copy_link(&cargo_out, &bin);
             bin
         }
     }
@@ -507,7 +507,7 @@ impl Step for Rustdoc {
             t!(fs::create_dir_all(&bindir));
             let bin_rustdoc = bindir.join(exe("rustdoc", target_compiler.host));
             let _ = fs::remove_file(&bin_rustdoc);
-            builder.copy(&tool_rustdoc, &bin_rustdoc);
+            builder.copy_link(&tool_rustdoc, &bin_rustdoc);
             bin_rustdoc
         } else {
             tool_rustdoc
@@ -686,7 +686,7 @@ impl Step for RustAnalyzerProcMacroSrv {
         // so that r-a can use it.
         let libexec_path = builder.sysroot(self.compiler).join("libexec");
         t!(fs::create_dir_all(&libexec_path));
-        builder.copy(&path, &libexec_path.join("rust-analyzer-proc-macro-srv"));
+        builder.copy_link(&path, &libexec_path.join("rust-analyzer-proc-macro-srv"));
 
         Some(path)
     }
@@ -765,7 +765,7 @@ macro_rules! tool_extended {
                     $(for add_bin in $add_bins_to_sysroot {
                         let bin_source = tools_out.join(exe(add_bin, $sel.target));
                         let bin_destination = bindir.join(exe(add_bin, $sel.compiler.host));
-                        $builder.copy(&bin_source, &bin_destination);
+                        $builder.copy_link(&bin_source, &bin_destination);
                     })?
 
                     let tool = bindir.join(exe($tool_name, $sel.compiler.host));
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 85211aabb74..f0fe994d155 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -1646,16 +1646,19 @@ impl Build {
         paths
     }
 
-    /// Copies a file from `src` to `dst`
-    pub fn copy(&self, src: &Path, dst: &Path) {
-        self.copy_internal(src, dst, false);
+    /// Links a file from `src` to `dst`.
+    /// Attempts to use hard links if possible, falling back to copying.
+    /// You can neither rely on this being a copy nor it being a link,
+    /// so do not write to dst.
+    pub fn copy_link(&self, src: &Path, dst: &Path) {
+        self.copy_link_internal(src, dst, false);
     }
 
-    fn copy_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
+    fn copy_link_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
         if self.config.dry_run() {
             return;
         }
-        self.verbose_than(1, || println!("Copy {src:?} to {dst:?}"));
+        self.verbose_than(1, || println!("Copy/Link {src:?} to {dst:?}"));
         if src == dst {
             return;
         }
@@ -1686,9 +1689,10 @@ impl Build {
         }
     }
 
-    /// Copies the `src` directory recursively to `dst`. Both are assumed to exist
+    /// Links the `src` directory recursively to `dst`. Both are assumed to exist
     /// when this function is called.
-    pub fn cp_r(&self, src: &Path, dst: &Path) {
+    /// Will attempt to use hard links if possible and fall back to copying.
+    pub fn cp_link_r(&self, src: &Path, dst: &Path) {
         if self.config.dry_run() {
             return;
         }
@@ -1698,24 +1702,31 @@ impl Build {
             let dst = dst.join(name);
             if t!(f.file_type()).is_dir() {
                 t!(fs::create_dir_all(&dst));
-                self.cp_r(&path, &dst);
+                self.cp_link_r(&path, &dst);
             } else {
-                let _ = fs::remove_file(&dst);
-                self.copy(&path, &dst);
+                self.copy_link(&path, &dst);
             }
         }
     }
 
     /// Copies the `src` directory recursively to `dst`. Both are assumed to exist
-    /// when this function is called. Unwanted files or directories can be skipped
+    /// when this function is called.
+    /// Will attempt to use hard links if possible and fall back to copying.
+    /// Unwanted files or directories can be skipped
     /// by returning `false` from the filter function.
-    pub fn cp_filtered(&self, src: &Path, dst: &Path, filter: &dyn Fn(&Path) -> bool) {
+    pub fn cp_link_filtered(&self, src: &Path, dst: &Path, filter: &dyn Fn(&Path) -> bool) {
         // Immediately recurse with an empty relative path
-        self.recurse_(src, dst, Path::new(""), filter)
+        self.cp_link_filtered_recurse(src, dst, Path::new(""), filter)
     }
 
     // Inner function does the actual work
-    fn recurse_(&self, src: &Path, dst: &Path, relative: &Path, filter: &dyn Fn(&Path) -> bool) {
+    fn cp_link_filtered_recurse(
+        &self,
+        src: &Path,
+        dst: &Path,
+        relative: &Path,
+        filter: &dyn Fn(&Path) -> bool,
+    ) {
         for f in self.read_dir(src) {
             let path = f.path();
             let name = path.file_name().unwrap();
@@ -1726,19 +1737,19 @@ impl Build {
                 if t!(f.file_type()).is_dir() {
                     let _ = fs::remove_dir_all(&dst);
                     self.create_dir(&dst);
-                    self.recurse_(&path, &dst, &relative, filter);
+                    self.cp_link_filtered_recurse(&path, &dst, &relative, filter);
                 } else {
                     let _ = fs::remove_file(&dst);
-                    self.copy(&path, &dst);
+                    self.copy_link(&path, &dst);
                 }
             }
         }
     }
 
-    fn copy_to_folder(&self, src: &Path, dest_folder: &Path) {
+    fn copy_link_to_folder(&self, src: &Path, dest_folder: &Path) {
         let file_name = src.file_name().unwrap();
         let dest = dest_folder.join(file_name);
-        self.copy(src, &dest);
+        self.copy_link(src, &dest);
     }
 
     fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
@@ -1751,7 +1762,7 @@ impl Build {
         if !src.exists() {
             panic!("ERROR: File \"{}\" not found!", src.display());
         }
-        self.copy_internal(src, &dst, true);
+        self.copy_link_internal(src, &dst, true);
         chmod(&dst, perms);
     }
 
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 03f56cba29d..4f99079a57f 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -197,7 +197,7 @@ impl<'a> Tarball<'a> {
     ) {
         let destdir = self.image_dir.join(destdir.as_ref());
         t!(std::fs::create_dir_all(&destdir));
-        self.builder.copy(src.as_ref(), &destdir.join(new_name));
+        self.builder.copy_link(src.as_ref(), &destdir.join(new_name));
     }
 
     pub(crate) fn add_legal_and_readme_to(&self, destdir: impl AsRef<Path>) {
@@ -210,7 +210,7 @@ impl<'a> Tarball<'a> {
         let dest = self.image_dir.join(dest.as_ref());
 
         t!(std::fs::create_dir_all(&dest));
-        self.builder.cp_r(src.as_ref(), &dest);
+        self.builder.cp_link_r(src.as_ref(), &dest);
     }
 
     pub(crate) fn add_bulk_dir(&mut self, src: impl AsRef<Path>, dest: impl AsRef<Path>) {
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh
index 324dd5fac16..b22d60f2b1d 100644..100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh
@@ -1,9 +1,11 @@
-#!/bin/sh
+#!/usr/bin/env bash
 
 set -ex
 
 cd $1
 
+source shared.sh
+
 # Setting up folders for GCC
 git clone https://github.com/antoyo/gcc gcc-src
 cd gcc-src
@@ -14,15 +16,17 @@ mkdir ../gcc-build ../gcc-install
 cd ../gcc-build
 
 # Building GCC.
-../gcc-src/configure \
+hide_output \
+  ../gcc-src/configure \
     --enable-host-shared \
     --enable-languages=jit \
     --enable-checking=release \
     --disable-bootstrap \
     --disable-multilib \
-    --prefix=$(pwd)/../gcc-install
-make
-make install
+    --prefix=$(pwd)/../gcc-install \
+
+hide_output make -j$(nproc)
+hide_output make install
 
 rm -rf ../gcc-src
 ln -s /scripts/gcc-install/lib/libgccjit.so /usr/lib/x86_64-linux-gnu/libgccjit.so
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 30d3a52d82b..e5aa81d83d5 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -41,6 +41,10 @@ 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 && \
+           # Check library crates on all tier 1 targets.
+           # We disable optimized compiler built-ins because that requires a C toolchain for the target.
+           # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs.
+           python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            python3 ../x.py clippy compiler -Aclippy::all -Dclippy::correctness && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
index 6540a500d3a..4fc2b2e507e 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
@@ -59,8 +59,9 @@ ENV RUST_CONFIGURE_ARGS \
 
 COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/
 
+COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
 COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
 
-RUN sh /scripts/build-gccjit.sh /scripts
+RUN /scripts/build-gccjit.sh /scripts
 
 ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
index ed4e1978c5d..7c2ecd198e2 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
@@ -58,8 +58,9 @@ ENV RUST_CONFIGURE_ARGS \
 
 COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/
 
+COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
 COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
 
-RUN sh /scripts/build-gccjit.sh /scripts
+RUN /scripts/build-gccjit.sh /scripts
 
 ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index a03577b4511..6f720569898 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -95,9 +95,10 @@ ENV RUST_CONFIGURE_ARGS \
 
 ENV HOST_TARGET x86_64-unknown-linux-gnu
 
+COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
 COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
 
-RUN sh /scripts/build-gccjit.sh /scripts
+RUN /scripts/build-gccjit.sh /scripts
 
 ENV SCRIPT /tmp/checktools.sh ../x.py && \
   NODE_PATH=`npm root -g` python3 ../x.py test tests/rustdoc-gui --stage 2 \
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index bd5447ac835..740eb7504f8 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -92,21 +92,38 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
     # Print docker version
     docker --version
 
-    # On non-CI or PR jobs, we don't have permissions to write to the registry cache, so we should
-    # not use `docker login` nor caching.
-    if [[ "$CI" == "" ]] || [[ "$PR_CI_JOB" == "1" ]];
+    REGISTRY=ghcr.io
+    # PR CI runs on rust-lang, but we want to use the cache from rust-lang-ci
+    REGISTRY_USERNAME=rust-lang-ci
+    # Tag used to push the final Docker image, so that it can be pulled by e.g. rustup
+    IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci:${cksum}
+    # Tag used to cache the Docker build
+    # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
+    CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
+
+    # On non-CI jobs, we don't do any caching.
+    if [[ "$CI" == "" ]];
     then
         retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
-    else
-        REGISTRY=ghcr.io
-        # Most probably rust-lang-ci, but in general the owner of the repository where CI runs
-        REGISTRY_USERNAME=${GITHUB_REPOSITORY_OWNER}
-        # Tag used to push the final Docker image, so that it can be pulled by e.g. rustup
-        IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci:${cksum}
-        # Tag used to cache the Docker build
-        # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
-        CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
+    # On PR CI jobs, we don't have permissions to write to the registry cache,
+    # but we can still read from it.
+    elif [[ "$PR_CI_JOB" == "1" ]];
+    then
+        # Enable a new Docker driver so that --cache-from works with a registry backend
+        docker buildx create --use --driver docker-container
 
+        # Build the image using registry caching backend
+        retry docker \
+          buildx \
+          build \
+          --rm \
+          -t rust-ci \
+          -f "$dockerfile" \
+          --cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
+          --output=type=docker \
+          "$context"
+    # On auto/try builds, we can also write to the cache.
+    else
         # Log into the Docker registry, so that we can read/write cache and the final image
         echo ${DOCKER_TOKEN} | docker login ${REGISTRY} \
             --username ${REGISTRY_USERNAME} \
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 285c773afa2..2ebbf5e15e6 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -33,16 +33,14 @@ All tier 1 targets with host tools support the full standard library.
 target | notes
 -------|-------
 `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+)
-`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+) [^windows-support] [^x86_32-floats-return-ABI]
-`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+) [^windows-support] [^x86_32-floats-return-ABI]
+`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+) [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+) [^x86_32-floats-return-ABI]
 `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]
 `x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+)
-`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+) [^windows-support]
-`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+) [^windows-support]
+`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+)
+`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+)
 `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+)
 
-[^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community.
-
 [^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue].
 
 [77071]: https://github.com/rust-lang/rust/issues/77071
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index b46d80eb362..fe5cb529c26 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -427,3 +427,32 @@ This flag is **deprecated** and **has no effect**.
 Rustdoc only supports Rust source code and Markdown input formats. If the
 file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
 Otherwise, it assumes that the input file is Rust.
+
+## `--test-builder`: `rustc`-like program to build tests
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc --test-builder /path/to/rustc src/lib.rs
+```
+
+Rustdoc will use the provided program to compile tests instead of the default `rustc` program from
+the sysroot.
+
+## `--test-builder-wrapper`: wrap calls to the test builder
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs
+$ rustdoc \
+    --test-builder-wrapper rustc-wrapper1 \
+    --test-builder-wrapper rustc-wrapper2 \
+    --test-builder rustc \
+    src/lib.rs
+```
+
+Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper program.
+The first argument to the program will be the test builder program.
+
+This flag can be passed multiple times to nest wrappers.
diff --git a/src/doc/unstable-book/src/language-features/f128.md b/src/doc/unstable-book/src/language-features/f128.md
new file mode 100644
index 00000000000..0cc5f677230
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/f128.md
@@ -0,0 +1,9 @@
+# `f128`
+
+The tracking issue for this feature is: [#116909]
+
+[#116909]: https://github.com/rust-lang/rust/issues/116909
+
+---
+
+Enable the `f128` type for  IEEE 128-bit floating numbers (quad precision).
diff --git a/src/doc/unstable-book/src/language-features/f16.md b/src/doc/unstable-book/src/language-features/f16.md
new file mode 100644
index 00000000000..efb07a5146d
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/f16.md
@@ -0,0 +1,9 @@
+# `f16`
+
+The tracking issue for this feature is: [#116909]
+
+[#116909]: https://github.com/rust-lang/rust/issues/116909
+
+---
+
+Enable the `f16` type for  IEEE 16-bit floating numbers (half precision).
diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py
index 7d7277d2408..227695cdadd 100644
--- a/src/etc/gdb_providers.py
+++ b/src/etc/gdb_providers.py
@@ -245,7 +245,14 @@ class StdNonZeroNumberProvider(printer_base):
         fields = valobj.type.fields()
         assert len(fields) == 1
         field = list(fields)[0]
-        self._value = str(valobj[field.name])
+
+        inner_valobj = valobj[field.name]
+
+        inner_fields = inner_valobj.type.fields()
+        assert len(inner_fields) == 1
+        inner_field = list(inner_fields)[0]
+
+        self._value = str(inner_valobj[inner_field.name])
 
     def to_string(self):
         return self._value
diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands
index ed66ecf3072..615d13ccd0f 100644
--- a/src/etc/lldb_commands
+++ b/src/etc/lldb_commands
@@ -15,5 +15,5 @@ type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)C
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
-type summary add -F lldb_lookup.summary_lookup  -e -x -h "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
 type category enable Rust
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index cfb3f0a4eae..5d2b6fd525c 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -743,7 +743,12 @@ class StdRefSyntheticProvider:
 
 def StdNonZeroNumberSummaryProvider(valobj, _dict):
     # type: (SBValue, dict) -> str
-    objtype = valobj.GetType()
-    field = objtype.GetFieldAtIndex(0)
-    element = valobj.GetChildMemberWithName(field.name)
-    return element.GetValue()
+    inner = valobj.GetChildAtIndex(0)
+    inner_inner = inner.GetChildAtIndex(0)
+
+    # FIXME: Avoid printing as character literal,
+    #        see https://github.com/llvm/llvm-project/issues/65076.
+    if inner_inner.GetTypeName() in ['char', 'unsigned char']:
+      return str(inner_inner.GetValueAsSigned())
+    else:
+      return inner_inner.GetValue()
diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis
index 5e0c21a13a9..8a441cf2093 100644
--- a/src/etc/natvis/libcore.natvis
+++ b/src/etc/natvis/libcore.natvis
@@ -42,7 +42,10 @@
   </Type>
 
   <Type Name="core::num::nonzero::NonZero&lt;*&gt;">
-    <DisplayString>{__0}</DisplayString>
+    <DisplayString>{__0.__0}</DisplayString>
+    <Expand>
+      <ExpandedItem>__0.__0</ExpandedItem>
+    </Expand>
   </Type>
 
   <Type Name="core::num::wrapping::Wrapping&lt;*&gt;">
diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py
index bf512bc99b8..2b06683ef93 100644
--- a/src/etc/rust_types.py
+++ b/src/etc/rust_types.py
@@ -34,23 +34,23 @@ class RustType(object):
     STD_NONZERO_NUMBER = "StdNonZeroNumber"
 
 
-STD_STRING_REGEX = re.compile(r"^(alloc::(\w+::)+)String$")
+STD_STRING_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)String$")
 STD_STR_REGEX = re.compile(r"^&(mut )?str$")
 STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.+\]$")
-STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::(\w+::)+)OsString$")
-STD_VEC_REGEX = re.compile(r"^(alloc::(\w+::)+)Vec<.+>$")
-STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::(\w+::)+)VecDeque<.+>$")
-STD_BTREE_SET_REGEX = re.compile(r"^(alloc::(\w+::)+)BTreeSet<.+>$")
-STD_BTREE_MAP_REGEX = re.compile(r"^(alloc::(\w+::)+)BTreeMap<.+>$")
-STD_HASH_MAP_REGEX = re.compile(r"^(std::collections::(\w+::)+)HashMap<.+>$")
-STD_HASH_SET_REGEX = re.compile(r"^(std::collections::(\w+::)+)HashSet<.+>$")
-STD_RC_REGEX = re.compile(r"^(alloc::(\w+::)+)Rc<.+>$")
-STD_ARC_REGEX = re.compile(r"^(alloc::(\w+::)+)Arc<.+>$")
-STD_CELL_REGEX = re.compile(r"^(core::(\w+::)+)Cell<.+>$")
-STD_REF_REGEX = re.compile(r"^(core::(\w+::)+)Ref<.+>$")
-STD_REF_MUT_REGEX = re.compile(r"^(core::(\w+::)+)RefMut<.+>$")
-STD_REF_CELL_REGEX = re.compile(r"^(core::(\w+::)+)RefCell<.+>$")
-STD_NONZERO_NUMBER_REGEX = re.compile(r"^core::num::([a-z_]+::)*NonZero.+$")
+STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::([a-z_]+::)+)OsString$")
+STD_VEC_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)Vec<.+>$")
+STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)VecDeque<.+>$")
+STD_BTREE_SET_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)BTreeSet<.+>$")
+STD_BTREE_MAP_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)BTreeMap<.+>$")
+STD_HASH_MAP_REGEX = re.compile(r"^(std::collections::([a-z_]+::)+)HashMap<.+>$")
+STD_HASH_SET_REGEX = re.compile(r"^(std::collections::([a-z_]+::)+)HashSet<.+>$")
+STD_RC_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)Rc<.+>$")
+STD_ARC_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)Arc<.+>$")
+STD_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)Cell<.+>$")
+STD_REF_REGEX = re.compile(r"^(core::([a-z_]+::)+)Ref<.+>$")
+STD_REF_MUT_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefMut<.+>$")
+STD_REF_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefCell<.+>$")
+STD_NONZERO_NUMBER_REGEX = re.compile(r"^(core::([a-z_]+::)+)NonZero<.+>$")
 
 TUPLE_ITEM_REGEX = re.compile(r"__\d+$")
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 77a78f57e95..6f86c6450d9 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -62,6 +62,9 @@ pub(crate) fn try_inline(
         attrs_without_docs.as_ref().map(|(attrs, def_id)| (&attrs[..], *def_id));
 
     let import_def_id = attrs.and_then(|(_, def_id)| def_id);
+
+    let (attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs);
+
     let kind = match res {
         Res::Def(DefKind::Trait, did) => {
             record_extern_fqn(cx, did, ItemType::Trait);
@@ -131,7 +134,7 @@ pub(crate) fn try_inline(
             cx.with_param_env(did, |cx| clean::ConstantItem(build_const(cx, did)))
         }
         Res::Def(DefKind::Macro(kind), did) => {
-            let mac = build_macro(cx, did, name, import_def_id, kind);
+            let mac = build_macro(cx, did, name, import_def_id, kind, attrs.is_doc_hidden());
 
             let type_kind = match kind {
                 MacroKind::Bang => ItemType::Macro,
@@ -144,7 +147,6 @@ pub(crate) fn try_inline(
         _ => return None,
     };
 
-    let (attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs);
     cx.inlined.insert(did.into());
     let mut item =
         clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, Box::new(attrs), cfg);
@@ -751,6 +753,7 @@ fn build_macro(
     name: Symbol,
     import_def_id: Option<DefId>,
     macro_kind: MacroKind,
+    is_doc_hidden: bool,
 ) -> clean::ItemKind {
     match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
         LoadedMacro::MacroDef(item_def, _) => match macro_kind {
@@ -758,7 +761,14 @@ fn build_macro(
                 if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
                     let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id));
                     clean::MacroItem(clean::Macro {
-                        source: utils::display_macro_source(cx, name, def, def_id, vis),
+                        source: utils::display_macro_source(
+                            cx,
+                            name,
+                            def,
+                            def_id,
+                            vis,
+                            is_doc_hidden,
+                        ),
                     })
                 } else {
                     unreachable!()
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b32d3ad562d..dfc026fe50b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -149,8 +149,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
 }
 
 fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool {
-    if let Some(node) = tcx.opt_hir_node_by_def_id(import_id)
-        && let hir::Node::Item(item) = node
+    if let hir::Node::Item(item) = tcx.hir_node_by_def_id(import_id)
         && let hir::ItemKind::Use(_, use_kind) = item.kind
     {
         use_kind == hir::UseKind::Glob
@@ -1612,8 +1611,7 @@ fn first_non_private<'tcx>(
             'reexps: for reexp in child.reexport_chain.iter() {
                 if let Some(use_def_id) = reexp.id()
                     && let Some(local_use_def_id) = use_def_id.as_local()
-                    && let Some(hir::Node::Item(item)) =
-                        cx.tcx.opt_hir_node_by_def_id(local_use_def_id)
+                    && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id)
                     && !item.ident.name.is_empty()
                     && let hir::ItemKind::Use(path, _) = item.kind
                 {
@@ -2796,7 +2794,8 @@ fn clean_maybe_renamed_item<'tcx>(
             ItemKind::Macro(ref macro_def, MacroKind::Bang) => {
                 let ty_vis = cx.tcx.visibility(def_id);
                 MacroItem(Macro {
-                    source: display_macro_source(cx, name, macro_def, def_id, ty_vis),
+                    // FIXME this shouldn't be false
+                    source: display_macro_source(cx, name, macro_def, def_id, ty_vis, false),
                 })
             }
             ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index c35baeb4cf5..a51f6360df2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1161,7 +1161,7 @@ impl Attributes {
         false
     }
 
-    fn is_doc_hidden(&self) -> bool {
+    pub(crate) fn is_doc_hidden(&self) -> bool {
         self.has_doc_flag(sym::hidden)
     }
 
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 57916ff0ff7..0b20cca3bca 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -625,6 +625,7 @@ pub(super) fn display_macro_source(
     def: &ast::MacroDef,
     def_id: DefId,
     vis: ty::Visibility<DefId>,
+    is_doc_hidden: bool,
 ) -> String {
     // Extract the spans of all matchers. They represent the "interface" of the macro.
     let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
@@ -635,7 +636,7 @@ pub(super) fn display_macro_source(
         if matchers.len() <= 1 {
             format!(
                 "{vis}macro {name}{matchers} {{\n    ...\n}}",
-                vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
+                vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
                 matchers = matchers
                     .map(|matcher| render_macro_matcher(cx.tcx, matcher))
                     .collect::<String>(),
@@ -643,7 +644,7 @@ pub(super) fn display_macro_source(
         } else {
             format!(
                 "{vis}macro {name} {{\n{arms}}}",
-                vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
+                vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
                 arms = render_macro_arms(cx.tcx, matchers, ","),
             )
         }
@@ -664,9 +665,10 @@ pub(crate) fn inherits_doc_hidden(
         def_id = id;
         if tcx.is_doc_hidden(def_id.to_def_id()) {
             return true;
-        } else if let Some(node) = tcx.opt_hir_node_by_def_id(def_id)
-            && matches!(node, hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),)
-        {
+        } else if matches!(
+            tcx.hir_node_by_def_id(def_id),
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. })
+        ) {
             // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly
             // on them, they don't inherit it from the parent context.
             return false;
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 4b1a417b211..be7e319bc79 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -130,6 +130,9 @@ pub(crate) struct Options {
     /// default to loading from `$sysroot/bin/rustc`.
     pub(crate) test_builder: Option<PathBuf>,
 
+    /// Run these wrapper instead of rustc directly
+    pub(crate) test_builder_wrappers: Vec<PathBuf>,
+
     // Options that affect the documentation process
     /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
     /// with and without documentation.
@@ -204,6 +207,7 @@ impl fmt::Debug for Options {
             .field("enable-per-target-ignores", &self.enable_per_target_ignores)
             .field("run_check", &self.run_check)
             .field("no_run", &self.no_run)
+            .field("test_builder_wrappers", &self.test_builder_wrappers)
             .field("nocapture", &self.nocapture)
             .field("scrape_examples_options", &self.scrape_examples_options)
             .field("unstable_features", &self.unstable_features)
@@ -521,6 +525,8 @@ impl Options {
             dcx.fatal("the `--test` flag must be passed to enable `--no-run`");
         }
 
+        let test_builder_wrappers =
+            matches.opt_strs("test-builder-wrapper").iter().map(PathBuf::from).collect();
         let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s));
         let output = matches.opt_str("output").map(|s| PathBuf::from(&s));
         let output = match (out_dir, output) {
@@ -727,6 +733,7 @@ impl Options {
             test_builder,
             run_check,
             no_run,
+            test_builder_wrappers,
             nocapture,
             crate_name,
             output_format,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index d446b781bf1..c6eb7be08cd 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -25,7 +25,7 @@ use tempfile::Builder as TempFileBuilder;
 use std::env;
 use std::io::{self, Write};
 use std::panic;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::{self, Command, Stdio};
 use std::str;
 use std::sync::atomic::{AtomicUsize, Ordering};
@@ -306,6 +306,18 @@ fn add_exe_suffix(input: String, target: &TargetTriple) -> String {
     input + &exe_suffix
 }
 
+fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command {
+    let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary].into_iter());
+
+    let exe = args.next().expect("unable to create rustc command");
+    let mut command = Command::new(exe);
+    for arg in args {
+        command.arg(arg);
+    }
+
+    command
+}
+
 fn run_test(
     test: &str,
     crate_name: &str,
@@ -334,7 +346,7 @@ fn run_test(
         .test_builder
         .as_deref()
         .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
-    let mut compiler = Command::new(&rustc_binary);
+    let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
     compiler.arg("--crate-type").arg("bin");
     for cfg in &rustdoc_options.cfgs {
         compiler.arg("--cfg").arg(&cfg);
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index afd5eb42d01..312765d3e6d 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -29,8 +29,7 @@ use rustc_target::spec::abi::Abi;
 use itertools::Itertools;
 
 use crate::clean::{
-    self, types::ExternalLocation, utils::find_nearest_parent_module, ExternalCrate, ItemId,
-    PrimitiveType,
+    self, types::ExternalLocation, utils::find_nearest_parent_module, ExternalCrate, PrimitiveType,
 };
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
@@ -1506,20 +1505,18 @@ impl clean::FnDecl {
 }
 
 pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
-    visibility: Option<ty::Visibility<DefId>>,
-    item_did: ItemId,
+    item: &clean::Item,
     cx: &'a Context<'tcx>,
 ) -> impl Display + 'a + Captures<'tcx> {
     use std::fmt::Write as _;
-
-    let to_print: Cow<'static, str> = match visibility {
+    let vis: Cow<'static, str> = match item.visibility(cx.tcx()) {
         None => "".into(),
         Some(ty::Visibility::Public) => "pub ".into(),
         Some(ty::Visibility::Restricted(vis_did)) => {
             // FIXME(camelid): This may not work correctly if `item_did` is a module.
             //                 However, rustdoc currently never displays a module's
             //                 visibility, so it shouldn't matter.
-            let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id());
+            let parent_module = find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id());
 
             if vis_did.is_crate_root() {
                 "pub(crate) ".into()
@@ -1547,7 +1544,15 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
             }
         }
     };
-    display_fn(move |f| f.write_str(&to_print))
+
+    let is_doc_hidden = item.is_doc_hidden();
+    display_fn(move |f| {
+        if is_doc_hidden {
+            f.write_str("#[doc(hidden)] ")?;
+        }
+
+        f.write_str(&vis)
+    })
 }
 
 /// This function is the same as print_with_space, except that it renders no links.
@@ -1557,8 +1562,9 @@ pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>(
     visibility: Option<ty::Visibility<DefId>>,
     tcx: TyCtxt<'tcx>,
     item_did: DefId,
+    is_doc_hidden: bool,
 ) -> impl Display + 'a + Captures<'tcx> {
-    let to_print: Cow<'static, str> = match visibility {
+    let vis: Cow<'static, str> = match visibility {
         None => "".into(),
         Some(ty::Visibility::Public) => "pub ".into(),
         Some(ty::Visibility::Restricted(vis_did)) => {
@@ -1582,7 +1588,12 @@ pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>(
             }
         }
     };
-    display_fn(move |f| f.write_str(&to_print))
+    display_fn(move |f| {
+        if is_doc_hidden {
+            f.write_str("#[doc(hidden)] ")?;
+        }
+        f.write_str(&vis)
+    })
 }
 
 pub(crate) trait PrintWithSpace {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index fe83095f944..6c5040414bc 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -883,7 +883,7 @@ fn assoc_const(
         w,
         "{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
         indent = " ".repeat(indent),
-        vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+        vis = visibility_print_with_space(it, cx),
         href = assoc_href_attr(it, link, cx),
         name = it.name.as_ref().unwrap(),
         generics = generics.print(cx),
@@ -912,12 +912,11 @@ fn assoc_type(
     indent: usize,
     cx: &Context<'_>,
 ) {
-    let tcx = cx.tcx();
     write!(
         w,
         "{indent}{vis}type <a{href} class=\"associatedtype\">{name}</a>{generics}",
         indent = " ".repeat(indent),
-        vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+        vis = visibility_print_with_space(it, cx),
         href = assoc_href_attr(it, link, cx),
         name = it.name.as_ref().unwrap(),
         generics = generics.print(cx),
@@ -945,7 +944,7 @@ fn assoc_method(
     let tcx = cx.tcx();
     let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item");
     let name = meth.name.as_ref().unwrap();
-    let vis = visibility_print_with_space(meth.visibility(tcx), meth.item_id, cx).to_string();
+    let vis = visibility_print_with_space(meth, cx).to_string();
     let defaultness = print_default_space(meth.is_default());
     // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
     // this condition.
@@ -1698,9 +1697,10 @@ fn render_impl(
                     let id = cx.derive_id(format!("{item_type}.{name}"));
                     let source_id = trait_
                         .and_then(|trait_| {
-                            trait_.items.iter().find(|item| {
-                                item.name.map(|n| n.as_str().eq(name.as_str())).unwrap_or(false)
-                            })
+                            trait_
+                                .items
+                                .iter()
+                                .find(|item| item.name.map(|n| n == *name).unwrap_or(false))
                         })
                         .map(|item| format!("{}.{name}", item.type_()));
                     write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index d588f219739..5d4f1acc4b1 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -445,14 +445,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                     Some(src) => write!(
                         w,
                         "<div class=\"item-name\"><code>{}extern crate {} as {};",
-                        visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx),
+                        visibility_print_with_space(myitem, cx),
                         anchor(myitem.item_id.expect_def_id(), src, cx),
                         myitem.name.unwrap(),
                     ),
                     None => write!(
                         w,
                         "<div class=\"item-name\"><code>{}extern crate {};",
-                        visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx),
+                        visibility_print_with_space(myitem, cx),
                         anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx),
                     ),
                 }
@@ -491,7 +491,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                          <code>{vis}{imp}</code>\
                      </div>\
                      {stab_tags_before}{stab_tags}{stab_tags_after}",
-                    vis = visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx),
+                    vis = visibility_print_with_space(myitem, cx),
                     imp = import.print(cx),
                 );
                 w.write_str(ITEM_TABLE_ROW_CLOSE);
@@ -511,10 +511,16 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                     _ => "",
                 };
 
-                let visibility_emoji = match myitem.visibility(tcx) {
+                let visibility_and_hidden = match myitem.visibility(tcx) {
                     Some(ty::Visibility::Restricted(_)) => {
-                        "<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
+                        if myitem.is_doc_hidden() {
+                            // Don't separate with a space when there are two of them
+                            "<span title=\"Restricted Visibility\">&nbsp;🔒</span><span title=\"Hidden item\">👻</span> "
+                        } else {
+                            "<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
+                        }
                     }
+                    _ if myitem.is_doc_hidden() => "<span title=\"Hidden item\">&nbsp;👻</span> ",
                     _ => "",
                 };
 
@@ -530,13 +536,13 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                     w,
                     "<div class=\"item-name\">\
                         <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
-                        {visibility_emoji}\
+                        {visibility_and_hidden}\
                         {unsafety_flag}\
                         {stab_tags}\
                      </div>\
                      {docs_before}{docs}{docs_after}",
                     name = myitem.name.unwrap(),
-                    visibility_emoji = visibility_emoji,
+                    visibility_and_hidden = visibility_and_hidden,
                     stab_tags = extra_info_tags(myitem, item, tcx),
                     class = myitem.type_(),
                     unsafety_flag = unsafety_flag,
@@ -625,7 +631,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
     let unsafety = header.unsafety.print_with_space();
     let abi = print_abi_with_space(header.abi).to_string();
     let asyncness = header.asyncness.print_with_space();
-    let visibility = visibility_print_with_space(it.visibility(tcx), it.item_id, cx).to_string();
+    let visibility = visibility_print_with_space(it, cx).to_string();
     let name = it.name.unwrap();
 
     let generics_len = format!("{:#}", f.generics.print(cx)).len();
@@ -682,7 +688,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             w,
             "{attrs}{vis}{unsafety}{is_auto}trait {name}{generics}{bounds}",
             attrs = render_attributes_in_pre(it, "", cx),
-            vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            vis = visibility_print_with_space(it, cx),
             unsafety = t.unsafety(tcx).print_with_space(),
             is_auto = if t.is_auto(tcx) { "auto " } else { "" },
             name = it.name.unwrap(),
@@ -1237,7 +1243,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
                 w,
                 "{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
                 attrs = render_attributes_in_pre(it, "", cx),
-                vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+                vis = visibility_print_with_space(it, cx),
                 name = it.name.unwrap(),
                 generics = t.generics.print(cx),
                 where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
@@ -1516,14 +1522,13 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
 }
 
 fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
-    let tcx = cx.tcx();
     let count_variants = e.variants().count();
     wrap_item(w, |w| {
         render_attributes_in_code(w, it, cx);
         write!(
             w,
             "{}enum {}{}",
-            visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            visibility_print_with_space(it, cx),
             it.name.unwrap(),
             e.generics.print(cx),
         );
@@ -1854,7 +1859,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
         write!(
             w,
             "{vis}const {name}{generics}: {typ}{where_clause}",
-            vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            vis = visibility_print_with_space(it, cx),
             name = it.name.unwrap(),
             generics = c.generics.print(cx),
             typ = c.type_.print(cx),
@@ -1958,7 +1963,7 @@ fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item,
         write!(
             buffer,
             "{vis}static {mutability}{name}: {typ}",
-            vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+            vis = visibility_print_with_space(it, cx),
             mutability = s.mutability.print_with_space(),
             name = it.name.unwrap(),
             typ = s.type_.print(cx)
@@ -1976,7 +1981,7 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::
         write!(
             buffer,
             "    {}type {};\n}}",
-            visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+            visibility_print_with_space(it, cx),
             it.name.unwrap(),
         )
         .unwrap();
@@ -2133,13 +2138,7 @@ fn render_union<'a, 'cx: 'a>(
     cx: &'a Context<'cx>,
 ) -> impl fmt::Display + 'a + Captures<'cx> {
     display_fn(move |mut f| {
-        let tcx = cx.tcx();
-        write!(
-            f,
-            "{}union {}",
-            visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
-            it.name.unwrap(),
-        )?;
+        write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;
 
         let where_displayed = g
             .map(|g| {
@@ -2169,7 +2168,7 @@ fn render_union<'a, 'cx: 'a>(
                 write!(
                     f,
                     "    {}{}: {},\n",
-                    visibility_print_with_space(field.visibility(tcx), field.item_id, cx),
+                    visibility_print_with_space(field, cx),
                     field.name.unwrap(),
                     ty.print(cx)
                 )?;
@@ -2197,11 +2196,10 @@ fn render_struct(
     structhead: bool,
     cx: &Context<'_>,
 ) {
-    let tcx = cx.tcx();
     write!(
         w,
         "{}{}{}",
-        visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+        visibility_print_with_space(it, cx),
         if structhead { "struct " } else { "" },
         it.name.unwrap()
     );
@@ -2230,7 +2228,6 @@ fn render_struct_fields(
     has_stripped_entries: bool,
     cx: &Context<'_>,
 ) {
-    let tcx = cx.tcx();
     match ty {
         None => {
             let where_displayed =
@@ -2254,7 +2251,7 @@ fn render_struct_fields(
                     write!(
                         w,
                         "\n{tab}    {vis}{name}: {ty},",
-                        vis = visibility_print_with_space(field.visibility(tcx), field.item_id, cx),
+                        vis = visibility_print_with_space(field, cx),
                         name = field.name.unwrap(),
                         ty = ty.print(cx),
                     );
@@ -2290,16 +2287,7 @@ fn render_struct_fields(
                     match *field.kind {
                         clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"),
                         clean::StructFieldItem(ref ty) => {
-                            write!(
-                                w,
-                                "{}{}",
-                                visibility_print_with_space(
-                                    field.visibility(tcx),
-                                    field.item_id,
-                                    cx
-                                ),
-                                ty.print(cx),
-                            )
+                            write!(w, "{}{}", visibility_print_with_space(field, cx), ty.print(cx),)
                         }
                         _ => unreachable!(),
                     }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 39d27b104cd..18651875130 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -530,6 +530,14 @@ fn opts() -> Vec<RustcOptGroup> {
         unstable("test-builder", |o| {
             o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH")
         }),
+        unstable("test-builder-wrapper", |o| {
+            o.optmulti(
+                "",
+                "test-builder-wrapper",
+                "Wrapper program to pass test-builder and arguments",
+                "PATH",
+            )
+        }),
         unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")),
         unstable("generate-redirect-map", |o| {
             o.optflagmulti(
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 0603aae5536..e85b998bfbe 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -80,9 +80,8 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
 
     // check if parent is trait impl
     if let Some(parent_def_id) = cx.tcx.opt_local_parent(def_id)
-        && let Some(parent_node) = cx.tcx.opt_hir_node_by_def_id(parent_def_id)
         && matches!(
-            parent_node,
+            cx.tcx.hir_node_by_def_id(parent_def_id),
             hir::Node::Item(hir::Item {
                 kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }),
                 ..
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 7973f3560287d750500718314a0fd4025bd8ac0
+Subproject 84f190a4abf58bbd5301c0fc831f7a96acea246
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 7065f0ef4aa267a7455e1c478b5ccacb7baea59
+Subproject 2fe739fcf16c5bf8c2064ab9d357f4a0e6c8539
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 8857cb8e382..ad589dad350 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -76,10 +76,9 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
             .hir()
             .get_parent_item(cx.tcx.local_def_id_to_hir_id(fn_def_id))
             .def_id;
-        let parent_node = cx.tcx.opt_hir_node_by_def_id(parent_id);
 
         let mut trait_self_ty = None;
-        if let Some(Node::Item(item)) = parent_node {
+        if let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent_id) {
             // If the method is an impl for a trait, don't warn.
             if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = item.kind {
                 return;
diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs
index 6603512c73c..106844dd434 100644
--- a/src/tools/clippy/clippy_lints/src/exit.rs
+++ b/src/tools/clippy/clippy_lints/src/exit.rs
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
             && let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id()
             && cx.tcx.is_diagnostic_item(sym::process_exit, def_id)
             && let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id
-            && let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.opt_hir_node_by_def_id(parent)
+            && let Node::Item(Item{kind: ItemKind::Fn(..), ..}) = cx.tcx.hir_node_by_def_id(parent)
             // If the next item up is a function we check if it is an entry point
             // and only then emit a linter warning
             && !is_entrypoint_fn(cx, parent.to_def_id())
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index 7f36f33fe70..37fbf2c7d59 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -92,7 +92,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty
             .expect("already checked this is adt")
             .did()
             .as_local()
-        && let Some(hir::Node::Item(item)) = cx.tcx.opt_hir_node_by_def_id(local_def_id)
+        && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id)
         && let hir::ItemKind::Enum(ref def, _) = item.kind
     {
         let variants_size = AdtVariantInfo::new(cx, *adt, subst);
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 4094d7ded7d..ea6e662b4be 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -225,10 +225,9 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
                 if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def()
                     && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name)
                     && let Some(local_did) = field.did.as_local()
-                    && let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(local_did)
                     && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data()
                 {
-                    (hir_id, ident)
+                    (cx.tcx.local_def_id_to_hir_id(local_did), ident)
                 } else {
                     return;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
index 88b331ddefd..3bf9f75e226 100644
--- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
@@ -220,7 +220,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
             && let self_ty = cx.tcx.type_of(self_path_did).skip_binder().peel_refs()
             && let Some(self_adt) = self_ty.ty_adt_def()
             && let Some(self_def_id) = self_adt.did().as_local()
-            && let Some(Node::Item(self_item)) = cx.tcx.opt_hir_node_by_def_id(self_def_id)
+            && let Node::Item(self_item) = cx.tcx.hir_node_by_def_id(self_def_id)
             // NB: can't call cx.typeck_results() as we are not in a body
             && let typeck_results = cx.tcx.typeck_body(*body_id)
             && should_lint(cx, typeck_results, block)
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index a5b58f9910a..a450dee3050 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -112,10 +112,7 @@ fn check_closures<'tcx>(
         }
         ctx.prev_bind = None;
         ctx.prev_move_to_closure.clear();
-        if let Some(body) = cx
-            .tcx
-            .opt_hir_node_by_def_id(closure)
-            .and_then(associated_body)
+        if let Some(body) = associated_body(cx.tcx.hir_node_by_def_id(closure))
             .map(|(_, body_id)| hir.body(body_id))
         {
             euv::ExprUseVisitor::new(ctx, infcx, closure, cx.param_env, cx.typeck_results()).consume_body(body);
diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
index fc5a45dd56d..85a2b1a6735 100644
--- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
+++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
@@ -72,8 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
 
         if let Some(self_def) = self_ty.ty_adt_def()
             && let Some(self_local_did) = self_def.did().as_local()
-            && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did)
-            && let Node::Item(x) = cx.tcx.hir_node(self_id)
+            && let Node::Item(x) = cx.tcx.hir_node_by_def_id(self_local_did)
             && let type_name = x.ident.name.as_str().to_lowercase()
             && (impl_item.ident.name.as_str() == type_name
                 || impl_item.ident.name.as_str().replace('_', "") == type_name)
diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
index 223cbb3fae1..2ce7e714c64 100644
--- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
@@ -95,7 +95,7 @@ impl SingleCallFn {
 /// to be considered.
 fn is_valid_item_kind(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
     matches!(
-        cx.tcx.hir_node(cx.tcx.local_def_id_to_hir_id(def_id)),
+        cx.tcx.hir_node_by_def_id(def_id),
         Node::Item(_) | Node::ImplItem(_) | Node::TraitItem(_)
     )
 }
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 7882bfdd09f..bdef82e9c5e 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
         _: Span,
         def_id: LocalDefId,
     ) {
-        let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx.tcx.opt_hir_node_by_def_id(
+        let is_in_trait_impl = if let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(
             cx.tcx
                 .hir()
                 .get_parent_item(cx.tcx.local_def_id_to_hir_id(def_id))
@@ -366,9 +366,9 @@ impl<'tcx> LateLintPass<'tcx> for Types {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
         match item.kind {
             ImplItemKind::Const(ty, _) => {
-                let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx
+                let is_in_trait_impl = if let hir::Node::Item(item) = cx
                     .tcx
-                    .opt_hir_node_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id)
+                    .hir_node_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id)
                 {
                     matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
                 } else {
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 81d4a26e9da..4aaf3b0a0b6 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
@@ -74,7 +74,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
 fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     let parent_id = cx.tcx.hir().get_parent_item(hir_id);
     let second_parent_id = cx.tcx.hir().get_parent_item(parent_id.into()).def_id;
-    if let Some(Node::Item(item)) = cx.tcx.opt_hir_node_by_def_id(second_parent_id) {
+    if let Node::Item(item) = cx.tcx.hir_node_by_def_id(second_parent_id) {
         if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
             return true;
         }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index dc072573032..a38db0ebec0 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -330,8 +330,7 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
 
 /// Checks if the `def_id` belongs to a function that is part of a trait impl.
 pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
-    if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id)
-        && let Node::Item(item) = cx.tcx.parent_hir_node(hir_id)
+    if let Node::Item(item) = cx.tcx.parent_hir_node(cx.tcx.local_def_id_to_hir_id(def_id))
         && let ItemKind::Impl(imp) = item.kind
     {
         imp.of_trait.is_some()
@@ -574,12 +573,12 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb
     let hir = tcx.hir();
 
     let root_mod;
-    let item_kind = match tcx.opt_hir_node_by_def_id(local_id) {
-        Some(Node::Crate(r#mod)) => {
+    let item_kind = match tcx.hir_node_by_def_id(local_id) {
+        Node::Crate(r#mod) => {
             root_mod = ItemKind::Mod(r#mod);
             &root_mod
         },
-        Some(Node::Item(item)) => &item.kind,
+        Node::Item(item) => &item.kind,
         _ => return Vec::new(),
     };
 
@@ -1254,12 +1253,10 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 /// Gets the name of the item the expression is in, if available.
 pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
     let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
-    match cx.tcx.opt_hir_node_by_def_id(parent_id) {
-        Some(
-            Node::Item(Item { ident, .. })
-            | Node::TraitItem(TraitItem { ident, .. })
-            | Node::ImplItem(ImplItem { ident, .. }),
-        ) => Some(ident.name),
+    match cx.tcx.hir_node_by_def_id(parent_id) {
+        Node::Item(Item { ident, .. })
+        | Node::TraitItem(TraitItem { ident, .. })
+        | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
         _ => None,
     }
 }
@@ -2667,11 +2664,10 @@ impl<'tcx> ExprUseNode<'tcx> {
                     .and(Binder::dummy(cx.tcx.type_of(id).instantiate_identity())),
             )),
             Self::Return(id) => {
-                let hir_id = cx.tcx.local_def_id_to_hir_id(id.def_id);
                 if let Node::Expr(Expr {
                     kind: ExprKind::Closure(c),
                     ..
-                }) = cx.tcx.hir_node(hir_id)
+                }) = cx.tcx.hir_node_by_def_id(id.def_id)
                 {
                     match c.fn_decl.output {
                         FnRetTy::DefaultReturn(_) => None,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 7be0571b111..f427055728f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1466,49 +1466,16 @@ impl<'test> TestCx<'test> {
         // Switch LLDB into "Rust mode"
         let rust_src_root =
             self.config.find_rust_src_root().expect("Could not find Rust source root");
-        let rust_pp_module_rel_path = Path::new("./src/etc/lldb_lookup.py");
-        let rust_pp_module_abs_path =
-            rust_src_root.join(rust_pp_module_rel_path).to_str().unwrap().to_owned();
-
-        let rust_type_regexes = vec![
-            "^(alloc::([a-z_]+::)+)String$",
-            "^&(mut )?str$",
-            "^&(mut )?\\[.+\\]$",
-            "^(std::ffi::([a-z_]+::)+)OsString$",
-            "^(alloc::([a-z_]+::)+)Vec<.+>$",
-            "^(alloc::([a-z_]+::)+)VecDeque<.+>$",
-            "^(alloc::([a-z_]+::)+)BTreeSet<.+>$",
-            "^(alloc::([a-z_]+::)+)BTreeMap<.+>$",
-            "^(std::collections::([a-z_]+::)+)HashMap<.+>$",
-            "^(std::collections::([a-z_]+::)+)HashSet<.+>$",
-            "^(alloc::([a-z_]+::)+)Rc<.+>$",
-            "^(alloc::([a-z_]+::)+)Arc<.+>$",
-            "^(core::([a-z_]+::)+)Cell<.+>$",
-            "^(core::([a-z_]+::)+)Ref<.+>$",
-            "^(core::([a-z_]+::)+)RefMut<.+>$",
-            "^(core::([a-z_]+::)+)RefCell<.+>$",
-            "^core::num::([a-z_]+::)*NonZero.+$",
-        ];
+        let rust_pp_module_rel_path = Path::new("./src/etc");
+        let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path);
 
-        // In newer versions of lldb, persistent results (the `$N =` part at the start of
-        // expressions you have evaluated that let you re-use the result) aren't printed, but lots
-        // of rustc's debuginfo tests rely on these, so re-enable this.
-        // See <https://reviews.llvm.org/rG385496385476fc9735da5fa4acabc34654e8b30d>.
-        script_str.push_str("command unalias print\n");
-        script_str.push_str("command alias print expr --\n");
-        script_str.push_str("command unalias p\n");
-        script_str.push_str("command alias p expr --\n");
-
-        script_str
-            .push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[..]);
-        script_str.push_str("type synthetic add -l lldb_lookup.synthetic_lookup -x '.*' ");
-        script_str.push_str("--category Rust\n");
-        for type_regex in rust_type_regexes {
-            script_str.push_str("type summary add -F lldb_lookup.summary_lookup  -e -x -h ");
-            script_str.push_str(&format!("'{}' ", type_regex));
-            script_str.push_str("--category Rust\n");
-        }
-        script_str.push_str("type category enable Rust\n");
+        script_str.push_str(&format!(
+            "command script import {}/lldb_lookup.py\n",
+            rust_pp_module_abs_path.to_str().unwrap()
+        ));
+        File::open(rust_pp_module_abs_path.join("lldb_commands"))
+            .and_then(|mut file| file.read_to_string(&mut script_str))
+            .expect("Failed to read lldb_commands");
 
         // Set breakpoints on every line that contains the string "#break"
         let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml
index d8a7a06efc6..9ea26defdc4 100644
--- a/src/tools/generate-windows-sys/Cargo.toml
+++ b/src/tools/generate-windows-sys/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies.windows-bindgen]
-version = "0.52.0"
+version = "0.55.0"
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index c5cd30ccc34..0c39f2fa601 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -16,6 +16,10 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
     ("rust-2018-compatibility", "Lints used to transition code from the 2015 edition to 2018"),
     ("rust-2021-compatibility", "Lints used to transition code from the 2018 edition to 2021"),
     ("rust-2024-compatibility", "Lints used to transition code from the 2021 edition to 2024"),
+    (
+        "refining-impl-trait",
+        "Detects refinement of `impl Trait` return types by trait implementations",
+    ),
 ];
 
 type LintGroups = BTreeMap<String, BTreeSet<String>>;
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr
index 7d481940ace..35de4535222 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
   --> $DIR/cast_fn_ptr_invalid_callee_ret.rs:LL:CC
    |
 LL |     f();
-   |     ^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
+   |     ^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
index b1a2bd2c79a..81d775f6d7f 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
   --> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
    |
 LL |             Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/opt-dist/src/bolt.rs b/src/tools/opt-dist/src/bolt.rs
index f694c08f9b9..eb10426f060 100644
--- a/src/tools/opt-dist/src/bolt.rs
+++ b/src/tools/opt-dist/src/bolt.rs
@@ -62,9 +62,11 @@ pub fn bolt_optimize(path: &Utf8Path, profile: &BoltProfile) -> anyhow::Result<(
         // Reorder basic blocks within functions
         .arg("-reorder-blocks=ext-tsp")
         // Reorder functions within the binary
-        .arg("-reorder-functions=hfsort+")
+        .arg("-reorder-functions=cdsort")
         // Split function code into hot and code regions
         .arg("-split-functions")
+        // Split using best available strategy (three-way splitting, Cache-Directed Sort)
+        .arg("-split-strategy=cdsplit")
         // Split as many basic blocks as possible
         .arg("-split-all-cold")
         // Move jump tables to a separate section
diff --git a/src/version b/src/version
index 54227249d1f..b3a8c61e6a8 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.78.0
+1.79.0