about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-04-18 06:37:34 +0000
committerGitHub <noreply@github.com>2025-04-18 06:37:34 +0000
commit46994aacccced2aa897ca72e27171481ca02e01d (patch)
tree385918a5c5e3e857e66faf2f9f3ec9f30abf708c /src
parent765d4b29af1830e41862d966d2f37f0807baac06 (diff)
parentdc21c77ae6ba8ea63b55e5d2924b64fad2ea0ab5 (diff)
downloadrust-46994aacccced2aa897ca72e27171481ca02e01d.tar.gz
rust-46994aacccced2aa897ca72e27171481ca02e01d.zip
Merge pull request #4279 from rust-lang/rustup-2025-04-18
Automatic Rustup
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs4
-rw-r--r--src/build_helper/src/fs/mod.rs56
-rw-r--r--src/build_helper/src/fs/tests.rs2
-rw-r--r--src/doc/rustc-dev-guide/src/tests/best-practices.md2
-rw-r--r--src/doc/rustc-dev-guide/src/tests/directives.md3
-rw-r--r--src/librustdoc/clean/inline.rs43
-rw-r--r--src/librustdoc/core.rs4
-rw-r--r--src/librustdoc/html/render/print_item.rs5
-rw-r--r--src/tools/compiletest/src/directive-list.rs1
-rw-r--r--src/tools/compiletest/src/header/cfg.rs4
-rw-r--r--src/tools/compiletest/src/header/tests.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs31
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc.rs4
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc_json.rs4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs2
-rw-r--r--src/tools/opt-dist/src/environment.rs5
-rw-r--r--src/tools/opt-dist/src/main.rs10
-rw-r--r--src/tools/run-make-support/Cargo.toml4
-rw-r--r--src/tools/run-make-support/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/Cargo.lock4
-rw-r--r--src/tools/tidy/src/deps.rs3
23 files changed, 136 insertions, 67 deletions
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index e157ff233bb..b70d452b427 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/138784
+Last change is for: https://github.com/rust-lang/rust/pull/139931
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 69a8bd59f16..6e84b83d17d 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -370,8 +370,8 @@ impl Step for Llvm {
             cfg.define("LLVM_PROFDATA_FILE", path);
         }
 
