diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 61e196bdebe..62c502f9524 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -918,12 +918,7 @@ fn check_doc_fake_variadic(&self, meta: &MetaItemInner, hir_id: HirId) { }; match item_kind { Some(ItemKind::Impl(i)) => { - let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) - || if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind { - bare_fn_ty.decl.inputs.len() == 1 - } else { - false - } + let is_valid = doc_fake_variadic_is_allowed_self_ty(i.self_ty) || if let Some(&[hir::GenericArg::Type(ty)]) = i .of_trait .as_ref() @@ -2630,3 +2625,20 @@ fn check_duplicates( }, } } + +fn doc_fake_variadic_is_allowed_self_ty(self_ty: &hir::Ty<'_>) -> bool { + matches!(&self_ty.kind, hir::TyKind::Tup([_])) + || if let hir::TyKind::BareFn(bare_fn_ty) = &self_ty.kind { + bare_fn_ty.decl.inputs.len() == 1 + } else { + false + } + || (if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &self_ty.kind + && let Some(&[hir::GenericArg::Type(ty)]) = + path.segments.last().map(|last| last.args().args) + { + doc_fake_variadic_is_allowed_self_ty(ty) + } else { + false + }) +} diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index eb60effe813..f68465c9bda 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -162,7 +162,9 @@ fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> } /// Returns the pattern as utf-8 bytes if possible. - fn as_utf8_pattern(&self) -> Option>; + fn as_utf8_pattern(&self) -> Option> { + None + } } /// Result of calling [`Pattern::as_utf8_pattern()`]. /// Can be used for inspecting the contents of a [`Pattern`] in cases @@ -675,11 +677,6 @@ impl Pattern for MultiCharEqPattern { fn into_searcher(self, haystack: &str) -> MultiCharEqSearcher<'_, C> { MultiCharEqSearcher { haystack, char_eq: self.0, char_indices: haystack.char_indices() } } - - #[inline] - fn as_utf8_pattern(&self) -> Option> { - None - } } unsafe impl<'a, C: MultiCharEq> Searcher<'a> for MultiCharEqSearcher<'a, C> { @@ -770,11 +767,6 @@ fn strip_suffix_of<$a>(self, haystack: &$a str) -> Option<&$a str> { ($pmap)(self).strip_suffix_of(haystack) } - - #[inline] - fn as_utf8_pattern(&self) -> Option> { - None - } }; } diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 88cc95caf40..fb0b495961c 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -96,9 +96,23 @@ fn stdout_works() { #[test] #[cfg_attr(any(windows, target_os = "vxworks"), ignore)] fn set_current_dir_works() { + // On many Unix platforms this will use the posix_spawn path. let mut cmd = shell_cmd(); cmd.arg("-c").arg("pwd").current_dir("/").stdout(Stdio::piped()); assert_eq!(run_output(cmd), "/\n"); + + // Also test the fork/exec path by setting a pre_exec function. + #[cfg(unix)] + { + use crate::os::unix::process::CommandExt; + + let mut cmd = shell_cmd(); + cmd.arg("-c").arg("pwd").current_dir("/").stdout(Stdio::piped()); + unsafe { + cmd.pre_exec(|| Ok(())); + } + assert_eq!(run_output(cmd), "/\n"); + } } #[test] diff --git a/library/std/src/random.rs b/library/std/src/random.rs index cdb88c795bf..45f51dd37b0 100644 --- a/library/std/src/random.rs +++ b/library/std/src/random.rs @@ -38,7 +38,7 @@ /// Vita | `arc4random_buf` /// Hermit | `read_entropy` /// Horizon | `getrandom` shim -/// Hurd, L4Re, QNX | `/dev/urandom` +/// AIX, Hurd, L4Re, QNX | `/dev/urandom` /// Redox | `/scheme/rand` /// RTEMS | [`arc4random_buf`](https://docs.rtems.org/branches/master/bsp-howto/getentropy.html) /// SGX | [`rdrand`](https://en.wikipedia.org/wiki/RDRAND) diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 4551d49e841..8faf1fda546 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -448,7 +448,6 @@ fn posix_spawn( use core::sync::atomic::{AtomicU8, Ordering}; use crate::mem::MaybeUninit; - use crate::sys::weak::weak; use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used}; if self.get_gid().is_some() @@ -462,6 +461,8 @@ fn posix_spawn( cfg_if::cfg_if! { if #[cfg(target_os = "linux")] { + use crate::sys::weak::weak; + weak! { fn pidfd_spawnp( *mut libc::c_int, @@ -575,16 +576,44 @@ unsafe fn retrying_libc_posix_spawnp( } } - // Solaris, glibc 2.29+, and musl 1.24+ can set a new working directory, - // and maybe others will gain this non-POSIX function too. We'll check - // for this weak symbol as soon as it's needed, so we can return early - // otherwise to do a manual chdir before exec. - weak! { - fn posix_spawn_file_actions_addchdir_np( - *mut libc::posix_spawn_file_actions_t, - *const libc::c_char - ) -> libc::c_int + type PosixSpawnAddChdirFn = unsafe extern "C" fn( + *mut libc::posix_spawn_file_actions_t, + *const libc::c_char, + ) -> libc::c_int; + + /// Get the function pointer for adding a chdir action to a + /// `posix_spawn_file_actions_t`, if available, assuming a dynamic libc. + /// + /// Some platforms can set a new working directory for a spawned process in the + /// `posix_spawn` path. This function looks up the function pointer for adding + /// such an action to a `posix_spawn_file_actions_t` struct. + #[cfg(not(all(target_os = "linux", target_env = "musl")))] + fn get_posix_spawn_addchdir() -> Option { + use crate::sys::weak::weak; + + weak! { + fn posix_spawn_file_actions_addchdir_np( + *mut libc::posix_spawn_file_actions_t, + *const libc::c_char + ) -> libc::c_int + } + + posix_spawn_file_actions_addchdir_np.get() } + + /// Get the function pointer for adding a chdir action to a + /// `posix_spawn_file_actions_t`, if available, on platforms where the function + /// is known to exist. + /// + /// Weak symbol lookup doesn't work with statically linked libcs, so in cases + /// where static linking is possible we need to either check for the presence + /// of the symbol at compile time or know about it upfront. + #[cfg(all(target_os = "linux", target_env = "musl"))] + fn get_posix_spawn_addchdir() -> Option { + // Our minimum required musl supports this function, so we can just use it. + Some(libc::posix_spawn_file_actions_addchdir_np) + } + let addchdir = match self.get_cwd() { Some(cwd) => { if cfg!(target_vendor = "apple") { @@ -597,7 +626,10 @@ fn posix_spawn_file_actions_addchdir_np( return Ok(None); } } - match posix_spawn_file_actions_addchdir_np.get() { + // Check for the availability of the posix_spawn addchdir + // function now. If it isn't available, bail and use the + // fork/exec path. + match get_posix_spawn_addchdir() { Some(f) => Some((f, cwd)), None => return Ok(None), } diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index edc2cacdfd8..f42351deb92 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -40,6 +40,7 @@ mod horizon; pub use horizon::fill_bytes; } else if #[cfg(any( + target_os = "aix", target_os = "hurd", target_os = "l4re", target_os = "nto", diff --git a/library/std/src/sys/thread_local/statik.rs b/library/std/src/sys/thread_local/statik.rs index ba94caa6690..4da01a84acf 100644 --- a/library/std/src/sys/thread_local/statik.rs +++ b/library/std/src/sys/thread_local/statik.rs @@ -14,12 +14,11 @@ (@key $t:ty, const $init:expr) => {{ const __INIT: $t = $init; + // NOTE: Please update the shadowing test in `tests/thread.rs` if these types are renamed. unsafe { - use $crate::thread::LocalKey; - use $crate::thread::local_impl::EagerStorage; - - LocalKey::new(|_| { - static VAL: EagerStorage<$t> = EagerStorage { value: __INIT }; + $crate::thread::LocalKey::new(|_| { + static VAL: $crate::thread::local_impl::EagerStorage<$t> = + $crate::thread::local_impl::EagerStorage { value: __INIT }; &VAL.value }) } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5c599f20f9f..ea2f930ab83 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1368,6 +1368,24 @@ fn print_type<'a, 'tcx: 'a>( write!(f, " -> ")?; fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?; } + } else if let clean::Type::Path { path } = type_ + && let Some(generics) = path.generics() + && generics.len() == 1 + && self.kind.is_fake_variadic() + { + let ty = generics[0]; + let wrapper = anchor(path.def_id(), path.last(), cx); + if f.alternate() { + write!(f, "{wrapper:#}<")?; + } else { + write!(f, "{wrapper}<")?; + } + self.print_type(ty, f, use_absolute, cx)?; + if f.alternate() { + write!(f, ">")?; + } else { + write!(f, ">")?; + } } else { fmt_type(&type_, f, use_absolute, cx)?; } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 42e5dcf258f..3a6eca7dc5d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -59,7 +59,7 @@ fn disable_error_reporting R, R>(f: F) -> R { use std::sync::Mutex; use windows::Win32::System::Diagnostics::Debug::{ - SEM_NOGPFAULTERRORBOX, SetErrorMode, THREAD_ERROR_MODE, + SEM_FAILCRITICALERRORS, SEM_NOGPFAULTERRORBOX, SetErrorMode, THREAD_ERROR_MODE, }; static LOCK: Mutex<()> = Mutex::new(()); @@ -67,13 +67,21 @@ fn disable_error_reporting R, R>(f: F) -> R { // Error mode is a global variable, so lock it so only one thread will change it let _lock = LOCK.lock().unwrap(); - // Tell Windows to not show any UI on errors (such as terminating abnormally). - // This is important for running tests, since some of them use abnormal - // termination by design. This mode is inherited by all child processes. + // Tell Windows to not show any UI on errors (such as terminating abnormally). This is important + // for running tests, since some of them use abnormal termination by design. This mode is + // inherited by all child processes. + // + // Note that `run-make` tests require `SEM_FAILCRITICALERRORS` in addition to suppress Windows + // Error Reporting (WER) error dialogues that come from "critical failures" such as missing + // DLLs. + // + // See and + // . unsafe { - let old_mode = SetErrorMode(SEM_NOGPFAULTERRORBOX); // read inherited flags + // read inherited flags + let old_mode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS); let old_mode = THREAD_ERROR_MODE(old_mode); - SetErrorMode(old_mode | SEM_NOGPFAULTERRORBOX); + SetErrorMode(old_mode | SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS); let r = f(); SetErrorMode(old_mode); r diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index f8ffd0fbe3f..e7ae773ffa1 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -2,7 +2,7 @@ use std::process::{Command, Output, Stdio}; use std::{env, fs}; -use super::{ProcRes, TestCx}; +use super::{ProcRes, TestCx, disable_error_reporting}; use crate::util::{copy_dir_all, dylib_env_var}; impl TestCx<'_> { @@ -514,8 +514,8 @@ fn run_rmake_v2_test(&self) { } } - let (Output { stdout, stderr, status }, truncated) = - self.read2_abbreviated(cmd.spawn().expect("failed to spawn `rmake`")); + let proc = disable_error_reporting(|| cmd.spawn().expect("failed to spawn `rmake`")); + let (Output { stdout, stderr, status }, truncated) = self.read2_abbreviated(proc); if !status.success() { let res = ProcRes { status, diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs index b15e996f929..d142729d2a8 100644 --- a/tests/rustdoc/primitive-tuple-variadic.rs +++ b/tests/rustdoc/primitive-tuple-variadic.rs @@ -33,3 +33,22 @@ pub trait Baz { fn baz(&self) -> T { todo!() } } //@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl Baz for (T₁, T₂, …, Tₙ)' #[doc(fake_variadic)] impl Baz for (T,) {} + +pub trait Qux {} + +pub struct NewType(T); + +//@ has foo/trait.Qux.html +//@ has - '//section[@id="impl-Qux-for-NewType%3C(T,)%3E"]/h3' 'impl Qux for NewType<(T₁, T₂, …, Tₙ)>' +#[doc(fake_variadic)] +impl Qux for NewType<(T,)> {} + +//@ has foo/trait.Qux.html +//@ has - '//section[@id="impl-Qux-for-NewType%3CNewType%3C(T,)%3E%3E"]/h3' 'impl Qux for NewType>' +#[doc(fake_variadic)] +impl Qux for NewType> {} + +//@ has foo/trait.Qux.html +//@ has - '//section[@id="impl-Qux-for-NewType%3Cfn(T)+-%3E+Out%3E"]/h3' 'impl Qux for NewType Out>' +#[doc(fake_variadic)] +impl Qux for NewType Out> {}