about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock3
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs6
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs34
-rw-r--r--compiler/rustc_session/Cargo.toml1
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--library/std/src/sync/once.rs2
-rw-r--r--library/std/src/thread/mod.rs13
-rw-r--r--library/std/src/thread/scoped.rs15
-rw-r--r--library/std/src/thread/tests.rs8
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/config.rs14
-rw-r--r--src/bootstrap/flags.rs2
-rw-r--r--src/bootstrap/lib.rs4
-rw-r--r--src/bootstrap/toolstate.rs13
-rw-r--r--src/librustdoc/clean/types.rs10
-rw-r--r--src/test/ui/issues/issue-87707.rs15
-rw-r--r--src/test/ui/issues/issue-87707.run.stderr3
-rw-r--r--src/test/ui/parser/trailing-question-in-macro-type.rs14
-rw-r--r--src/test/ui/parser/trailing-question-in-macro-type.stderr9
-rw-r--r--src/tools/build-manifest/Cargo.toml1
-rw-r--r--src/tools/build-manifest/src/main.rs2
22 files changed, 112 insertions, 62 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8ca6f26e326..de582f702ad 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -221,7 +221,6 @@ dependencies = [
  "getopts",
  "ignore",
  "libc",
- "num_cpus",
  "once_cell",
  "opener",
  "pretty_assertions",
@@ -249,7 +248,6 @@ dependencies = [
  "anyhow",
  "flate2",
  "hex 0.4.2",
- "num_cpus",
  "rayon",
  "serde",
  "serde_json",
@@ -4242,7 +4240,6 @@ name = "rustc_session"
 version = "0.0.0"
 dependencies = [
  "getopts",
- "num_cpus",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index c7aa9ffc793..40daf4eb28f 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1,5 +1,5 @@
 use super::pat::Expected;
-use super::ty::{AllowPlus, IsAsCast};
+use super::ty::{AllowPlus, RecoverQuestionMark};
 use super::{
     BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions,
     SemiColonMode, SeqSep, TokenExpectType, TokenType,
@@ -1049,9 +1049,9 @@ impl<'a> Parser<'a> {
     pub(super) fn maybe_recover_from_question_mark(
         &mut self,
         ty: P<Ty>,
-        is_as_cast: IsAsCast,
+        recover_question_mark: RecoverQuestionMark,
     ) -> P<Ty> {
-        if let IsAsCast::Yes = is_as_cast {
+        if let RecoverQuestionMark::No = recover_question_mark {
             return ty;
         }
         if self.token == token::Question {
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 83e0a4997ad..40902fa1833 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -140,7 +140,7 @@ impl<'a> Parser<'a> {
             }
 
             NonterminalKind::Ty => {
-                token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty())?)
+                token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?)
             }
             // this could be handled like a token, since it is one
             NonterminalKind::Ident
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 0b01f9e927f..436c5bd4fca 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -44,7 +44,7 @@ pub(super) enum RecoverQPath {
     No,
 }
 
-pub(super) enum IsAsCast {
+pub(super) enum RecoverQuestionMark {
     Yes,
     No,
 }
@@ -105,7 +105,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -119,7 +119,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             Some(ty_params),
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -133,7 +133,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -150,7 +150,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -163,9 +163,21 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::Yes,
+            RecoverQuestionMark::No,
         )
     }
+
+    pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(
+            AllowPlus::Yes,
+            AllowCVariadic::No,
+            RecoverQPath::Yes,
+            RecoverReturnSign::Yes,
+            None,
+            RecoverQuestionMark::No,
+        )
+    }
+
     /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
     pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
@@ -174,7 +186,7 @@ impl<'a> Parser<'a> {
             RecoverQPath::Yes,
             RecoverReturnSign::OnlyFatArrow,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -193,7 +205,7 @@ impl<'a> Parser<'a> {
                 recover_qpath,
                 recover_return_sign,
                 None,
-                IsAsCast::No,
+                RecoverQuestionMark::Yes,
             )?;
             FnRetTy::Ty(ty)
         } else if recover_return_sign.can_recover(&self.token.kind) {
@@ -214,7 +226,7 @@ impl<'a> Parser<'a> {
                 recover_qpath,
                 recover_return_sign,
                 None,
-                IsAsCast::No,
+                RecoverQuestionMark::Yes,
             )?;
             FnRetTy::Ty(ty)
         } else {
@@ -229,7 +241,7 @@ impl<'a> Parser<'a> {
         recover_qpath: RecoverQPath,
         recover_return_sign: RecoverReturnSign,
         ty_generics: Option<&Generics>,
-        is_as_cast: IsAsCast,
+        recover_question_mark: RecoverQuestionMark,
     ) -> PResult<'a, P<Ty>> {
         let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
@@ -305,7 +317,7 @@ impl<'a> Parser<'a> {
         // Try to recover from use of `+` with incorrect priority.
         self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
         self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
-        let ty = self.maybe_recover_from_question_mark(ty, is_as_cast);
+        let ty = self.maybe_recover_from_question_mark(ty, recover_question_mark);
         self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
     }
 
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 37cfc4a0dc3..6b1eaa4d399 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -15,6 +15,5 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_span = { path = "../rustc_span" }
 rustc_fs_util = { path = "../rustc_fs_util" }
-num_cpus = "1.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 17eec333e09..c42a1530451 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -551,7 +551,7 @@ mod parse {
     crate fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool {
         match v.and_then(|s| s.parse().ok()) {
             Some(0) => {
-                *slot = ::num_cpus::get();
+                *slot = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get);
                 true
             }
             Some(i) => {
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index f76d0759561..511de863dc5 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -256,6 +256,7 @@ impl Once {
     ///
     /// [poison]: struct.Mutex.html#poisoning
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[track_caller]
     pub fn call_once<F>(&self, f: F)
     where
         F: FnOnce(),
@@ -390,6 +391,7 @@ impl Once {
     // currently no way to take an `FnOnce` and call it via virtual dispatch
     // without some allocation overhead.
     #[cold]
+    #[track_caller]
     fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&OnceState)) {
         let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire);
         loop {
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 09d1e714ab6..5ffc86b4560 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1443,13 +1443,18 @@ impl<T> JoinHandle<T> {
         self.0.join()
     }
 
-    /// Checks if the associated thread is still running its main function.
+    /// Checks if the associated thread has finished running its main function.
     ///
-    /// This might return `false` for a brief moment after the thread's main
+    /// This might return `true` for a brief moment after the thread's main
     /// function has returned, but before the thread itself has stopped running.
+    /// However, once this returns `true`, [`join`][Self::join] can be expected
+    /// to return quickly, without blocking for any significant amount of time.
+    ///
+    /// This function does not block. To block while waiting on the thread to finish,
+    /// use [`join`][Self::join].
     #[unstable(feature = "thread_is_running", issue = "90470")]
-    pub fn is_running(&self) -> bool {
-        Arc::strong_count(&self.0.packet) > 1
+    pub fn is_finished(&self) -> bool {
+        Arc::strong_count(&self.0.packet) == 1
     }
 }
 
diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs
index 9dd7c15fc59..ea9623be63b 100644
--- a/library/std/src/thread/scoped.rs
+++ b/library/std/src/thread/scoped.rs
@@ -240,7 +240,6 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
     ///
     /// ```
     /// #![feature(scoped_threads)]
-    /// #![feature(thread_is_running)]
     ///
     /// use std::thread;
     ///
@@ -274,7 +273,6 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
     ///
     /// ```
     /// #![feature(scoped_threads)]
-    /// #![feature(thread_is_running)]
     ///
     /// use std::thread;
     ///
@@ -289,13 +287,18 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
         self.0.join()
     }
 
-    /// Checks if the associated thread is still running its main function.
+    /// Checks if the associated thread has finished running its main function.
     ///
-    /// This might return `false` for a brief moment after the thread's main
+    /// This might return `true` for a brief moment after the thread's main
     /// function has returned, but before the thread itself has stopped running.
+    /// However, once this returns `true`, [`join`][Self::join] can be expected
+    /// to return quickly, without blocking for any significant amount of time.
+    ///
+    /// This function does not block. To block while waiting on the thread to finish,
+    /// use [`join`][Self::join].
     #[unstable(feature = "thread_is_running", issue = "90470")]
-    pub fn is_running(&self) -> bool {
-        Arc::strong_count(&self.0.packet) > 1
+    pub fn is_finished(&self) -> bool {
+        Arc::strong_count(&self.0.packet) == 1
     }
 }
 
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 4f2c81731a3..3323ba36bf3 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -52,7 +52,7 @@ fn test_run_basic() {
 }
 
 #[test]
-fn test_is_running() {
+fn test_is_finished() {
     let b = Arc::new(Barrier::new(2));
     let t = thread::spawn({
         let b = b.clone();
@@ -63,14 +63,14 @@ fn test_is_running() {
     });
 
     // Thread is definitely running here, since it's still waiting for the barrier.
-    assert_eq!(t.is_running(), true);
+    assert_eq!(t.is_finished(), false);
 
     // Unblock the barrier.
     b.wait();
 
-    // Now check that t.is_running() becomes false within a reasonable time.
+    // Now check that t.is_finished() becomes true within a reasonable time.
     let start = Instant::now();
-    while t.is_running() {
+    while !t.is_finished() {
         assert!(start.elapsed() < Duration::from_secs(2));
         thread::sleep(Duration::from_millis(15));
     }
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 592a137e379..02efc08cc79 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -37,7 +37,6 @@ test = false
 build_helper = { path = "../build_helper" }
 cmake = "0.1.38"
 filetime = "0.2"
-num_cpus = "1.0"
 getopts = "0.2.19"
 cc = "1.0.69"
 libc = "0.2"
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index d6f77fe6cd6..997e811e214 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -387,7 +387,7 @@ macro_rules! derive_merge {
 
 derive_merge! {
     /// TOML representation of various global build decisions.
-    #[derive(Deserialize, Default, Clone)]
+    #[derive(Deserialize, Default)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Build {
         build: Option<String>,
@@ -434,7 +434,7 @@ derive_merge! {
 
 derive_merge! {
     /// TOML representation of various global install decisions.
-    #[derive(Deserialize, Default, Clone)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Install {
         prefix: Option<String>,
@@ -449,7 +449,7 @@ derive_merge! {
 
 derive_merge! {
     /// TOML representation of how the LLVM build is configured.
-    #[derive(Deserialize, Default)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Llvm {
         skip_rebuild: Option<bool>,
@@ -483,7 +483,7 @@ derive_merge! {
 }
 
 derive_merge! {
-    #[derive(Deserialize, Default, Clone)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Dist {
         sign_folder: Option<String>,
@@ -510,7 +510,7 @@ impl Default for StringOrBool {
 
 derive_merge! {
     /// TOML representation of how the Rust build is configured.
-    #[derive(Deserialize, Default)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Rust {
         optimize: Option<bool>,
@@ -565,7 +565,7 @@ derive_merge! {
 
 derive_merge! {
     /// TOML representation of how each build target is configured.
-    #[derive(Deserialize, Default)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct TomlTarget {
         cc: Option<String>,
@@ -1187,7 +1187,7 @@ fn set<T>(field: &mut T, val: Option<T>) {
 
 fn threads_from_config(v: u32) -> u32 {
     match v {
-        0 => num_cpus::get() as u32,
+        0 => std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32,
         n => n,
     }
 }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 9180c5f03af..74528f2752f 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -208,7 +208,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
         let j_msg = format!(
             "number of jobs to run in parallel; \
              defaults to {} (this host's logical CPU count)",
-            num_cpus::get()
+            std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
         );
         opts.optopt("j", "jobs", &j_msg, "JOBS");
         opts.optflag("h", "help", "print this help message");
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index abfac2a5897..a1f0bfd8f26 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -922,7 +922,9 @@ impl Build {
     /// Returns the number of parallel jobs that have been configured for this
     /// build.
     fn jobs(&self) -> u32 {
-        self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32)
+        self.config.jobs.unwrap_or_else(|| {
+            std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
+        })
     }
 
     fn debuginfo_map_to(&self, which: GitRepo) -> Option<String> {
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 2394c5e020d..08d08158062 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -24,7 +24,7 @@ const OS: Option<&str> = None;
 
 type ToolstateData = HashMap<Box<str>, ToolState>;
 
-#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
+#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
 #[serde(rename_all = "kebab-case")]
 /// Whether a tool can be compiled, tested or neither
 pub enum ToolState {
@@ -50,13 +50,6 @@ impl fmt::Display for ToolState {
     }
 }
 
-impl Default for ToolState {
-    fn default() -> Self {
-        // err on the safe side
-        ToolState::BuildFail
-    }
-}
-
 /// Number of days after the last promotion of beta.
 /// Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens.
 /// The Wednesday after this has value 0.
@@ -466,13 +459,11 @@ fn publish_test_results(current_toolstate: &ToolstateData) {
     t!(fs::write(&history_path, file));
 }
 
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Deserialize)]
 struct RepoState {
     tool: String,
     windows: ToolState,
     linux: ToolState,
-    commit: String,
-    datetime: String,
 }
 
 impl RepoState {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 78928fb4059..c0e7cd0b1f5 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1506,11 +1506,11 @@ impl Type {
     }
 
     crate fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
-        let (self_, trait_, assoc) = match self {
-            QPath { self_type, trait_, assoc, .. } => (self_type, trait_, assoc),
-            _ => return None,
-        };
-        Some((&self_, trait_.def_id(), *assoc.clone()))
+        if let QPath { self_type, trait_, assoc, .. } = self {
+            Some((&self_type, trait_.def_id(), *assoc.clone()))
+        } else {
+            None
+        }
     }
 
     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
diff --git a/src/test/ui/issues/issue-87707.rs b/src/test/ui/issues/issue-87707.rs
new file mode 100644
index 00000000000..d2e9343f86c
--- /dev/null
+++ b/src/test/ui/issues/issue-87707.rs
@@ -0,0 +1,15 @@
+// test for #87707
+// edition:2018
+// run-fail
+// check-run-results
+
+use std::sync::Once;
+use std::panic;
+
+fn main() {
+    let o = Once::new();
+    let _ = panic::catch_unwind(|| {
+        o.call_once(|| panic!("Here Once instance is poisoned."));
+    });
+    o.call_once(|| {});
+}
diff --git a/src/test/ui/issues/issue-87707.run.stderr b/src/test/ui/issues/issue-87707.run.stderr
new file mode 100644
index 00000000000..8f82ccc0c2a
--- /dev/null
+++ b/src/test/ui/issues/issue-87707.run.stderr
@@ -0,0 +1,3 @@
+thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:12:24
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:14:7
diff --git a/src/test/ui/parser/trailing-question-in-macro-type.rs b/src/test/ui/parser/trailing-question-in-macro-type.rs
new file mode 100644
index 00000000000..e2a681ddd11
--- /dev/null
+++ b/src/test/ui/parser/trailing-question-in-macro-type.rs
@@ -0,0 +1,14 @@
+macro_rules! fn_expr {
+    ($return_type:ty : $body:expr) => {
+        (|| -> $return_type { $body })()
+    };
+    ($body:expr) => {
+        (|| $body)()
+    };
+}
+
+
+fn main() {
+    fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) };
+    //~^ ERROR cannot find value `o` in this scope
+}
diff --git a/src/test/ui/parser/trailing-question-in-macro-type.stderr b/src/test/ui/parser/trailing-question-in-macro-type.stderr
new file mode 100644
index 00000000000..c096ae04fbb
--- /dev/null
+++ b/src/test/ui/parser/trailing-question-in-macro-type.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `o` in this scope
+  --> $DIR/trailing-question-in-macro-type.rs:12:15
+   |
+LL |     fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) };
+   |               ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml
index c022d3aa0ac..c437bde5ae6 100644
--- a/src/tools/build-manifest/Cargo.toml
+++ b/src/tools/build-manifest/Cargo.toml
@@ -13,4 +13,3 @@ tar = "0.4.29"
 sha2 = "0.10.1"
 rayon = "1.5.1"
 hex = "0.4.2"
-num_cpus = "1.13.0"
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 8a62146abfc..378efeb6443 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -208,7 +208,7 @@ fn main() {
     let num_threads = if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") {
         num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS")
     } else {
-        num_cpus::get()
+        std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
     };
     rayon::ThreadPoolBuilder::new()
         .num_threads(num_threads)