-        // Libraries for ELF section compression.
-        if !target.is_windows() {
+        // Libraries for ELF section compression and profraw files merging.
+        if !target.is_msvc() {
             cfg.define("LLVM_ENABLE_ZLIB", "ON");
         } else {
             cfg.define("LLVM_ENABLE_ZLIB", "OFF");
diff --git a/src/build_helper/src/fs/mod.rs b/src/build_helper/src/fs/mod.rs
index 02029846fd1..123df76e6a2 100644
--- a/src/build_helper/src/fs/mod.rs
+++ b/src/build_helper/src/fs/mod.rs
@@ -22,21 +22,27 @@ where
 /// A wrapper around [`std::fs::remove_dir_all`] that can also be used on *non-directory entries*,
 /// including files and symbolic links.
 ///
-/// - This will produce an error if the target path is not found.
+/// - This will not produce an error if the target path is not found.
 /// - Like [`std::fs::remove_dir_all`], this helper does not traverse symbolic links, will remove
 ///   symbolic link itself.
 /// - This helper is **not** robust against races on the underlying filesystem, behavior is
 ///   unspecified if this helper is called concurrently.
 /// - This helper is not robust against TOCTOU problems.
 ///
-/// FIXME: this implementation is insufficiently robust to replace bootstrap's clean `rm_rf`
-/// implementation:
-///
-/// - This implementation currently does not perform retries.
+/// FIXME: Audit whether this implementation is robust enough to replace bootstrap's clean `rm_rf`.
 #[track_caller]
 pub fn recursive_remove<P: AsRef<Path>>(path: P) -> io::Result<()> {
     let path = path.as_ref();
-    let metadata = fs::symlink_metadata(path)?;
+
+    // If the path doesn't exist, we treat it as a successful no-op.
+    // From the caller's perspective, the goal is simply "ensure this file/dir is gone" —
+    // if it's already not there, that's a success, not an error.
+    let metadata = match fs::symlink_metadata(path) {
+        Ok(m) => m,
+        Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(()),
+        Err(e) => return Err(e),
+    };
+
     #[cfg(windows)]
     let is_dir_like = |meta: &fs::Metadata| {
         use std::os::windows::fs::FileTypeExt;
@@ -45,11 +51,35 @@ pub fn recursive_remove<P: AsRef<Path>>(path: P) -> io::Result<()> {
     #[cfg(not(windows))]
     let is_dir_like = fs::Metadata::is_dir;
 
-    if is_dir_like(&metadata) {
-        fs::remove_dir_all(path)
-    } else {
-        try_remove_op_set_perms(fs::remove_file, path, metadata)
+    const MAX_RETRIES: usize = 5;
+    const RETRY_DELAY_MS: u64 = 100;
+
+    let try_remove = || {
+        if is_dir_like(&metadata) {
+            fs::remove_dir_all(path)
+        } else {
+            try_remove_op_set_perms(fs::remove_file, path, metadata.clone())
+        }
+    };
+
+    // Retry deletion a few times to handle transient filesystem errors.
+    // This is unusual for local file operations, but it's a mitigation
+    // against unlikely events where malware scanners may be holding a
+    // file beyond our control, to give the malware scanners some opportunity
+    // to release their hold.
+    for attempt in 0..MAX_RETRIES {
+        match try_remove() {
+            Ok(()) => return Ok(()),
+            Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(()),
+            Err(_) if attempt < MAX_RETRIES - 1 => {
+                std::thread::sleep(std::time::Duration::from_millis(RETRY_DELAY_MS));
+                continue;
+            }
+            Err(e) => return Err(e),
+        }
     }
+
+    Ok(())
 }
 
 fn try_remove_op_set_perms<'p, Op>(mut op: Op, path: &'p Path, metadata: Metadata) -> io::Result<()>
@@ -67,3 +97,9 @@ where
         Err(e) => Err(e),
     }
 }
+
+pub fn remove_and_create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
+    let path = path.as_ref();
+    recursive_remove(path)?;
+    fs::create_dir_all(path)
+}
diff --git a/src/build_helper/src/fs/tests.rs b/src/build_helper/src/fs/tests.rs
index 1e694393127..7ce1d8928d1 100644
--- a/src/build_helper/src/fs/tests.rs
+++ b/src/build_helper/src/fs/tests.rs
@@ -14,7 +14,7 @@ mod recursive_remove_tests {
         let tmpdir = env::temp_dir();
         let path = tmpdir.join("__INTERNAL_BOOTSTRAP_nonexistent_path");
         assert!(fs::symlink_metadata(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound));
-        assert!(recursive_remove(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound));
+        assert!(recursive_remove(&path).is_ok());
     }
 
     #[test]
diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md
index 6905ee13283..2bdc7f3a243 100644
--- a/src/doc/rustc-dev-guide/src/tests/best-practices.md
+++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md
@@ -175,6 +175,8 @@ See [compiletest directives] for a listing of directives.
 - For `ignore-*`/`needs-*`/`only-*` directives, unless extremely obvious,
   provide a brief remark on why the directive is needed. E.g. `"//@ ignore-wasi
   (wasi codegens the main symbol differently)"`.
+- When using `//@ ignore-auxiliary`, specify the corresponding main test files,
+  e.g. ``//@ ignore-auxiliary (used by `./foo.rs`)``.
 
 ## FileCheck best practices
 
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index 0aad8be982f..dae659e6317 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -124,6 +124,9 @@ means the test won't be compiled or run.
 * `ignore-X` where `X` is a target detail or other criteria on which to ignore the test (see below)
 * `only-X` is like `ignore-X`, but will *only* run the test on that target or
   stage
+* `ignore-auxiliary` is intended for files that *participate* in one or more other
+  main test files but that `compiletest` should not try to build the file itself.
+  Please backlink to which main test is actually using the auxiliary file.
 * `ignore-test` always ignores the test. This can be used to temporarily disable
   a test if it is currently not working, but you want to keep it in tree to
   re-enable it later.
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 2f6870e3c36..55a116a018a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -67,9 +67,13 @@ pub(crate) fn try_inline(
             record_extern_fqn(cx, did, ItemType::Trait);
             cx.with_param_env(did, |cx| {
                 build_impls(cx, did, attrs_without_docs, &mut ret);
-                clean::TraitItem(Box::new(build_external_trait(cx, did)))
+                clean::TraitItem(Box::new(build_trait(cx, did)))
             })
         }
+        Res::Def(DefKind::TraitAlias, did) => {
+            record_extern_fqn(cx, did, ItemType::TraitAlias);
+            cx.with_param_env(did, |cx| clean::TraitAliasItem(build_trait_alias(cx, did)))
+        }
         Res::Def(DefKind::Fn, did) => {
             record_extern_fqn(cx, did, ItemType::Function);
             cx.with_param_env(did, |cx| {
@@ -251,7 +255,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
     }
 }
 
-pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
+pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
     let trait_items = cx
         .tcx
         .associated_items(did)
@@ -263,11 +267,18 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
     let predicates = cx.tcx.predicates_of(did);
     let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
     let generics = filter_non_trait_generics(did, generics);
-    let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
+    let (generics, supertrait_bounds) = separate_self_bounds(generics);
     clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
 }
 
-pub(crate) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
+fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
+    let predicates = cx.tcx.predicates_of(did);
+    let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
+    let (generics, bounds) = separate_self_bounds(generics);
+    clean::TraitAlias { generics, bounds }
+}
+
+pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
     let sig = cx.tcx.fn_sig(def_id).instantiate_identity();
     // The generics need to be cleaned before the signature.
     let mut generics =
