diff --git a/Cargo.lock b/Cargo.lock index 8ca6f26e326d1..2ee9a872d3ee2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -214,14 +214,12 @@ dependencies = [ name = "bootstrap" version = "0.0.0" dependencies = [ - "build_helper", "cc", "cmake", "filetime", "getopts", "ignore", "libc", - "num_cpus", "once_cell", "opener", "pretty_assertions", @@ -249,7 +247,6 @@ dependencies = [ "anyhow", "flate2", "hex 0.4.2", - "num_cpus", "rayon", "serde", "serde_json", @@ -258,10 +255,6 @@ dependencies = [ "toml", ] -[[package]] -name = "build_helper" -version = "0.1.0" - [[package]] name = "bump-stage0" version = "0.1.0" @@ -3893,7 +3886,6 @@ dependencies = [ name = "rustc_llvm" version = "0.0.0" dependencies = [ - "build_helper", "cc", "libc", ] @@ -4242,7 +4234,6 @@ name = "rustc_session" version = "0.0.0" dependencies = [ "getopts", - "num_cpus", "rustc_ast", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index d8dfcc84e68da..34556df3c6d79 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -11,5 +11,4 @@ emscripten = [] libc = "0.2.73" [build-dependencies] -build_helper = { path = "../../src/build_helper" } cc = "1.0.69" diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 3b6808d693f21..ac758c15cca78 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -1,8 +1,8 @@ use std::env; +use std::ffi::{OsStr, OsString}; +use std::fmt::Display; use std::path::{Path, PathBuf}; -use std::process::Command; - -use build_helper::{output, tracked_env_var_os}; +use std::process::{Command, Stdio}; fn detect_llvm_link() -> (&'static str, &'static str) { // Force the link mode we want, preferring static by default, but @@ -14,13 +14,74 @@ fn detect_llvm_link() -> (&'static str, &'static str) { } } +// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may +// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM +// shared library, which means that when our freshly built llvm-config goes to load it's +// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first +// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from +// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't +// perfect -- we might actually want to see something from Cargo's added library paths -- but +// for now it works. +fn restore_library_path() { + let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR"); + if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") { + env::set_var(&key, &env); + } else { + env::remove_var(&key); + } +} + +/// Reads an environment variable and adds it to dependencies. +/// Supposed to be used for all variables except those set for build scripts by cargo +/// +fn tracked_env_var_os + Display>(key: K) -> Option { + println!("cargo:rerun-if-env-changed={}", key); + env::var_os(key) +} + +fn rerun_if_changed_anything_in_dir(dir: &Path) { + let mut stack = dir + .read_dir() + .unwrap() + .map(|e| e.unwrap()) + .filter(|e| &*e.file_name() != ".git") + .collect::>(); + while let Some(entry) = stack.pop() { + let path = entry.path(); + if entry.file_type().unwrap().is_dir() { + stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); + } else { + println!("cargo:rerun-if-changed={}", path.display()); + } + } +} + +#[track_caller] +fn output(cmd: &mut Command) -> String { + let output = match cmd.stderr(Stdio::inherit()).output() { + Ok(status) => status, + Err(e) => { + println!("\n\nfailed to execute command: {:?}\nerror: {}\n\n", cmd, e); + std::process::exit(1); + } + }; + if !output.status.success() { + panic!( + "command did not execute successfully: {:?}\n\ + expected success, got: {}", + cmd, output.status + ); + } + String::from_utf8(output.stdout).unwrap() +} + fn main() { if tracked_env_var_os("RUST_CHECK").is_some() { // If we're just running `check`, there's no need for LLVM to be built. return; } - build_helper::restore_library_path(); + restore_library_path(); let target = env::var("TARGET").expect("TARGET was not set"); let llvm_config = @@ -160,7 +221,7 @@ fn main() { cfg.debug(false); } - build_helper::rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper")); + rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper")); cfg.file("llvm-wrapper/PassWrapper.cpp") .file("llvm-wrapper/RustWrapper.cpp") .file("llvm-wrapper/ArchiveWrapper.cpp") diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c7aa9ffc7937d..40daf4eb28fc1 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, - is_as_cast: IsAsCast, + recover_question_mark: RecoverQuestionMark, ) -> P { - 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 83e0a4997ad85..40902fa183313 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 0b01f9e927f33..436c5bd4fcac2 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> { + 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> { 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> { 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 37cfc4a0dc3c2..6b1eaa4d399d9 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 17eec333e0980..c42a1530451d6 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/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 1dba24dd14907..c02a6f2d78c64 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -172,6 +172,7 @@ impl_fn_for_zst! { /// documentation for more information. #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] #[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct EscapeAscii<'a> { inner: iter::FlatMap, ascii::EscapeDefault, EscapeByte>, } diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 0298bba8d329e..3d781c9591977 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -498,7 +498,7 @@ unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { /// /// use std::slice; /// -/// slice::range(2..1, ..3); +/// let _ = slice::range(2..1, ..3); /// ``` /// /// ```should_panic @@ -506,7 +506,7 @@ unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { /// /// use std::slice; /// -/// slice::range(1..4, ..3); +/// let _ = slice::range(1..4, ..3); /// ``` /// /// ```should_panic @@ -514,12 +514,13 @@ unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { /// /// use std::slice; /// -/// slice::range(1..=usize::MAX, ..3); +/// let _ = slice::range(1..=usize::MAX, ..3); /// ``` /// /// [`Index::index`]: ops::Index::index #[track_caller] #[unstable(feature = "slice_range", issue = "76393")] +#[must_use] pub fn range(range: R, bounds: ops::RangeTo) -> ops::Range where R: ops::RangeBounds, diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index d260cc69469cf..c89cb6794b282 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -62,6 +62,7 @@ fn size_from_ptr(_: *const T) -> usize { /// [`iter`]: slice::iter /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { ptr: NonNull, end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that @@ -182,6 +183,7 @@ impl AsRef<[T]> for Iter<'_, T> { /// [`iter_mut`]: slice::iter_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, T: 'a> { ptr: NonNull, end: *mut T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that @@ -339,6 +341,7 @@ pub(super) trait SplitIter: DoubleEndedIterator { /// [`split`]: slice::split /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Split<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -469,6 +472,7 @@ impl FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {} /// [`split_inclusive`]: slice::split_inclusive /// [slices]: slice #[stable(feature = "split_inclusive", since = "1.51.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitInclusive<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -589,6 +593,7 @@ impl FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool /// [`split_mut`]: slice::split_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -718,6 +723,7 @@ impl FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {} /// [`split_inclusive_mut`]: slice::split_inclusive_mut /// [slices]: slice #[stable(feature = "split_inclusive", since = "1.51.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitInclusiveMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -841,6 +847,7 @@ impl FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> b /// [`rsplit`]: slice::rsplit /// [slices]: slice #[stable(feature = "slice_rsplit", since = "1.27.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplit<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -937,6 +944,7 @@ impl FusedIterator for RSplit<'_, T, P> where P: FnMut(&T) -> bool {} /// [`rsplit_mut`]: slice::rsplit_mut /// [slices]: slice #[stable(feature = "slice_rsplit", since = "1.27.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplitMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1059,6 +1067,7 @@ impl> Iterator for GenericSplitN { /// [`splitn`]: slice::splitn /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1099,6 +1108,7 @@ where /// [`rsplitn`]: slice::rsplitn /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1138,6 +1148,7 @@ where /// [`splitn_mut`]: slice::splitn_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1178,6 +1189,7 @@ where /// [`rsplitn_mut`]: slice::rsplitn_mut /// [slices]: slice #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -1222,6 +1234,7 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] } /// [slices]: slice #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Windows<'a, T: 'a> { v: &'a [T], size: NonZeroUsize, @@ -1370,6 +1383,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Windows<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Chunks<'a, T: 'a> { v: &'a [T], chunk_size: usize, @@ -1553,6 +1567,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Chunks<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunksMut<'a, T: 'a> { v: &'a mut [T], chunk_size: usize, @@ -1722,6 +1737,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksMut<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "chunks_exact", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunksExact<'a, T: 'a> { v: &'a [T], rem: &'a [T], @@ -1881,6 +1897,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExact<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "chunks_exact", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunksExactMut<'a, T: 'a> { v: &'a mut [T], rem: &'a mut [T], @@ -2034,6 +2051,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExactMut<'a, T> { /// [slices]: slice #[derive(Debug, Clone, Copy)] #[unstable(feature = "array_windows", issue = "75027")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayWindows<'a, T: 'a, const N: usize> { slice_head: *const T, num: usize, @@ -2156,6 +2174,7 @@ impl ExactSizeIterator for ArrayWindows<'_, T, N> { /// [slices]: slice #[derive(Debug)] #[unstable(feature = "array_chunks", issue = "74985")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayChunks<'a, T: 'a, const N: usize> { iter: Iter<'a, [T; N]>, rem: &'a [T], @@ -2282,6 +2301,7 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunks<' /// [slices]: slice #[derive(Debug)] #[unstable(feature = "array_chunks", issue = "74985")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayChunksMut<'a, T: 'a, const N: usize> { iter: IterMut<'a, [T; N]>, rem: &'a mut [T], @@ -2396,6 +2416,7 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunksMu /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunks<'a, T: 'a> { v: &'a [T], chunk_size: usize, @@ -2569,6 +2590,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunks<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunksMut<'a, T: 'a> { v: &'a mut [T], chunk_size: usize, @@ -2742,6 +2764,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksMut<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunksExact<'a, T: 'a> { v: &'a [T], rem: &'a [T], @@ -2905,6 +2928,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExact<'a, T> { /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct RChunksExactMut<'a, T: 'a> { v: &'a mut [T], rem: &'a mut [T], @@ -3071,6 +3095,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> { /// [`group_by`]: slice::group_by /// [slices]: slice #[unstable(feature = "slice_group_by", issue = "80552")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct GroupBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, @@ -3157,6 +3182,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> { /// [`group_by_mut`]: slice::group_by_mut /// [slices]: slice #[unstable(feature = "slice_group_by", issue = "80552")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct GroupByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 08b95d791a38c..5a46a99b5a4d6 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -125,6 +125,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")] #[inline] + #[must_use] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) pub const fn len(&self) -> usize { // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable. @@ -148,6 +149,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.39.0")] #[inline] + #[must_use] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -166,6 +168,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn first(&self) -> Option<&T> { if let [first, ..] = self { Some(first) } else { None } } @@ -185,6 +188,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn first_mut(&mut self) -> Option<&mut T> { if let [first, ..] = self { Some(first) } else { None } } @@ -204,6 +208,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn split_first(&self) -> Option<(&T, &[T])> { if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } @@ -225,6 +230,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } @@ -244,6 +250,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn split_last(&self) -> Option<(&T, &[T])> { if let [init @ .., last] = self { Some((last, init)) } else { None } } @@ -265,6 +272,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { if let [init @ .., last] = self { Some((last, init)) } else { None } } @@ -283,6 +291,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] #[inline] + #[must_use] pub const fn last(&self) -> Option<&T> { if let [.., last] = self { Some(last) } else { None } } @@ -302,6 +311,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] + #[must_use] pub const fn last_mut(&mut self) -> Option<&mut T> { if let [.., last] = self { Some(last) } else { None } } @@ -325,6 +335,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[must_use] pub fn get(&self, index: I) -> Option<&I::Output> where I: SliceIndex, @@ -349,6 +360,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[must_use] pub fn get_mut(&mut self, index: I) -> Option<&mut I::Output> where I: SliceIndex, @@ -380,6 +392,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[must_use] pub unsafe fn get_unchecked(&self, index: I) -> &I::Output where I: SliceIndex, @@ -416,6 +429,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[must_use] pub unsafe fn get_unchecked_mut(&mut self, index: I) -> &mut I::Output where I: SliceIndex, @@ -455,6 +469,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")] #[inline] + #[must_use] pub const fn as_ptr(&self) -> *const T { self as *const [T] as *const T } @@ -483,6 +498,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] #[inline] + #[must_use] pub const fn as_mut_ptr(&mut self) -> *mut T { self as *mut [T] as *mut T } @@ -518,6 +534,7 @@ impl [T] { #[stable(feature = "slice_ptr_range", since = "1.48.0")] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] #[inline] + #[must_use] pub const fn as_ptr_range(&self) -> Range<*const T> { let start = self.as_ptr(); // SAFETY: The `add` here is safe, because: @@ -560,6 +577,7 @@ impl [T] { #[stable(feature = "slice_ptr_range", since = "1.48.0")] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] #[inline] + #[must_use] pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> { let start = self.as_mut_ptr(); // SAFETY: See as_ptr_range() above for why `add` here is safe. @@ -945,6 +963,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub unsafe fn as_chunks_unchecked(&self) -> &[[T; N]] { debug_assert_ne!(N, 0); debug_assert_eq!(self.len() % N, 0); @@ -976,6 +995,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_chunks(&self) -> (&[[T; N]], &[T]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1006,6 +1026,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_rchunks(&self) -> (&[T], &[[T; N]]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1081,6 +1102,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub unsafe fn as_chunks_unchecked_mut(&mut self) -> &mut [[T; N]] { debug_assert_ne!(N, 0); debug_assert_eq!(self.len() % N, 0); @@ -1118,6 +1140,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_chunks_mut(&mut self) -> (&mut [[T; N]], &mut [T]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1154,6 +1177,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] + #[must_use] pub fn as_rchunks_mut(&mut self) -> (&mut [T], &mut [[T; N]]) { assert_ne!(N, 0); let len = self.len() / N; @@ -1512,6 +1536,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] + #[must_use] pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which @@ -1543,6 +1568,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] + #[must_use] pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which @@ -1594,6 +1620,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] #[inline] + #[must_use] pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { // SAFETY: Caller has to check that `0 <= mid <= self.len()` unsafe { (self.get_unchecked(..mid), self.get_unchecked(mid..)) } @@ -1634,6 +1661,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] #[inline] + #[must_use] pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { let len = self.len(); let ptr = self.as_mut_ptr(); @@ -1683,6 +1711,7 @@ impl [T] { #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] #[track_caller] + #[must_use] pub fn split_array_ref(&self) -> (&[T; N], &[T]) { let (a, b) = self.split_at(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at) @@ -1715,6 +1744,7 @@ impl [T] { #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] #[track_caller] + #[must_use] pub fn split_array_mut(&mut self) -> (&mut [T; N], &mut [T]) { let (a, b) = self.split_at_mut(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) @@ -1759,6 +1789,7 @@ impl [T] { /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] + #[must_use] pub fn rsplit_array_ref(&self) -> (&[T], &[T; N]) { assert!(N <= self.len()); let (a, b) = self.split_at(self.len() - N); @@ -1792,6 +1823,7 @@ impl [T] { /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] + #[must_use] pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; N]) { assert!(N <= self.len()); let (a, b) = self.split_at_mut(self.len() - N); @@ -2123,6 +2155,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[must_use] pub fn contains(&self, x: &T) -> bool where T: PartialEq, @@ -2151,6 +2184,7 @@ impl [T] { /// assert!(v.starts_with(&[])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq, @@ -2180,6 +2214,7 @@ impl [T] { /// assert!(v.ends_with(&[])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq, @@ -3387,6 +3422,7 @@ impl [T] { /// } /// ``` #[stable(feature = "slice_align_to", since = "1.30.0")] + #[must_use] pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { // Note that most of this function will be constant-evaluated, if mem::size_of::() == 0 || mem::size_of::() == 0 { @@ -3447,6 +3483,7 @@ impl [T] { /// } /// ``` #[stable(feature = "slice_align_to", since = "1.30.0")] + #[must_use] pub unsafe fn align_to_mut(&mut self) -> (&mut [T], &mut [U], &mut [T]) { // Note that most of this function will be constant-evaluated, if mem::size_of::() == 0 || mem::size_of::() == 0 { @@ -3541,6 +3578,7 @@ impl [T] { /// ``` #[unstable(feature = "portable_simd", issue = "86656")] #[cfg(not(miri))] // Miri does not support all SIMD intrinsics + #[must_use] pub fn as_simd(&self) -> (&[T], &[Simd], &[T]) where Simd: AsRef<[T; LANES]>, @@ -3585,6 +3623,7 @@ impl [T] { /// method for something like `LANES == 3`. #[unstable(feature = "portable_simd", issue = "86656")] #[cfg(not(miri))] // Miri does not support all SIMD intrinsics + #[must_use] pub fn as_simd_mut(&mut self) -> (&mut [T], &mut [Simd], &mut [T]) where Simd: AsMut<[T; LANES]>, @@ -3624,6 +3663,7 @@ impl [T] { /// ``` #[inline] #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[must_use] pub fn is_sorted(&self) -> bool where T: PartialOrd, @@ -3639,6 +3679,7 @@ impl [T] { /// /// [`is_sorted`]: slice::is_sorted #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[must_use] pub fn is_sorted_by(&self, mut compare: F) -> bool where F: FnMut(&T, &T) -> Option, @@ -3664,6 +3705,7 @@ impl [T] { /// ``` #[inline] #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[must_use] pub fn is_sorted_by_key(&self, f: F) -> bool where F: FnMut(&T) -> K, @@ -3701,6 +3743,7 @@ impl [T] { /// assert!(v[i..].iter().all(|&x| !(x < 5))); /// ``` #[stable(feature = "partition_point", since = "1.52.0")] + #[must_use] pub fn partition_point

(&self, mut pred: P) -> usize where P: FnMut(&T) -> bool, diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 39c8d68e4bf34..6744400c304a1 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -85,6 +85,7 @@ use crate::ptr; #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +#[must_use] pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_check_data_len(data, len); @@ -124,6 +125,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +#[must_use] pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_check_data_len(data as _, len); @@ -168,6 +170,7 @@ const fn debug_check_data_len(_data: *const T, _len: usize) {} /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] #[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +#[must_use] pub const fn from_ref(s: &T) -> &[T] { array::from_ref(s) } @@ -175,6 +178,7 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] #[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +#[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { array::from_mut(s) } diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 06a30d7096c77..fc0acc8048081 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2344,7 +2344,7 @@ fn slice_rsplit_array_mut() { fn slice_split_array_ref_out_of_bounds() { let v = &[1, 2, 3, 4, 5, 6][..]; - v.split_array_ref::<7>(); + let _ = v.split_array_ref::<7>(); } #[should_panic] @@ -2352,7 +2352,7 @@ fn slice_split_array_ref_out_of_bounds() { fn slice_split_array_mut_out_of_bounds() { let v = &mut [1, 2, 3, 4, 5, 6][..]; - v.split_array_mut::<7>(); + let _ = v.split_array_mut::<7>(); } #[should_panic] @@ -2360,7 +2360,7 @@ fn slice_split_array_mut_out_of_bounds() { fn slice_rsplit_array_ref_out_of_bounds() { let v = &[1, 2, 3, 4, 5, 6][..]; - v.rsplit_array_ref::<7>(); + let _ = v.rsplit_array_ref::<7>(); } #[should_panic] @@ -2368,7 +2368,7 @@ fn slice_rsplit_array_ref_out_of_bounds() { fn slice_rsplit_array_mut_out_of_bounds() { let v = &mut [1, 2, 3, 4, 5, 6][..]; - v.rsplit_array_mut::<7>(); + let _ = v.rsplit_array_mut::<7>(); } macro_rules! take_tests { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 10fec8e115245..4df5f2a8df4a5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -212,7 +212,6 @@ #![needs_panic_runtime] // std may use features in a platform-specific way #![allow(unused_features)] -#![feature(rustc_allow_const_fn_unstable)] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), @@ -222,22 +221,16 @@ // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. -#![feature(absolute_path)] #![feature(alloc_error_handler)] #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(arbitrary_self_types)] #![feature(array_error_internals)] #![feature(assert_matches)] -#![feature(associated_type_bounds)] #![feature(async_iterator)] -#![feature(atomic_mut_ptr)] -#![feature(auto_traits)] #![feature(bench_black_box)] -#![feature(bool_to_option)] #![feature(box_syntax)] #![feature(c_unwind)] #![feature(c_variadic)] @@ -248,7 +241,6 @@ #![feature(char_internals)] #![feature(concat_bytes)] #![feature(concat_idents)] -#![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] #![feature(const_fn_trait_bound)] #![feature(const_format_args)] @@ -257,10 +249,8 @@ #![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(const_option)] -#![feature(const_mut_refs)] #![feature(const_socketaddr)] #![feature(const_trait_impl)] -#![feature(container_error_extra)] #![feature(c_size_t)] #![feature(core_ffi_c)] #![feature(core_intrinsics)] @@ -279,24 +269,17 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] -#![feature(fn_traits)] #![feature(float_minimum_maximum)] #![feature(format_args_nl)] -#![feature(gen_future)] -#![feature(generator_trait)] #![feature(get_mut_unchecked)] #![feature(hashmap_internals)] #![feature(int_error_internals)] -#![feature(integer_atomics)] -#![feature(int_log)] -#![feature(into_future)] #![feature(intra_doc_pointers)] #![feature(lang_items)] #![feature(linkage)] #![feature(log_syntax)] #![feature(map_try_insert)] #![feature(maybe_uninit_slice)] -#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] #![feature(mixed_integer_ops)] @@ -316,19 +299,14 @@ #![feature(portable_simd)] #![feature(prelude_import)] #![feature(ptr_as_uninit)] -#![feature(ptr_internals)] #![feature(raw_os_nonzero)] #![feature(rustc_attrs)] -#![feature(rustc_private)] #![feature(saturating_int_impl)] -#![feature(slice_concat_ext)] #![feature(slice_internals)] #![feature(slice_ptr_get)] -#![feature(slice_ptr_len)] #![feature(staged_api)] #![feature(std_internals)] #![feature(stdsimd)] -#![feature(stmt_expr_attributes)] #![feature(str_internals)] #![feature(test)] #![feature(thread_local)] @@ -338,8 +316,6 @@ #![feature(trace_macros)] #![feature(try_blocks)] #![feature(try_reserve_kind)] -#![feature(unboxed_closures)] -#![feature(unwrap_infallible)] #![feature(vec_into_raw_parts)] // NB: the above list is sorted to minimize merge conflicts. #![default_lib_allocator] diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 09d1e714ab6dd..5ffc86b4560fc 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1443,13 +1443,18 @@ impl JoinHandle { 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 9dd7c15fc5922..ea9623be63bc7 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 4f2c81731a335..3323ba36bf310 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 592a137e379de..fe9d6a727ed1e 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -34,10 +34,8 @@ path = "bin/llvm-config-wrapper.rs" test = false [dependencies] -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/builder.rs b/src/bootstrap/builder.rs index 0d387ff1e37c2..4c49ed2d6a297 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -11,8 +11,6 @@ use std::path::{Component, Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; -use build_helper::{output, t}; - use crate::cache::{Cache, Interned, INTERNER}; use crate::check; use crate::compile; @@ -25,7 +23,7 @@ use crate::native; use crate::run; use crate::test; use crate::tool::{self, SourceType}; -use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir}; +use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 8c47f625d732b..7ce446876118a 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -26,9 +26,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::{env, iter}; -use build_helper::output; - use crate::config::{Target, TargetSelection}; +use crate::util::output; use crate::{Build, CLang, GitRepo}; // The `cc` crate doesn't provide a way to obtain a path to the detected archiver, diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 6478578c3c402..1932a0017ee25 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -8,8 +8,7 @@ use std::path::Path; use std::process::Command; -use build_helper::output; - +use crate::util::output; use crate::Build; pub enum GitInfo { diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 3b73dc1c7df74..069f3d6acf158 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -9,8 +9,7 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; -use build_helper::t; - +use crate::util::t; use crate::Build; pub fn clean(build: &Build, all: bool) { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9971778034601..9cfd9f92aa7cd 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -16,7 +16,6 @@ use std::path::{Path, PathBuf}; use std::process::{exit, Command, Stdio}; use std::str; -use build_helper::{output, t, up_to_date}; use serde::Deserialize; use crate::builder::Cargo; @@ -26,7 +25,7 @@ use crate::config::{LlvmLibunwind, TargetSelection}; use crate::dist; use crate::native; use crate::tool::SourceType; -use crate::util::{exe, is_debug_info, is_dylib, symlink_dir}; +use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date}; use crate::LLVM_TOOLS; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d6f77fe6cd6d0..a3599b6d1fae3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -17,8 +17,7 @@ use crate::cache::{Interned, INTERNER}; use crate::channel::GitInfo; pub use crate::flags::Subcommand; use crate::flags::{Color, Flags}; -use crate::util::exe; -use build_helper::t; +use crate::util::{exe, t}; use serde::Deserialize; macro_rules! check_ci_llvm { @@ -1187,7 +1186,7 @@ fn set(field: &mut T, val: Option) { 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/dist.rs b/src/bootstrap/dist.rs index 8693e85e4742f..45c924ce93c55 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -14,15 +14,13 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::{output, t}; - use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::TargetSelection; use crate::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::tool::{self, Tool}; -use crate::util::{exe, is_dylib, timeit}; +use crate::util::{exe, is_dylib, output, t, timeit}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 23b5ddcd47a0e..be55871b56a28 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -12,15 +12,13 @@ use std::fs; use std::io; use std::path::{Path, PathBuf}; -use crate::Mode; -use build_helper::{t, up_to_date}; - use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::{Config, TargetSelection}; use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; -use crate::util::symlink_dir; +use crate::util::{symlink_dir, t, up_to_date}; +use crate::Mode; macro_rules! submodule_helper { ($path:expr, submodule) => { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 9180c5f03af68..e34b40a93ff47 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -7,12 +7,12 @@ use std::env; use std::path::PathBuf; use std::process; -use build_helper::t; use getopts::Options; use crate::builder::Builder; use crate::config::{Config, TargetSelection}; use crate::setup::Profile; +use crate::util::t; use crate::{Build, DocTests}; pub enum Color { @@ -208,7 +208,7 @@ To learn more about a subcommand, run `./x.py -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/format.rs b/src/bootstrap/format.rs index 530cc829320d1..10b846e6db208 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -1,7 +1,7 @@ //! Runs rustfmt on the repository. +use crate::util::{output, t}; use crate::Build; -use build_helper::{output, t}; use ignore::WalkBuilder; use std::collections::VecDeque; use std::path::{Path, PathBuf}; diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 06acf1a9a0083..27b9196d9868e 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -8,7 +8,7 @@ use std::fs; use std::path::{Component, PathBuf}; use std::process::Command; -use build_helper::t; +use crate::util::t; use crate::dist::{self, sanitize_sh}; use crate::tarball::GeneratedTarball; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index abfac2a589793..17799cd93c075 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -116,12 +116,13 @@ use std::os::unix::fs::symlink as symlink_file; #[cfg(windows)] use std::os::windows::fs::symlink_file; -use build_helper::{mtime, output, run, run_suppressed, t, try_run, try_run_suppressed}; use filetime::FileTime; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; -use crate::util::{exe, libdir, CiEnv}; +use crate::util::{ + exe, libdir, mtime, output, run, run_suppressed, t, try_run, try_run_suppressed, CiEnv, +}; mod builder; mod cache; @@ -922,7 +923,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 { diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 65e229697dc87..59dc50be47f06 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -1,10 +1,10 @@ use std::path::PathBuf; use std::process::Command; -use build_helper::output; use serde::Deserialize; use crate::cache::INTERNER; +use crate::util::output; use crate::{Build, Crate}; #[derive(Deserialize)] diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index a751a6e3ece7f..d27ad9644b56c 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -16,13 +16,10 @@ use std::io; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::{output, t}; - use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::config::TargetSelection; -use crate::util::{self, exe}; +use crate::util::{self, exe, output, t, up_to_date}; use crate::{CLang, GitRepo}; -use build_helper::up_to_date; pub struct Meta { stamp: HashStamp, diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index 11b393857e74c..25abe7a72fdc8 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -1,7 +1,7 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::dist::distdir; use crate::tool::Tool; -use build_helper::output; +use crate::util::output; use std::process::Command; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index d7db2cef24f2b..8c2899c1ac01e 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -15,10 +15,9 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use build_helper::output; - use crate::cache::INTERNER; use crate::config::Target; +use crate::util::output; use crate::Build; pub struct Finder { diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs index 9ff5c2327e0f7..c743c5188e754 100644 --- a/src/bootstrap/tarball.rs +++ b/src/bootstrap/tarball.rs @@ -3,9 +3,8 @@ use std::{ process::Command, }; -use build_helper::t; - use crate::builder::Builder; +use crate::util::t; #[derive(Copy, Clone)] pub(crate) enum OverlayKind { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 19d98df3ce902..e4fcb287f1228 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -11,8 +11,6 @@ use std::iter; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use build_helper::{self, output, t}; - use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::Interned; use crate::compile; @@ -22,7 +20,7 @@ use crate::flags::Subcommand; use crate::native; use crate::tool::{self, SourceType, Tool}; use crate::toolstate::ToolState; -use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var}; +use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t}; use crate::Crate as CargoCrate; use crate::{envify, CLang, DocTests, GitRepo, Mode}; @@ -2306,9 +2304,7 @@ impl Step for Distcheck { .current_dir(&dir), ); builder.run( - Command::new(build_helper::make(&builder.config.build.triple)) - .arg("check") - .current_dir(&dir), + Command::new(util::make(&builder.config.build.triple)).arg("check").current_dir(&dir), ); // Now make sure that rust-src has all of libstd's dependencies diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 1317c3f983975..2ae4d830721e8 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -4,14 +4,12 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::{exit, Command}; -use build_helper::t; - use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; use crate::channel::GitInfo; use crate::compile; use crate::config::TargetSelection; use crate::toolstate::ToolState; -use crate::util::{add_dylib_path, exe}; +use crate::util::{add_dylib_path, exe, t}; use crate::Compiler; use crate::Mode; diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 2394c5e020d2b..cf4725253522d 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -1,5 +1,5 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use build_helper::t; +use crate::util::t; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::env; diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 2c78ceb1e5bec..8e770d4d57fa6 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -7,15 +7,38 @@ use std::env; use std::fs; use std::io; use std::path::{Path, PathBuf}; -use std::process::Command; +use std::process::{Command, Stdio}; use std::str; -use std::time::Instant; - -use build_helper::t; +use std::time::{Instant, SystemTime, UNIX_EPOCH}; use crate::builder::Builder; use crate::config::{Config, TargetSelection}; +/// A helper macro to `unwrap` a result except also print out details like: +/// +/// * The file/line of the panic +/// * The expression that failed +/// * The error itself +/// +/// This is currently used judiciously throughout the build system rather than +/// using a `Result` with `try!`, but this may change one day... +macro_rules! t { + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; + // it can show extra info in the second parameter + ($e:expr, $extra:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra), + } + }; +} +pub(crate) use t; + /// Given an executable called `name`, return the filename for the /// executable for a particular target. pub fn exe(name: &str, target: TargetSelection) -> String { @@ -301,3 +324,119 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( _ => None, } } + +pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { + if !try_run(cmd, print_cmd_on_fail) { + std::process::exit(1); + } +} + +pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { + let status = match cmd.status() { + Ok(status) => status, + Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), + }; + if !status.success() && print_cmd_on_fail { + println!( + "\n\ncommand did not execute successfully: {:?}\n\ + expected success, got: {}\n\n", + cmd, status + ); + } + status.success() +} + +pub fn run_suppressed(cmd: &mut Command) { + if !try_run_suppressed(cmd) { + std::process::exit(1); + } +} + +pub fn try_run_suppressed(cmd: &mut Command) -> bool { + let output = match cmd.output() { + Ok(status) => status, + Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), + }; + if !output.status.success() { + println!( + "\n\ncommand did not execute successfully: {:?}\n\ + expected success, got: {}\n\n\ + stdout ----\n{}\n\ + stderr ----\n{}\n\n", + cmd, + output.status, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + } + output.status.success() +} + +pub fn make(host: &str) -> PathBuf { + if host.contains("dragonfly") + || host.contains("freebsd") + || host.contains("netbsd") + || host.contains("openbsd") + { + PathBuf::from("gmake") + } else { + PathBuf::from("make") + } +} + +#[track_caller] +pub fn output(cmd: &mut Command) -> String { + let output = match cmd.stderr(Stdio::inherit()).output() { + Ok(status) => status, + Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), + }; + if !output.status.success() { + panic!( + "command did not execute successfully: {:?}\n\ + expected success, got: {}", + cmd, output.status + ); + } + String::from_utf8(output.stdout).unwrap() +} + +/// Returns the last-modified time for `path`, or zero if it doesn't exist. +pub fn mtime(path: &Path) -> SystemTime { + fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH) +} + +/// Returns `true` if `dst` is up to date given that the file or files in `src` +/// are used to generate it. +/// +/// Uses last-modified time checks to verify this. +pub fn up_to_date(src: &Path, dst: &Path) -> bool { + if !dst.exists() { + return false; + } + let threshold = mtime(dst); + let meta = match fs::metadata(src) { + Ok(meta) => meta, + Err(e) => panic!("source {:?} failed to get metadata: {}", src, e), + }; + if meta.is_dir() { + dir_up_to_date(src, threshold) + } else { + meta.modified().unwrap_or(UNIX_EPOCH) <= threshold + } +} + +fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool { + t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { + let meta = t!(e.metadata()); + if meta.is_dir() { + dir_up_to_date(&e.path(), threshold) + } else { + meta.modified().unwrap_or(UNIX_EPOCH) < threshold + } + }) +} + +fn fail(s: &str) -> ! { + println!("\n\n{}\n\n", s); + std::process::exit(1); +} diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml deleted file mode 100644 index d88df0e08fab3..0000000000000 --- a/src/build_helper/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "build_helper" -version = "0.1.0" -edition = "2021" - -[lib] -path = "lib.rs" diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs deleted file mode 100644 index 24aded547315e..0000000000000 --- a/src/build_helper/lib.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::ffi::{OsStr, OsString}; -use std::fmt::Display; -use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; -use std::time::{SystemTime, UNIX_EPOCH}; -use std::{env, fs}; - -/// A helper macro to `unwrap` a result except also print out details like: -/// -/// * The file/line of the panic -/// * The expression that failed -/// * The error itself -/// -/// This is currently used judiciously throughout the build system rather than -/// using a `Result` with `try!`, but this may change one day... -#[macro_export] -macro_rules! t { - ($e:expr) => { - match $e { - Ok(e) => e, - Err(e) => panic!("{} failed with {}", stringify!($e), e), - } - }; - // it can show extra info in the second parameter - ($e:expr, $extra:expr) => { - match $e { - Ok(e) => e, - Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra), - } - }; -} - -/// Reads an environment variable and adds it to dependencies. -/// Supposed to be used for all variables except those set for build scripts by cargo -/// -pub fn tracked_env_var_os + Display>(key: K) -> Option { - println!("cargo:rerun-if-env-changed={}", key); - env::var_os(key) -} - -// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may -// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM -// shared library, which means that when our freshly built llvm-config goes to load it's -// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first -// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from -// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't -// perfect -- we might actually want to see something from Cargo's added library paths -- but -// for now it works. -pub fn restore_library_path() { - let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR"); - if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") { - env::set_var(&key, &env); - } else { - env::remove_var(&key); - } -} - -pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { - if !try_run(cmd, print_cmd_on_fail) { - std::process::exit(1); - } -} - -pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { - let status = match cmd.status() { - Ok(status) => status, - Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), - }; - if !status.success() && print_cmd_on_fail { - println!( - "\n\ncommand did not execute successfully: {:?}\n\ - expected success, got: {}\n\n", - cmd, status - ); - } - status.success() -} - -pub fn run_suppressed(cmd: &mut Command) { - if !try_run_suppressed(cmd) { - std::process::exit(1); - } -} - -pub fn try_run_suppressed(cmd: &mut Command) -> bool { - let output = match cmd.output() { - Ok(status) => status, - Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), - }; - if !output.status.success() { - println!( - "\n\ncommand did not execute successfully: {:?}\n\ - expected success, got: {}\n\n\ - stdout ----\n{}\n\ - stderr ----\n{}\n\n", - cmd, - output.status, - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) - ); - } - output.status.success() -} - -pub fn make(host: &str) -> PathBuf { - if host.contains("dragonfly") - || host.contains("freebsd") - || host.contains("netbsd") - || host.contains("openbsd") - { - PathBuf::from("gmake") - } else { - PathBuf::from("make") - } -} - -#[track_caller] -pub fn output(cmd: &mut Command) -> String { - let output = match cmd.stderr(Stdio::inherit()).output() { - Ok(status) => status, - Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), - }; - if !output.status.success() { - panic!( - "command did not execute successfully: {:?}\n\ - expected success, got: {}", - cmd, output.status - ); - } - String::from_utf8(output.stdout).unwrap() -} - -pub fn rerun_if_changed_anything_in_dir(dir: &Path) { - let mut stack = dir - .read_dir() - .unwrap() - .map(|e| e.unwrap()) - .filter(|e| &*e.file_name() != ".git") - .collect::>(); - while let Some(entry) = stack.pop() { - let path = entry.path(); - if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } - } -} - -/// Returns the last-modified time for `path`, or zero if it doesn't exist. -pub fn mtime(path: &Path) -> SystemTime { - fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH) -} - -/// Returns `true` if `dst` is up to date given that the file or files in `src` -/// are used to generate it. -/// -/// Uses last-modified time checks to verify this. -pub fn up_to_date(src: &Path, dst: &Path) -> bool { - if !dst.exists() { - return false; - } - let threshold = mtime(dst); - let meta = match fs::metadata(src) { - Ok(meta) => meta, - Err(e) => panic!("source {:?} failed to get metadata: {}", src, e), - }; - if meta.is_dir() { - dir_up_to_date(src, threshold) - } else { - meta.modified().unwrap_or(UNIX_EPOCH) <= threshold - } -} - -fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool { - t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { - let meta = t!(e.metadata()); - if meta.is_dir() { - dir_up_to_date(&e.path(), threshold) - } else { - meta.modified().unwrap_or(UNIX_EPOCH) < threshold - } - }) -} - -fn fail(s: &str) -> ! { - println!("\n\n{}\n\n", s); - std::process::exit(1); -} diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed index 0055758a6a442..6e02a7024b949 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed @@ -2,6 +2,7 @@ // run-rustfix // rustfix-only-machine-applicable +#[allow(unused_must_use)] fn main() { let small = [1, 2]; let big = [0u8; 33]; diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.rs b/src/test/ui/iterators/into-iter-on-arrays-lint.rs index 01857c78a730c..582d5cadd0658 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs @@ -2,6 +2,7 @@ // run-rustfix // rustfix-only-machine-applicable +#[allow(unused_must_use)] fn main() { let small = [1, 2]; let big = [0u8; 33]; diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr index 634728096ed69..e32d35d8638d7 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -1,5 +1,5 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:10:11 + --> $DIR/into-iter-on-arrays-lint.rs:11:11 | LL | small.into_iter(); | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | IntoIterator::into_iter(small); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:13:12 + --> $DIR/into-iter-on-arrays-lint.rs:14:12 | LL | [1, 2].into_iter(); | ^^^^^^^^^ @@ -34,7 +34,7 @@ LL | IntoIterator::into_iter([1, 2]); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:16:9 + --> $DIR/into-iter-on-arrays-lint.rs:17:9 | LL | big.into_iter(); | ^^^^^^^^^ @@ -51,7 +51,7 @@ LL | IntoIterator::into_iter(big); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:19:15 + --> $DIR/into-iter-on-arrays-lint.rs:20:15 | LL | [0u8; 33].into_iter(); | ^^^^^^^^^ @@ -68,7 +68,7 @@ LL | IntoIterator::into_iter([0u8; 33]); | ++++++++++++++++++++++++ ~ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:23:21 + --> $DIR/into-iter-on-arrays-lint.rs:24:21 | LL | Box::new(small).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -77,7 +77,7 @@ LL | Box::new(small).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:26:22 + --> $DIR/into-iter-on-arrays-lint.rs:27:22 | LL | Box::new([1, 2]).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -86,7 +86,7 @@ LL | Box::new([1, 2]).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:29:19 + --> $DIR/into-iter-on-arrays-lint.rs:30:19 | LL | Box::new(big).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -95,7 +95,7 @@ LL | Box::new(big).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:32:25 + --> $DIR/into-iter-on-arrays-lint.rs:33:25 | LL | Box::new([0u8; 33]).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -104,7 +104,7 @@ LL | Box::new([0u8; 33]).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:36:31 + --> $DIR/into-iter-on-arrays-lint.rs:37:31 | LL | Box::new(Box::new(small)).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -113,7 +113,7 @@ LL | Box::new(Box::new(small)).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:39:32 + --> $DIR/into-iter-on-arrays-lint.rs:40:32 | LL | Box::new(Box::new([1, 2])).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -122,7 +122,7 @@ LL | Box::new(Box::new([1, 2])).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:42:29 + --> $DIR/into-iter-on-arrays-lint.rs:43:29 | LL | Box::new(Box::new(big)).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` @@ -131,7 +131,7 @@ LL | Box::new(Box::new(big)).into_iter(); = note: for more information, see warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 - --> $DIR/into-iter-on-arrays-lint.rs:45:35 + --> $DIR/into-iter-on-arrays-lint.rs:46:35 | LL | Box::new(Box::new([0u8; 33])).into_iter(); | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` 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 0000000000000..e2a681ddd1115 --- /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 0000000000000..c096ae04fbbb6 --- /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 c022d3aa0acd7..c437bde5ae69a 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 8a62146abfc4e..378efeb644375 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)