diff --git a/compiler/rustc_mir/src/dataflow/framework/fmt.rs b/compiler/rustc_mir/src/dataflow/framework/fmt.rs index 0140a75054433..35115ca9db756 100644 --- a/compiler/rustc_mir/src/dataflow/framework/fmt.rs +++ b/compiler/rustc_mir/src/dataflow/framework/fmt.rs @@ -33,7 +33,7 @@ pub trait DebugWithContext: Eq + fmt::Debug { } write!(f, "\u{001f}-")?; - self.fmt_with(ctxt, f) + old.fmt_with(ctxt, f) } } diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir/src/dataflow/framework/mod.rs index 344d7b9becd19..a5badc07d1017 100644 --- a/compiler/rustc_mir/src/dataflow/framework/mod.rs +++ b/compiler/rustc_mir/src/dataflow/framework/mod.rs @@ -42,7 +42,7 @@ mod cursor; mod direction; mod engine; pub mod fmt; -mod graphviz; +pub mod graphviz; pub mod lattice; mod visitor; diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs index 03531a6b0049c..4ca757cf269e4 100644 --- a/compiler/rustc_mir/src/dataflow/mod.rs +++ b/compiler/rustc_mir/src/dataflow/mod.rs @@ -5,7 +5,7 @@ use rustc_span::symbol::{sym, Symbol}; pub(crate) use self::drop_flag_effects::*; pub use self::framework::{ - fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState, + fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState, BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects, }; diff --git a/compiler/rustc_mir/src/util/mod.rs b/compiler/rustc_mir/src/util/mod.rs index b7b702431bc2a..3e466b5060feb 100644 --- a/compiler/rustc_mir/src/util/mod.rs +++ b/compiler/rustc_mir/src/util/mod.rs @@ -18,4 +18,4 @@ pub use self::alignment::is_disaligned; pub use self::find_self_call::find_self_call; pub use self::generic_graph::graphviz_safe_def_name; pub use self::graphviz::write_mir_graphviz; -pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere}; +pub use self::pretty::{dump_enabled, dump_mir, write_mir_fn, write_mir_pretty, PassWhere}; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 4e157b0a574fb..ae65222f3f22f 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -15,6 +15,7 @@ use rustc_middle::middle::privacy; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; +use std::mem; // Any local node that may call something in its body block should be // explored. For example, if it's a live Node::Item that is a @@ -395,8 +396,14 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { } fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { + // When inline const blocks are used in pattern position, paths + // referenced by it should be considered as used. + let in_pat = mem::replace(&mut self.in_pat, false); + self.live_symbols.insert(self.tcx.hir().local_def_id(c.hir_id)); intravisit::walk_anon_const(self, c); + + self.in_pat = in_pat; } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7c97a17b45406..a602a58e51712 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2073,20 +2073,85 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { continue; } }); + + struct Lifetime(Span, String); + impl Lifetime { + fn is_unnamed(&self) -> bool { + self.1.starts_with('&') && !self.1.starts_with("&'") + } + fn is_underscore(&self) -> bool { + self.1.starts_with("&'_ ") + } + fn is_named(&self) -> bool { + self.1.starts_with("&'") + } + fn suggestion(&self, sugg: String) -> Option<(Span, String)> { + Some( + match ( + self.is_unnamed(), + self.is_underscore(), + self.is_named(), + sugg.starts_with("&"), + ) { + (true, _, _, false) => (self.span_unnamed_borrow(), sugg), + (true, _, _, true) => { + (self.span_unnamed_borrow(), sugg[1..].to_string()) + } + (_, true, _, false) => { + (self.span_underscore_borrow(), sugg.trim().to_string()) + } + (_, true, _, true) => { + (self.span_underscore_borrow(), sugg[1..].trim().to_string()) + } + (_, _, true, false) => { + (self.span_named_borrow(), sugg.trim().to_string()) + } + (_, _, true, true) => { + (self.span_named_borrow(), sugg[1..].trim().to_string()) + } + _ => return None, + }, + ) + } + fn span_unnamed_borrow(&self) -> Span { + let lo = self.0.lo() + BytePos(1); + self.0.with_lo(lo).with_hi(lo) + } + fn span_named_borrow(&self) -> Span { + let lo = self.0.lo() + BytePos(1); + self.0.with_lo(lo) + } + fn span_underscore_borrow(&self) -> Span { + let lo = self.0.lo() + BytePos(1); + let hi = lo + BytePos(2); + self.0.with_lo(lo).with_hi(hi) + } + } + for param in params { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) { - if snippet.starts_with('&') && !snippet.starts_with("&'") { - introduce_suggestion - .push((param.span, format!("&'a {}", &snippet[1..]))); - } else if let Some(stripped) = snippet.strip_prefix("&'_ ") { - introduce_suggestion.push((param.span, format!("&'a {}", &stripped))); + if let Some((span, sugg)) = + Lifetime(param.span, snippet).suggestion("'a ".to_string()) + { + introduce_suggestion.push((span, sugg)); } } } - for ((span, _), sugg) in spans_with_counts.iter().copied().zip(suggs.iter()) { - if let Some(sugg) = sugg { - introduce_suggestion.push((span, sugg.to_string())); - } + for (span, sugg) in spans_with_counts.iter().copied().zip(suggs.iter()).filter_map( + |((span, _), sugg)| match &sugg { + Some(sugg) => Some((span, sugg.to_string())), + _ => None, + }, + ) { + let (span, sugg) = self + .tcx + .sess + .source_map() + .span_to_snippet(span) + .ok() + .and_then(|snippet| Lifetime(span, snippet).suggestion(sugg.clone())) + .unwrap_or((span, sugg)); + introduce_suggestion.push((span, sugg.to_string())); } err.multipart_suggestion_with_style( &msg, @@ -2159,7 +2224,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { for ((span, _), snippet) in spans_with_counts.iter().copied().zip(snippets.iter()) { match snippet.as_deref() { Some("") => spans_suggs.push((span, "'lifetime, ".to_string())), - Some("&") => spans_suggs.push((span, "&'lifetime ".to_string())), + Some("&") => spans_suggs + .push((span.with_lo(span.lo() + BytePos(1)), "'lifetime ".to_string())), _ => {} } } diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 510e233b43110..77161e961e798 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -520,7 +520,10 @@ pub trait BuildHasher { /// ); /// ``` #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")] - fn hash_one(&self, x: T) -> u64 { + fn hash_one(&self, x: T) -> u64 + where + Self: Sized, + { let mut hasher = self.build_hasher(); x.hash(&mut hasher); hasher.finish() diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 1566d35749017..72ccdd4848a47 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -1,7 +1,7 @@ mod sip; use std::default::Default; -use std::hash::{Hash, Hasher}; +use std::hash::{BuildHasher, Hash, Hasher}; use std::rc::Rc; struct MyHasher { @@ -139,3 +139,10 @@ fn test_indirect_hasher() { } assert_eq!(hasher.hash, 5); } + +#[test] +fn test_build_hasher_object_safe() { + use std::collections::hash_map::{DefaultHasher, RandomState}; + + let _: &dyn BuildHasher = &RandomState::new(); +} diff --git a/library/std/src/env.rs b/library/std/src/env.rs index f9f14d0dc63b4..a746520095559 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -185,9 +185,13 @@ impl fmt::Debug for VarsOs { /// /// # Errors /// -/// Returns `[None]` if the environment variable isn't set. -/// Returns `[None]` if the environment variable is not valid Unicode. If this is not -/// desired, consider using [`var_os`]. +/// This function will return an error if the environment variable isn't set. +/// +/// This function may return an error if the environment variable's name contains +/// the equal sign character (`=`) or the NUL character. +/// +/// This function will return an error if the environment variable's value is +/// not valid Unicode. If this is not desired, consider using [`var_os`]. /// /// # Examples /// @@ -221,8 +225,13 @@ fn _var(key: &OsStr) -> Result { /// /// # Errors /// -/// Returns `[None]` if the variable isn't set. -/// May return `[None]` if the variable value contains the NUL character. +/// This function returns an error if the environment variable isn't set. +/// +/// This function may return an error if the environment variable's name contains +/// the equal sign character (`=`) or the NUL character. +/// +/// This function may return an error if the environment variable's value contains +/// the NUL character. /// /// # Examples /// diff --git a/library/std/src/os/wasi/io.rs b/library/std/src/os/wasi/io.rs index cf4501b98cbd4..b6bc74da8e7b5 100644 --- a/library/std/src/os/wasi/io.rs +++ b/library/std/src/os/wasi/io.rs @@ -6,11 +6,18 @@ use crate::fs; use crate::io; use crate::net; +use crate::os::raw; use crate::sys; use crate::sys_common::{AsInner, FromInner, IntoInner}; /// Raw file descriptors. -pub type RawFd = u32; +/// +/// This has type `c_int` to ease compatibility with code that also compiles on +/// Unix configurations, however unlike Unix and POSIX, in WASI negative file +/// descriptors are valid. Only `-1` is reserved for indicating errors. Code +/// intending to be portable across Unix platforms and WASI should avoid +/// assuming that negative file descriptors are invalid. +pub type RawFd = raw::c_int; /// A trait to extract the raw WASI file descriptor from an underlying /// object. @@ -161,41 +168,41 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as RawFd + libc::STDIN_FILENO } } impl AsRawFd for io::Stdout { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd + libc::STDOUT_FILENO } } impl AsRawFd for io::Stderr { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd + libc::STDERR_FILENO } } impl<'a> AsRawFd for io::StdinLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as RawFd + libc::STDIN_FILENO } } impl<'a> AsRawFd for io::StdoutLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd + libc::STDOUT_FILENO } } impl<'a> AsRawFd for io::StderrLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd + libc::STDERR_FILENO } } diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs index ba66eba2ad38b..1f6ea8d6e8df3 100644 --- a/library/std/src/sys/wasi/fd.rs +++ b/library/std/src/sys/wasi/fd.rs @@ -5,10 +5,11 @@ use super::err2io; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; +use crate::os::raw::c_int; #[derive(Debug)] pub struct WasiFd { - fd: wasi::Fd, + fd: c_int, } fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] { @@ -26,38 +27,38 @@ fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] { } impl WasiFd { - pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd { + pub unsafe fn from_raw(fd: c_int) -> WasiFd { WasiFd { fd } } - pub fn into_raw(self) -> wasi::Fd { + pub fn into_raw(self) -> c_int { let ret = self.fd; mem::forget(self); ret } - pub fn as_raw(&self) -> wasi::Fd { + pub fn as_raw(&self) -> c_int { self.fd } pub fn datasync(&self) -> io::Result<()> { - unsafe { wasi::fd_datasync(self.fd).map_err(err2io) } + unsafe { wasi::fd_datasync(self.fd as wasi::Fd).map_err(err2io) } } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) } + unsafe { wasi::fd_pread(self.fd as wasi::Fd, iovec(bufs), offset).map_err(err2io) } } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) } + unsafe { wasi::fd_pwrite(self.fd as wasi::Fd, ciovec(bufs), offset).map_err(err2io) } } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) } + unsafe { wasi::fd_read(self.fd as wasi::Fd, iovec(bufs)).map_err(err2io) } } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result { - unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) } + unsafe { wasi::fd_write(self.fd as wasi::Fd, ciovec(bufs)).map_err(err2io) } } pub fn seek(&self, pos: SeekFrom) -> io::Result { @@ -66,37 +67,37 @@ impl WasiFd { SeekFrom::End(pos) => (wasi::WHENCE_END, pos), SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) } + unsafe { wasi::fd_seek(self.fd as wasi::Fd, offset, whence).map_err(err2io) } } pub fn tell(&self) -> io::Result { - unsafe { wasi::fd_tell(self.fd).map_err(err2io) } + unsafe { wasi::fd_tell(self.fd as wasi::Fd).map_err(err2io) } } // FIXME: __wasi_fd_fdstat_get pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> { - unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) } + unsafe { wasi::fd_fdstat_set_flags(self.fd as wasi::Fd, flags).map_err(err2io) } } pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> { - unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) } + unsafe { wasi::fd_fdstat_set_rights(self.fd as wasi::Fd, base, inheriting).map_err(err2io) } } pub fn sync(&self) -> io::Result<()> { - unsafe { wasi::fd_sync(self.fd).map_err(err2io) } + unsafe { wasi::fd_sync(self.fd as wasi::Fd).map_err(err2io) } } pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { - unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) } + unsafe { wasi::fd_advise(self.fd as wasi::Fd, offset, len, advice).map_err(err2io) } } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) } + unsafe { wasi::fd_allocate(self.fd as wasi::Fd, offset, len).map_err(err2io) } } pub fn create_directory(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) } + unsafe { wasi::path_create_directory(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn link( @@ -107,7 +108,14 @@ impl WasiFd { new_path: &str, ) -> io::Result<()> { unsafe { - wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io) + wasi::path_link( + self.fd as wasi::Fd, + old_flags, + old_path, + new_fd.fd as wasi::Fd, + new_path, + ) + .map_err(err2io) } } @@ -122,7 +130,7 @@ impl WasiFd { ) -> io::Result { unsafe { wasi::path_open( - self.fd, + self.fd as wasi::Fd, dirflags, path, oflags, @@ -130,25 +138,34 @@ impl WasiFd { fs_rights_inheriting, fs_flags, ) - .map(|fd| WasiFd::from_raw(fd)) + .map(|fd| WasiFd::from_raw(fd as c_int)) .map_err(err2io) } } pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result { - unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) } + unsafe { + wasi::fd_readdir(self.fd as wasi::Fd, buf.as_mut_ptr(), buf.len(), cookie) + .map_err(err2io) + } } pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result { - unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) } + unsafe { + wasi::path_readlink(self.fd as wasi::Fd, path, buf.as_mut_ptr(), buf.len()) + .map_err(err2io) + } } pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> { - unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) } + unsafe { + wasi::path_rename(self.fd as wasi::Fd, old_path, new_fd.fd as wasi::Fd, new_path) + .map_err(err2io) + } } pub fn filestat_get(&self) -> io::Result { - unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) } + unsafe { wasi::fd_filestat_get(self.fd as wasi::Fd).map_err(err2io) } } pub fn filestat_set_times( @@ -157,11 +174,13 @@ impl WasiFd { mtim: wasi::Timestamp, fstflags: wasi::Fstflags, ) -> io::Result<()> { - unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) } + unsafe { + wasi::fd_filestat_set_times(self.fd as wasi::Fd, atim, mtim, fstflags).map_err(err2io) + } } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) } + unsafe { wasi::fd_filestat_set_size(self.fd as wasi::Fd, size).map_err(err2io) } } pub fn path_filestat_get( @@ -169,7 +188,7 @@ impl WasiFd { flags: wasi::Lookupflags, path: &str, ) -> io::Result { - unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) } + unsafe { wasi::path_filestat_get(self.fd as wasi::Fd, flags, path).map_err(err2io) } } pub fn path_filestat_set_times( @@ -181,21 +200,21 @@ impl WasiFd { fstflags: wasi::Fstflags, ) -> io::Result<()> { unsafe { - wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags) + wasi::path_filestat_set_times(self.fd as wasi::Fd, flags, path, atim, mtim, fstflags) .map_err(err2io) } } pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> { - unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) } + unsafe { wasi::path_symlink(old_path, self.fd as wasi::Fd, new_path).map_err(err2io) } } pub fn unlink_file(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) } + unsafe { wasi::path_unlink_file(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn remove_directory(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) } + unsafe { wasi::path_remove_directory(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn sock_recv( @@ -203,11 +222,11 @@ impl WasiFd { ri_data: &mut [IoSliceMut<'_>], ri_flags: wasi::Riflags, ) -> io::Result<(usize, wasi::Roflags)> { - unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) } + unsafe { wasi::sock_recv(self.fd as wasi::Fd, iovec(ri_data), ri_flags).map_err(err2io) } } pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result { - unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) } + unsafe { wasi::sock_send(self.fd as wasi::Fd, ciovec(si_data), si_flags).map_err(err2io) } } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { @@ -216,7 +235,7 @@ impl WasiFd { Shutdown::Write => wasi::SDFLAGS_WR, Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD, }; - unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) } + unsafe { wasi::sock_shutdown(self.fd as wasi::Fd, how).map_err(err2io) } } } @@ -224,6 +243,6 @@ impl Drop for WasiFd { fn drop(&mut self) { // FIXME: can we handle the return code here even though we can't on // unix? - let _ = unsafe { wasi::fd_close(self.fd) }; + let _ = unsafe { wasi::fd_close(self.fd as wasi::Fd) }; } } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 8ffa1c88d88e7..55c9c652a8bbb 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -6,6 +6,7 @@ use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::iter; use crate::mem::{self, ManuallyDrop}; +use crate::os::raw::c_int; use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; @@ -454,8 +455,8 @@ impl File { } } -impl FromInner for File { - fn from_inner(fd: u32) -> File { +impl FromInner for File { + fn from_inner(fd: c_int) -> File { unsafe { File { fd: WasiFd::from_raw(fd) } } } } @@ -653,7 +654,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { let relative = CStr::from_ptr(relative_path).to_bytes().to_vec(); return Ok(( - ManuallyDrop::new(WasiFd::from_raw(fd as u32)), + ManuallyDrop::new(WasiFd::from_raw(fd as c_int)), PathBuf::from(OsString::from_vec(relative)), )); } diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 06860673d90e0..50b7352933e57 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -5,6 +5,7 @@ use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::os::raw::c_int; use crate::sys::unsupported; use crate::sys_common::FromInner; use crate::time::Duration; @@ -115,8 +116,8 @@ impl TcpStream { } } -impl FromInner for TcpStream { - fn from_inner(fd: u32) -> TcpStream { +impl FromInner for TcpStream { + fn from_inner(fd: c_int) -> TcpStream { unsafe { TcpStream { fd: WasiFd::from_raw(fd) } } } } @@ -181,8 +182,8 @@ impl TcpListener { } } -impl FromInner for TcpListener { - fn from_inner(fd: u32) -> TcpListener { +impl FromInner for TcpListener { + fn from_inner(fd: c_int) -> TcpListener { unsafe { TcpListener { fd: WasiFd::from_raw(fd) } } } } @@ -331,8 +332,8 @@ impl UdpSocket { } } -impl FromInner for UdpSocket { - fn from_inner(fd: u32) -> UdpSocket { +impl FromInner for UdpSocket { + fn from_inner(fd: c_int) -> UdpSocket { unsafe { UdpSocket { fd: WasiFd::from_raw(fd) } } } } diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs index 209d5b996e5b4..8782f333a1fa4 100644 --- a/library/std/src/sys/wasi/stdio.rs +++ b/library/std/src/sys/wasi/stdio.rs @@ -3,6 +3,7 @@ use super::fd::WasiFd; use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; +use crate::os::raw; pub struct Stdin; pub struct Stdout; @@ -14,7 +15,7 @@ impl Stdin { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 0 } } @@ -40,7 +41,7 @@ impl Stdout { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 1 } } @@ -69,7 +70,7 @@ impl Stderr { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 2 } } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 9effdb2c959d0..d12e86b7c1deb 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -933,6 +933,8 @@ impl Step for RustdocGUI { let mut command = Command::new(&nodejs); command .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js")) + .arg("--jobs") + .arg(&builder.jobs().to_string()) .arg("--doc-folder") .arg(out_dir.join("doc")) .arg("--tests-folder") diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 8dd7b2b3edc40..dab6d655c6a87 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -216,6 +216,9 @@ nav.main .separator { a { color: #c5c5c5; } +body.source .example-wrap pre.rust a { + background: #c5c5c5; +} .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow), .item-info a, diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index c26122e4bffb5..d9348be6994e2 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -177,6 +177,9 @@ nav.main .separator { a { color: #ddd; } +body.source .example-wrap pre.rust a { + background: #333; +} .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow), .item-info a, diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index bc18a72450896..0ffe5929ea593 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -172,6 +172,9 @@ nav.main .separator { a { color: #000; } +body.source .example-wrap pre.rust a { + background: #eee; +} .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow), .item-info a, diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr index ee9a4733fd95f..fbd77d9670091 100644 --- a/src/test/ui/error-codes/E0106.stderr +++ b/src/test/ui/error-codes/E0106.stderr @@ -59,7 +59,7 @@ LL | type MyStr = &str; help: consider introducing a named lifetime parameter | LL | type MyStr<'a> = &'a str; - | ++++ ~~~ + | ++++ ++ error: aborting due to 5 previous errors diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr index 1594747e54ce9..e82cbf7e8e5ef 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr @@ -15,7 +15,7 @@ LL | type F = &[u8]; help: consider introducing a named lifetime parameter | LL | type F<'a, T1> = &'a [u8]; - | +++ ~~~ + | +++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr index b752cde228d52..44955c58889aa 100644 --- a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr +++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr @@ -7,7 +7,7 @@ LL | type Output = &i32; help: consider introducing a named lifetime parameter | LL | type Output<'a> = &'a i32; - | ++++ ~~~ + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/assoc-type.rs:16:20 diff --git a/src/test/ui/type-alias-impl-trait/private_unused.rs b/src/test/ui/impl-trait/private_unused.rs similarity index 100% rename from src/test/ui/type-alias-impl-trait/private_unused.rs rename to src/test/ui/impl-trait/private_unused.rs diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr index c3e5fcdd63b55..18f69bb57755a 100644 --- a/src/test/ui/issues/issue-19707.stderr +++ b/src/test/ui/issues/issue-19707.stderr @@ -9,11 +9,11 @@ LL | type Foo = fn(&u8, &u8) -> &u8; help: consider making the type lifetime-generic with a new `'a` lifetime | LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8; - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ help: consider introducing a named lifetime parameter | LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8; - | ++++ ~~~~~~ ~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-19707.rs:5:27 @@ -26,11 +26,11 @@ LL | fn bar &u8>(f: &F) {} help: consider making the bound lifetime-generic with a new `'a` lifetime | LL | fn bar Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ help: consider introducing a named lifetime parameter | LL | fn bar<'a, F: Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} - | +++ ~~~~~~ ~~~~~~ ~~~ + | +++ ++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index 5784ca9d77f0e..bb7cdcbb100ff 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -8,7 +8,7 @@ LL | fn parse_type(iter: Box+'static>) -> &str { iter.ne help: consider introducing a named lifetime parameter | LL | fn parse_type<'a>(iter: Box+'static>) -> &'a str { iter.next() } - | ++++ ~~~ + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:4:40 diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr index 390aa31487a87..e5f492af5b366 100644 --- a/src/test/ui/issues/issue-30255.stderr +++ b/src/test/ui/issues/issue-30255.stderr @@ -8,7 +8,7 @@ LL | fn f(a: &S, b: i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn f<'a>(a: &'a S, b: i32) -> &'a i32 { - | ++++ ~~~~~ ~~~ + | ++++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:14:34 @@ -20,7 +20,7 @@ LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn g<'a>(a: &'a S, b: bool, c: &'a i32) -> &'a i32 { - | ++++ ~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:19:44 @@ -32,7 +32,7 @@ LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S, d: &'a i32) -> &'a i32 { - | ++++ ~~~~~~~~ ~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ ++ error: aborting due to 3 previous errors diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index d0dc3601202f0..0e69cd50f6a82 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -20,7 +20,7 @@ LL | fn g(_x: &isize, _y: &isize) -> &isize { help: consider introducing a named lifetime parameter | LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize { - | ++++ ~~~~~~~~~ ~~~~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19 @@ -32,7 +32,7 @@ LL | fn h(_x: &Foo) -> &isize { help: consider introducing a named lifetime parameter | LL | fn h<'a>(_x: &'a Foo) -> &'a isize { - | ++++ ~~~~~~~ ~~~ + | ++++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20 diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index cf365af99040a..bcc3e9510ac97 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -8,7 +8,7 @@ LL | fn foo(x: &i32, y: &i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - | ++++ ~~~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lint/dead-code/anon-const-in-pat.rs b/src/test/ui/lint/dead-code/anon-const-in-pat.rs new file mode 100644 index 0000000000000..4c6211a279a58 --- /dev/null +++ b/src/test/ui/lint/dead-code/anon-const-in-pat.rs @@ -0,0 +1,45 @@ +// check-pass +#![feature(inline_const)] +#![allow(incomplete_features)] +#![deny(dead_code)] + +const fn one() -> i32 { + 1 +} + +const fn two() -> i32 { + 2 +} + +const fn three() -> i32 { + 3 +} + +fn inline_const() { + // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern + match 1 { + const { one() } => {} + _ => {} + } +} + +fn inline_const_range() { + match 1 { + 1 ..= const { two() } => {} + _ => {} + } +} + +struct S; + +fn const_generic_arg() { + match S::<3> { + S::<{three()}> => {} + } +} + +fn main() { + inline_const(); + inline_const_range(); + const_generic_arg(); +} diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr index 8ed606cf90510..65b9f68817aa4 100644 --- a/src/test/ui/rfc1623-2.stderr +++ b/src/test/ui/rfc1623-2.stderr @@ -9,7 +9,7 @@ LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = help: consider making the type lifetime-generic with a new `'a` lifetime | LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/rfc1623-2.rs:10:39 @@ -22,7 +22,7 @@ LL | &(non_elidable as fn(&u8, &u8) -> &u8); help: consider making the type lifetime-generic with a new `'a` lifetime | LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr index 20468cef20ba2..7c0f8d199a965 100644 --- a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr +++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr @@ -25,11 +25,11 @@ LL | struct S2 &i32>(F); help: consider making the bound lifetime-generic with a new `'a` lifetime | LL | struct S2 Fn(&'a i32, &'a i32) -> &'a i32>(F); - | +++++++ ~~~~~~~ ~~~~~~~ ~~~ + | +++++++ ++ ++ ++ help: consider introducing a named lifetime parameter | LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F); - | +++ ~~~~~~~ ~~~~~~~ ~~~ + | +++ ++ ++ ++ error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types --> $DIR/fn-missing-lifetime-in-item.rs:3:40 diff --git a/src/test/ui/suggestions/issue-84592.stderr b/src/test/ui/suggestions/issue-84592.stderr index fe301e41277fc..70c96feb1de4c 100644 --- a/src/test/ui/suggestions/issue-84592.stderr +++ b/src/test/ui/suggestions/issue-84592.stderr @@ -10,7 +10,7 @@ LL | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> { help: consider introducing a named lifetime parameter | LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> { - | ++++ ~~~~~~ ~~~~~~ ~~ ~~ + | ++++ ++ ++ ~~ ~~ error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr index c1319165a7040..14dbbfffb0e62 100644 --- a/src/test/ui/suggestions/issue-86667.stderr +++ b/src/test/ui/suggestions/issue-86667.stderr @@ -8,7 +8,7 @@ LL | async fn a(s1: &str, s2: &str) -> &str { help: consider introducing a named lifetime parameter | LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str { - | ++++ ~~~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-86667.rs:11:29 @@ -20,7 +20,7 @@ LL | fn b(s1: &str, s2: &str) -> &str { help: consider introducing a named lifetime parameter | LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str { - | ++++ ~~~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr index b1caaea9aed7b..33f9d092e6ee0 100644 --- a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr +++ b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr @@ -47,7 +47,7 @@ LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); help: consider using one of the available lifetimes here | LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X); - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/missing-lt-for-hrtb.rs:5:41 diff --git a/src/test/ui/suggestions/return-elided-lifetime.stderr b/src/test/ui/suggestions/return-elided-lifetime.stderr index cdc3f5e85d142..f147b4463e2f2 100644 --- a/src/test/ui/suggestions/return-elided-lifetime.stderr +++ b/src/test/ui/suggestions/return-elided-lifetime.stderr @@ -80,7 +80,7 @@ LL | fn f3(s: &S) -> &i32 { loop {} } help: consider introducing a named lifetime parameter | LL | fn f3<'a>(s: &'a S) -> &'a i32 { loop {} } - | ++++ ~~~~~ ~~~ + | ++++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:21:26 @@ -92,7 +92,7 @@ LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } help: consider introducing a named lifetime parameter | LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&'a i32, &i32) { loop {} } - | ++++ ~~~~~ ~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:21:32 @@ -104,7 +104,7 @@ LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } help: consider introducing a named lifetime parameter | LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&i32, &'a i32) { loop {} } - | ++++ ~~~~~ ~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:25:42 @@ -121,7 +121,7 @@ LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } help: consider using one of the available lifetimes here | LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'lifetime i32 { loop {} } - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:27:44 @@ -138,7 +138,7 @@ LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } help: consider using one of the available lifetimes here | LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'lifetime i32, &i32) { loop {} } - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:27:50 @@ -155,7 +155,7 @@ LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } help: consider using one of the available lifetimes here | LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &'lifetime i32) { loop {} } - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:31:35 diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr index 89d36bfc92662..6a104e8f94b32 100644 --- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr +++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr @@ -8,7 +8,7 @@ LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } } - | ++++ ~~~~~~~ ~~~~~~~ ~~ + | ++++ ++ ++ ~~ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index 4c207bd3e68d8..22bf1fdba326f 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -43,7 +43,7 @@ LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } help: consider introducing a named lifetime parameter | LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } - | ++++ ~~~~~~ ~~~~~~ ~~ + | ++++ ~~ ~~ ~~ error: aborting due to 5 previous errors diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index d1cf5fb803d63..e697e1f86a9d5 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -17,6 +17,11 @@ function showHelp() { console.log(" --no-headless : disable headless mode"); console.log(" --help : show this message then quit"); console.log(" --tests-folder [PATH] : location of the .GOML tests folder"); + console.log(" --jobs [NUMBER] : number of threads to run tests on"); +} + +function isNumeric(s) { + return /^\d+$/.test(s); } function parseOptions(args) { @@ -27,6 +32,7 @@ function parseOptions(args) { "debug": false, "show_text": false, "no_headless": false, + "jobs": -1, }; var correspondances = { "--doc-folder": "doc_folder", @@ -39,13 +45,21 @@ function parseOptions(args) { for (var i = 0; i < args.length; ++i) { if (args[i] === "--doc-folder" || args[i] === "--tests-folder" - || args[i] === "--file") { + || args[i] === "--file" + || args[i] === "--jobs") { i += 1; if (i >= args.length) { console.log("Missing argument after `" + args[i - 1] + "` option."); return null; } - if (args[i - 1] !== "--file") { + if (args[i - 1] === "--jobs") { + if (!isNumeric(args[i])) { + console.log( + "`--jobs` option expects a positive number, found `" + args[i] + "`"); + return null; + } + opts["jobs"] = parseInt(args[i]); + } else if (args[i - 1] !== "--file") { opts[correspondances[args[i - 1]]] = args[i]; } else { opts["files"].push(args[i]); @@ -158,7 +172,11 @@ async function main(argv) { files.sort(); console.log(`Running ${files.length} rustdoc-gui tests...`); - process.setMaxListeners(files.length + 1); + if (opts["jobs"] < 1) { + process.setMaxListeners(files.length + 1); + } else { + process.setMaxListeners(opts["jobs"]); + } let tests = []; let results = { successful: [],