@@ -788,12 +799,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
     g
 }
 
-/// Supertrait bounds for a trait are also listed in the generics coming from
-/// the metadata for a crate, so we want to separate those out and create a new
-/// list of explicit supertrait bounds to render nicely.
-fn separate_supertrait_bounds(
-    mut g: clean::Generics,
-) -> (clean::Generics, Vec<clean::GenericBound>) {
+fn separate_self_bounds(mut g: clean::Generics) -> (clean::Generics, Vec<clean::GenericBound>) {
     let mut ty_bounds = Vec::new();
     g.where_predicates.retain(|pred| match *pred {
         clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
@@ -806,22 +812,17 @@ fn separate_supertrait_bounds(
 }
 
 pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
-    if did.is_local() {
-        return;
-    }
-
+    if did.is_local()
+        || cx.external_traits.contains_key(&did)
+        || cx.active_extern_traits.contains(&did)
     {
-        if cx.external_traits.contains_key(&did) || cx.active_extern_traits.contains(&did) {
-            return;
-        }
+        return;
     }
 
-    {
-        cx.active_extern_traits.insert(did);
-    }
+    cx.active_extern_traits.insert(did);
 
     debug!("record_extern_trait: {did:?}");
-    let trait_ = build_external_trait(cx, did);
+    let trait_ = build_trait(cx, did);
 
     cx.external_traits.insert(did, trait_);
     cx.active_extern_traits.remove(&did);
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index c4dea79370d..41688b41c6e 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -27,7 +27,7 @@ use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use tracing::{debug, info};
 
-use crate::clean::inline::build_external_trait;
+use crate::clean::inline::build_trait;
 use crate::clean::{self, ItemId};
 use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
 use crate::formats::cache::Cache;
@@ -385,7 +385,7 @@ pub(crate) fn run_global_ctxt(
     //
     // Note that in case of `#![no_core]`, the trait is not available.
     if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() {
-        let sized_trait = build_external_trait(&mut ctxt, sized_trait_did);
+        let sized_trait = build_trait(&mut ctxt, sized_trait_did);
         ctxt.external_traits.insert(sized_trait_did, sized_trait);
     }
 
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 45cb0adecf3..39a631b637b 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1232,12 +1232,13 @@ fn item_trait_alias(
         wrap_item(w, |w| {
             write!(
                 w,
-                "{attrs}trait {name}{generics}{where_b} = {bounds};",
+                "{attrs}trait {name}{generics} = {bounds}{where_clause};",
                 attrs = render_attributes_in_pre(it, "", cx),
                 name = it.name.unwrap(),
                 generics = t.generics.print(cx),
-                where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(),
                 bounds = bounds(&t.bounds, true, cx),
+                where_clause =
+                    print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(),
             )
         })?;
 
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 086a8a67456..44c52c8c766 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -44,6 +44,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-arm-unknown-linux-gnueabihf",
     "ignore-arm-unknown-linux-musleabi",
     "ignore-arm-unknown-linux-musleabihf",
+    "ignore-auxiliary",
     "ignore-avr",
     "ignore-beta",
     "ignore-cdb",
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index c369fff97f4..f1f1384afb9 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -101,6 +101,10 @@ fn parse_cfg_name_directive<'a>(
         message: "always"
     }
     condition! {
+        name: "auxiliary",
+        message: "used by another main test file"
+    }
+    condition! {
         name: &config.target,
         allowed_names: &target_cfgs.all_targets,
         message: "when the target is {name}"
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 3a8c3748de9..2525e0adc83 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -940,3 +940,9 @@ fn test_supported_crate_types() {
         "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
     ));
 }
+
+#[test]
+fn test_ignore_auxiliary() {
+    let config = cfg().build();
+    assert!(check_ignore(&config, "//@ ignore-auxiliary"));
+}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index eb298060b2e..d11f5c1a3a6 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -9,6 +9,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio};
 use std::sync::Arc;
 use std::{env, iter, str};
 
+use build_helper::fs::remove_and_create_dir_all;
 use camino::{Utf8Path, Utf8PathBuf};
 use colored::Colorize;
 use regex::{Captures, Regex};
@@ -207,12 +208,6 @@ pub fn compute_stamp_hash(config: &Config) -> String {
     format!("{:x}", hash.finish())
 }
 
-fn remove_and_create_dir_all(path: &Utf8Path) {
-    let path = path.as_std_path();
-    let _ = fs::remove_dir_all(path);
-    fs::create_dir_all(path).unwrap();
-}
-
 #[derive(Copy, Clone, Debug)]
 struct TestCx<'test> {
     config: &'test Config,
@@ -523,7 +518,9 @@ impl<'test> TestCx<'test> {
         let mut rustc = Command::new(&self.config.rustc_path);
 
         let out_dir = self.output_base_name().with_extension("pretty-out");
-        remove_and_create_dir_all(&out_dir);
+        remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| {
+            panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
+        });
 
         let target = if self.props.force_host { &*self.config.host } else { &*self.config.target };
 
@@ -1098,13 +1095,19 @@ impl<'test> TestCx<'test> {
         let aux_dir = self.aux_output_dir_name();
 
         if !self.props.aux.builds.is_empty() {
-            remove_and_create_dir_all(&aux_dir);
+            remove_and_create_dir_all(&aux_dir).unwrap_or_else(|e| {
+                panic!("failed to remove and recreate output directory `{aux_dir}`: {e}")
+            });
         }
 
         if !self.props.aux.bins.is_empty() {
             let aux_bin_dir = self.aux_bin_output_dir_name();
-            remove_and_create_dir_all(&aux_dir);
-            remove_and_create_dir_all(&aux_bin_dir);
+            remove_and_create_dir_all(&aux_dir).unwrap_or_else(|e| {
+                panic!("failed to remove and recreate output directory `{aux_dir}`: {e}")
+            });
+            remove_and_create_dir_all(&aux_bin_dir).unwrap_or_else(|e| {
+                panic!("failed to remove and recreate output directory `{aux_bin_dir}`: {e}")
+            });
         }
 
         aux_dir
@@ -1509,7 +1512,9 @@ impl<'test> TestCx<'test> {
 
         let set_mir_dump_dir = |rustc: &mut Command| {
             let mir_dump_dir = self.get_mir_dump_dir();
-            remove_and_create_dir_all(&mir_dump_dir);
+            remove_and_create_dir_all(&mir_dump_dir).unwrap_or_else(|e| {
+                panic!("failed to remove and recreate output directory `{mir_dump_dir}`: {e}")
+            });
             let mut dir_opt = "-Zdump-mir-dir=".to_string();
             dir_opt.push_str(mir_dump_dir.as_str());
             debug!("dir_opt: {:?}", dir_opt);
@@ -1969,7 +1974,9 @@ impl<'test> TestCx<'test> {
         let suffix =
             self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly");
         let compare_dir = output_base_dir(self.config, self.testpaths, Some(&suffix));
-        remove_and_create_dir_all(&compare_dir);
+        remove_and_create_dir_all(&compare_dir).unwrap_or_else(|e| {
+            panic!("failed to remove and recreate output directory `{compare_dir}`: {e}")
+        });
 
         // We need to create a new struct for the lifetimes on `config` to work.
         let new_rustdoc = TestCx {
diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs
index 2583ae96a67..637ea833357 100644
--- a/src/tools/compiletest/src/runtest/rustdoc.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc.rs
@@ -7,7 +7,9 @@ impl TestCx<'_> {
         assert!(self.revision.is_none(), "revisions not relevant here");
 
         let out_dir = self.output_base_dir();
-        remove_and_create_dir_all(&out_dir);
+        remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| {
+            panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
+        });
 
         let proc_res = self.document(&out_dir, &self.testpaths);
         if !proc_res.status.success() {
diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs
index bf7eb2e109a..9f88faca892 100644
--- a/src/tools/compiletest/src/runtest/rustdoc_json.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs
@@ -9,7 +9,9 @@ impl TestCx<'_> {
         assert!(self.revision.is_none(), "revisions not relevant here");
 
         let out_dir = self.output_base_dir();
-        remove_and_create_dir_all(&out_dir);
+        remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| {
+            panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
+        });
 
         let proc_res = self.document(&out_dir, &self.testpaths);
         if !proc_res.status.success() {
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index ed2e4474add..45b3546a09b 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-883f9f72e87ccb6838d528d8158ea6323baacc65
+1f76d219c906f0112bb1872f33aa977164c53fa6
diff --git a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs
index 341b2280e01..abc0968f7c4 100644
--- a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs
+++ b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs
@@ -13,7 +13,7 @@ pub fn main() {
     TLS.set(Some(Box::leak(Box::new(123))));
 
     // We can only ignore leaks on targets that use `#[thread_local]` statics to implement
-    // `thread_local!`. Ignore the test on targest that don't.
+    // `thread_local!`. Ignore the test on targets that don't.
     if cfg!(target_thread_local) {
         thread_local! {
             static TLS_KEY: Cell<Option<&'static i32>> = Cell::new(None);
diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs
index 90d0ca717b2..9342d164be4 100644
--- a/src/tools/opt-dist/src/environment.rs
+++ b/src/tools/opt-dist/src/environment.rs
@@ -25,6 +25,7 @@ pub struct Environment {
     prebuilt_rustc_perf: Option<Utf8PathBuf>,
     use_bolt: bool,
     shared_llvm: bool,
+    run_tests: bool,
 }
 
 impl Environment {
@@ -101,6 +102,10 @@ impl Environment {
     pub fn benchmark_cargo_config(&self) -> &[String] {
         &self.benchmark_cargo_config
     }
+
+    pub fn run_tests(&self) -> bool {
+        self.run_tests
+    }
 }
 
 /// What is the extension of binary executables on this platform?
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index ff4ddbaea49..d5e6640fb43 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -94,6 +94,10 @@ enum EnvironmentCmd {
         /// Arguments passed to `rustc-perf --cargo-config <value>` when running benchmarks.
         #[arg(long)]
         benchmark_cargo_config: Vec<String>,
+
+        /// Perform tests after final build if it's not a try build
+        #[arg(long)]
+        run_tests: bool,
     },
     /// Perform an optimized build on Linux CI, from inside Docker.
     LinuxCi {
@@ -125,6 +129,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
             skipped_tests,
             benchmark_cargo_config,
             shared,
+            run_tests,
         } => {
             let env = EnvironmentBuilder::default()
                 .host_tuple(target_triple)
@@ -138,6 +143,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
                 .use_bolt(use_bolt)
                 .skipped_tests(skipped_tests)
                 .benchmark_cargo_config(benchmark_cargo_config)
+                .run_tests(run_tests)
                 .build()?;
 
             (env, shared.build_args)
@@ -160,6 +166,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
                 // FIXME: Enable bolt for aarch64 once it's fixed upstream. Broken as of December 2024.
                 .use_bolt(!is_aarch64)
                 .skipped_tests(vec![])
+                .run_tests(true)
                 .build()?;
 
             (env, shared.build_args)
@@ -179,6 +186,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
                 .shared_llvm(false)
                 .use_bolt(false)
                 .skipped_tests(vec![])
+                .run_tests(true)
                 .build()?;
 
             (env, shared.build_args)
@@ -344,7 +352,7 @@ fn execute_pipeline(
     // possible regressions.
     // The tests are not executed for try builds, which can be in various broken states, so we don't
     // want to gatekeep them with tests.
-    if !is_try_build() {
+    if !is_try_build() && env.run_tests() {
         timer.section("Run tests", |_| run_tests(env))?;
     }
 
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index f9beffec750..15ed03ad5c2 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -14,9 +14,5 @@ build_helper = { path = "../../build_helper" }
 serde_json = "1.0"
 libc = "0.2"
 
-# FIXME(#137532): replace `os_pipe` with `anonymous_pipe` once it stabilizes and
-# reaches beta.
-os_pipe = "1.2.1"
-
 [lib]
 crate-type = ["lib", "dylib"]
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index c75d500d2f0..f37b38ac0b1 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -41,8 +41,6 @@ pub use bstr;
 pub use gimli;
 pub use libc;
 pub use object;
-// FIXME(#137532): replace with std `anonymous_pipe` once it stabilizes and reaches beta.
-pub use os_pipe;
 pub use regex;
 pub use serde_json;
 pub use similar;
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 745a8097c8a..2dbb3f5d69c 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -902,9 +902,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.169"
+version = "0.2.172"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
 
 [[package]]
 name = "libloading"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index fd8e4eacc0f..dd7f9c6b146 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -260,7 +260,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "constant_time_eq",
     "cpufeatures",
     "crc32fast",
-    "crossbeam-channel",
     "crossbeam-deque",
     "crossbeam-epoch",
     "crossbeam-utils",
@@ -295,7 +294,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "gimli",
     "gsgdt",
     "hashbrown",
-    "hermit-abi",
     "icu_list",
     "icu_list_data",
     "icu_locid",
@@ -329,7 +327,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "miniz_oxide",
     "nix",
     "nu-ansi-term",
-    "num_cpus",
     "object",
     "odht",
     "once_cell",