diff --git a/compiler/rustc_data_structures/src/captures.rs b/compiler/rustc_data_structures/src/captures.rs index 26b90ebfd5f11..677ccb31454ea 100644 --- a/compiler/rustc_data_structures/src/captures.rs +++ b/compiler/rustc_data_structures/src/captures.rs @@ -3,8 +3,6 @@ /// Basically a workaround; see [this comment] for details. /// /// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999 -// FIXME(eddyb) false positive, the lifetime parameter is "phantom" but needed. -#[allow(unused_lifetimes)] pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index d6989b866c1d2..f65cc429fbd48 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -11,7 +11,7 @@ use crate::check::{ use rustc_ast as ast; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ExprKind, Node, QPath}; use rustc_middle::ty::adjustment::AllowTwoPhase; @@ -120,8 +120,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error_code: &str, c_variadic: bool, sugg_unit: bool| { - let (span, start_span, args) = match &expr.kind { - hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]), + let (span, start_span, args, ctor_of) = match &expr.kind { + hir::ExprKind::Call( + hir::Expr { + span, + kind: + hir::ExprKind::Path(hir::QPath::Resolved( + _, + hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. }, + )), + .. + }, + args, + ) => (*span, *span, &args[..], Some(of)), + hir::ExprKind::Call(hir::Expr { span, .. }, args) => { + (*span, *span, &args[..], None) + } hir::ExprKind::MethodCall(path_segment, span, args, _) => ( *span, // `sp` doesn't point at the whole `foo.bar()`, only at `bar`. @@ -137,6 +151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .unwrap_or(*span), &args[1..], // Skip the receiver. + None, // methods are never ctors ), k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k), }; @@ -157,7 +172,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = tcx.sess.struct_span_err_with_code( span, &format!( - "this function takes {}{} but {} {} supplied", + "this {} takes {}{} but {} {} supplied", + match ctor_of { + Some(CtorOf::Struct) => "struct", + Some(CtorOf::Variant) => "enum variant", + None => "function", + }, if c_variadic { "at least " } else { "" }, potentially_plural_count(expected_count, "argument"), potentially_plural_count(arg_count, "argument"), diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index a0efe681285b4..2e466106fe553 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1772,9 +1772,9 @@ macro_rules! int_impl { #[inline] #[rustc_inherit_overflow_checks] pub const fn abs(self) -> Self { - // Note that the #[inline] above means that the overflow - // semantics of the subtraction depend on the crate we're being - // inlined into. + // Note that the #[rustc_inherit_overflow_checks] and #[inline] + // above mean that the overflow semantics of the subtraction + // depend on the crate we're being called from. if self.is_negative() { -self } else { diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 0aae4674b2942..f8884523cf446 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -399,12 +399,11 @@ impl fmt::Display for Backtrace { let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path); f.add_context()?; for frame in frames { - let mut f = f.frame(); if frame.symbols.is_empty() { - f.print_raw(frame.frame.ip(), None, None, None)?; + f.frame().print_raw(frame.frame.ip(), None, None, None)?; } else { for symbol in frame.symbols.iter() { - f.print_raw_with_column( + f.frame().print_raw_with_column( frame.frame.ip(), symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)), symbol.filename.as_ref().map(|b| match b { diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 9527254c94793..04f13cdeb88e3 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -205,6 +205,88 @@ impl Cursor { } } +impl Cursor +where + T: AsRef<[u8]>, +{ + /// Returns the remaining length. + /// + /// # Examples + /// + /// ``` + /// #![feature(cursor_remaining)] + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.remaining(), 5); + /// + /// buff.set_position(2); + /// assert_eq!(buff.remaining(), 3); + /// + /// buff.set_position(4); + /// assert_eq!(buff.remaining(), 1); + /// + /// buff.set_position(6); + /// assert_eq!(buff.remaining(), 0); + /// ``` + #[unstable(feature = "cursor_remaining", issue = "86369")] + pub fn remaining(&self) -> u64 { + (self.inner.as_ref().len() as u64).checked_sub(self.pos).unwrap_or(0) + } + + /// Returns the remaining slice. + /// + /// # Examples + /// + /// ``` + /// #![feature(cursor_remaining)] + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.remaining_slice(), &[1, 2, 3, 4, 5]); + /// + /// buff.set_position(2); + /// assert_eq!(buff.remaining_slice(), &[3, 4, 5]); + /// + /// buff.set_position(4); + /// assert_eq!(buff.remaining_slice(), &[5]); + /// + /// buff.set_position(6); + /// assert_eq!(buff.remaining_slice(), &[]); + /// ``` + #[unstable(feature = "cursor_remaining", issue = "86369")] + pub fn remaining_slice(&self) -> &[u8] { + let len = self.pos.min(self.inner.as_ref().len() as u64); + &self.inner.as_ref()[(len as usize)..] + } + + /// Returns `true` if the remaining slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(cursor_remaining)] + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// buff.set_position(2); + /// assert!(!buff.is_empty()); + /// + /// buff.set_position(5); + /// assert!(buff.is_empty()); + /// + /// buff.set_position(10); + /// assert!(buff.is_empty()); + /// ``` + #[unstable(feature = "cursor_remaining", issue = "86369")] + pub fn is_empty(&self) -> bool { + self.pos >= self.inner.as_ref().len() as u64 + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Cursor where @@ -268,7 +350,7 @@ where T: AsRef<[u8]>, { fn read(&mut self, buf: &mut [u8]) -> io::Result { - let n = Read::read(&mut self.fill_buf()?, buf)?; + let n = Read::read(&mut self.remaining_slice(), buf)?; self.pos += n as u64; Ok(n) } @@ -291,7 +373,7 @@ where fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { let n = buf.len(); - Read::read_exact(&mut self.fill_buf()?, buf)?; + Read::read_exact(&mut self.remaining_slice(), buf)?; self.pos += n as u64; Ok(()) } @@ -308,8 +390,7 @@ where T: AsRef<[u8]>, { fn fill_buf(&mut self) -> io::Result<&[u8]> { - let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64); - Ok(&self.inner.as_ref()[(amt as usize)..]) + Ok(self.remaining_slice()) } fn consume(&mut self, amt: usize) { self.pos += amt as u64; diff --git a/library/std/src/os/fortanix_sgx/arch.rs b/library/std/src/os/fortanix_sgx/arch.rs index b0170e67446db..4ce482e23cbfb 100644 --- a/library/std/src/os/fortanix_sgx/arch.rs +++ b/library/std/src/os/fortanix_sgx/arch.rs @@ -33,13 +33,13 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result, u32> asm!( // rbx is reserved by LLVM - "xchg {0}, rbx", + "xchg %rbx, {0}", "enclu", - "mov rbx, {0}", + "mov {0}, %rbx", inout(reg) request => _, inlateout("eax") ENCLU_EGETKEY => error, in("rcx") out.as_mut_ptr(), - options(nostack), + options(att_syntax, nostack), ); match error { @@ -64,14 +64,14 @@ pub fn ereport( asm!( // rbx is reserved by LLVM - "xchg {0}, rbx", + "xchg %rbx, {0}", "enclu", - "mov rbx, {0}", + "mov {0}, %rbx", inout(reg) targetinfo => _, in("eax") ENCLU_EREPORT, in("rcx") reportdata, in("rdx") report.as_mut_ptr(), - options(preserves_flags, nostack), + options(att_syntax, preserves_flags, nostack), ); report.assume_init() diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index f35a3a8a80fc5..6da79d19f5949 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -1,8 +1,10 @@ #![allow(dead_code)] +use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::sys::hermit::abi; use crate::sys::hermit::thread_local_dtor::run_dtors; use crate::time::Duration; @@ -95,6 +97,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/sgx/abi/mem.rs b/library/std/src/sys/sgx/abi/mem.rs index 1e743894a9fea..52e8bec937c79 100644 --- a/library/std/src/sys/sgx/abi/mem.rs +++ b/library/std/src/sys/sgx/abi/mem.rs @@ -36,9 +36,9 @@ pub fn image_base() -> u64 { let base: u64; unsafe { asm!( - "lea {}, qword ptr [rip + IMAGE_BASE]", + "lea IMAGE_BASE(%rip), {}", lateout(reg) base, - options(nostack, preserves_flags, nomem, pure), + options(att_syntax, nostack, preserves_flags, nomem, pure), ) }; base diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index 67e2e8b59d397..cbb8ba964018a 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -1,6 +1,8 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? +use super::unsupported; use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::time::Duration; use super::abi::usercalls; @@ -135,6 +137,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index b8f43caec32a3..df2ba0a8bc8e6 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -2,6 +2,7 @@ use crate::cmp; use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::ptr; use crate::sys::{os, stack_overflow}; use crate::time::Duration; @@ -198,6 +199,88 @@ impl Drop for Thread { } } +pub fn available_concurrency() -> io::Result { + cfg_if::cfg_if! { + if #[cfg(any( + target_os = "android", + target_os = "emscripten", + target_os = "fuchsia", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "solaris", + target_os = "illumos", + ))] { + match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { + -1 => Err(io::Error::last_os_error()), + 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), + cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }), + } + } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { + use crate::ptr; + + let mut cpus: libc::c_uint = 0; + let mut cpus_size = crate::mem::size_of_val(&cpus); + + unsafe { + cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint; + } + + // Fallback approach in case of errors or no hardware threads. + if cpus < 1 { + let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + let res = unsafe { + libc::sysctl( + mib.as_mut_ptr(), + 2, + &mut cpus as *mut _ as *mut _, + &mut cpus_size as *mut _ as *mut _, + ptr::null_mut(), + 0, + ) + }; + + // Handle errors if any. + if res == -1 { + return Err(io::Error::last_os_error()); + } else if cpus == 0 { + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); + } + } + Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else if #[cfg(target_os = "openbsd")] { + use crate::ptr; + + let mut cpus: libc::c_uint = 0; + let mut cpus_size = crate::mem::size_of_val(&cpus); + let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + + let res = unsafe { + libc::sysctl( + mib.as_mut_ptr(), + 2, + &mut cpus as *mut _ as *mut _, + &mut cpus_size as *mut _ as *mut _, + ptr::null_mut(), + 0, + ) + }; + + // Handle errors if any. + if res == -1 { + return Err(io::Error::last_os_error()); + } else if cpus == 0 { + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); + } + + Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else { + // FIXME: implement on vxWorks, Redox, Haiku, l4re + Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform")) + } + } +} + #[cfg(all( not(target_os = "linux"), not(target_os = "freebsd"), diff --git a/library/std/src/sys/unsupported/thread.rs b/library/std/src/sys/unsupported/thread.rs index cda8510e1baeb..dc75d4ee6725c 100644 --- a/library/std/src/sys/unsupported/thread.rs +++ b/library/std/src/sys/unsupported/thread.rs @@ -1,6 +1,7 @@ use super::unsupported; use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::time::Duration; pub struct Thread(!); @@ -30,6 +31,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index 74515553a8218..9ec02bbec2644 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -3,6 +3,7 @@ use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::sys::unsupported; use crate::time::Duration; @@ -63,6 +64,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/wasm/atomics/thread.rs b/library/std/src/sys/wasm/atomics/thread.rs index 54bc877aa7de7..0971483510495 100644 --- a/library/std/src/sys/wasm/atomics/thread.rs +++ b/library/std/src/sys/wasm/atomics/thread.rs @@ -1,5 +1,7 @@ +use super::unsupported; use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::sys::unsupported; use crate::time::Duration; @@ -39,6 +41,10 @@ impl Thread { pub fn join(self) {} } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index b64870401f1fd..193c28c7673d7 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -13,6 +13,7 @@ use libc::{c_void, size_t, wchar_t}; pub use self::EXCEPTION_DISPOSITION::*; pub use self::FILE_INFO_BY_HANDLE_CLASS::*; +pub type DWORD_PTR = ULONG_PTR; pub type DWORD = c_ulong; pub type NonZeroDWORD = NonZero_c_ulong; pub type HANDLE = LPVOID; @@ -53,6 +54,7 @@ pub type LPWSADATA = *mut WSADATA; pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; pub type LPWSTR = *mut WCHAR; pub type LPFILETIME = *mut FILETIME; +pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; pub type LPWSABUF = *mut WSABUF; pub type LPWSAOVERLAPPED = *mut c_void; pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void; @@ -533,6 +535,21 @@ pub struct FILETIME { pub dwHighDateTime: DWORD, } +#[repr(C)] +pub struct SYSTEM_INFO { + pub wProcessorArchitecture: WORD, + pub wReserved: WORD, + pub dwPageSize: DWORD, + pub lpMinimumApplicationAddress: LPVOID, + pub lpMaximumApplicationAddress: LPVOID, + pub dwActiveProcessorMask: DWORD_PTR, + pub dwNumberOfProcessors: DWORD, + pub dwProcessorType: DWORD, + pub dwAllocationGranularity: DWORD, + pub wProcessorLevel: WORD, + pub wProcessorRevision: WORD, +} + #[repr(C)] pub struct OVERLAPPED { pub Internal: *mut c_ulong, @@ -934,6 +951,7 @@ extern "system" { pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); + pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); pub fn CreateEventW( lpEventAttributes: LPSECURITY_ATTRIBUTES, diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index 38839ea5e90ed..ef7a9733fd880 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -1,5 +1,6 @@ use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::ptr; use crate::sys::c; use crate::sys::handle::Handle; @@ -98,6 +99,21 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + let res = unsafe { + let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed(); + c::GetSystemInfo(&mut sysinfo); + sysinfo.dwNumberOfProcessors as usize + }; + match res { + 0 => Err(io::Error::new_const( + io::ErrorKind::NotFound, + &"The number of hardware threads is not known for the target platform", + )), + cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }), + } +} + #[cfg_attr(test, allow(dead_code))] pub mod guard { pub type Guard = !; diff --git a/library/std/src/thread/available_concurrency.rs b/library/std/src/thread/available_concurrency.rs deleted file mode 100644 index e8cdde8801459..0000000000000 --- a/library/std/src/thread/available_concurrency.rs +++ /dev/null @@ -1,156 +0,0 @@ -use crate::io; -use crate::num::NonZeroUsize; - -/// Returns the number of hardware threads available to the program. -/// -/// This value should be considered only a hint. -/// -/// # Platform-specific behavior -/// -/// If interpreted as the number of actual hardware threads, it may undercount on -/// Windows systems with more than 64 hardware threads. If interpreted as the -/// available concurrency for that process, it may overcount on Windows systems -/// when limited by a process wide affinity mask or job object limitations, and -/// it may overcount on Linux systems when limited by a process wide affinity -/// mask or affected by cgroups limits. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not -/// limited to just these cases: -/// -/// - If the number of hardware threads is not known for the target platform. -/// - The process lacks permissions to view the number of hardware threads -/// available. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// #![feature(available_concurrency)] -/// use std::thread; -/// -/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1); -/// ``` -#[unstable(feature = "available_concurrency", issue = "74479")] -pub fn available_concurrency() -> io::Result { - available_concurrency_internal() -} - -cfg_if::cfg_if! { - if #[cfg(windows)] { - #[allow(nonstandard_style)] - fn available_concurrency_internal() -> io::Result { - #[repr(C)] - struct SYSTEM_INFO { - wProcessorArchitecture: u16, - wReserved: u16, - dwPageSize: u32, - lpMinimumApplicationAddress: *mut u8, - lpMaximumApplicationAddress: *mut u8, - dwActiveProcessorMask: *mut u8, - dwNumberOfProcessors: u32, - dwProcessorType: u32, - dwAllocationGranularity: u32, - wProcessorLevel: u16, - wProcessorRevision: u16, - } - extern "system" { - fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32; - } - let res = unsafe { - let mut sysinfo = crate::mem::zeroed(); - GetSystemInfo(&mut sysinfo); - sysinfo.dwNumberOfProcessors as usize - }; - match res { - 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), - cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }), - } - } - } else if #[cfg(any( - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "solaris", - target_os = "illumos", - ))] { - fn available_concurrency_internal() -> io::Result { - match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { - -1 => Err(io::Error::last_os_error()), - 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), - cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }), - } - } - } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { - fn available_concurrency_internal() -> io::Result { - use crate::ptr; - - let mut cpus: libc::c_uint = 0; - let mut cpus_size = crate::mem::size_of_val(&cpus); - - unsafe { - cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint; - } - - // Fallback approach in case of errors or no hardware threads. - if cpus < 1 { - let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; - let res = unsafe { - libc::sysctl( - mib.as_mut_ptr(), - 2, - &mut cpus as *mut _ as *mut _, - &mut cpus_size as *mut _ as *mut _, - ptr::null_mut(), - 0, - ) - }; - - // Handle errors if any. - if res == -1 { - return Err(io::Error::last_os_error()); - } else if cpus == 0 { - return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); - } - } - Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) - } - } else if #[cfg(target_os = "openbsd")] { - fn available_concurrency_internal() -> io::Result { - use crate::ptr; - - let mut cpus: libc::c_uint = 0; - let mut cpus_size = crate::mem::size_of_val(&cpus); - let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; - - let res = unsafe { - libc::sysctl( - mib.as_mut_ptr(), - 2, - &mut cpus as *mut _ as *mut _, - &mut cpus_size as *mut _ as *mut _, - ptr::null_mut(), - 0, - ) - }; - - // Handle errors if any. - if res == -1 { - return Err(io::Error::last_os_error()); - } else if cpus == 0 { - return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); - } - - Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) - } - } else { - // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re - fn available_concurrency_internal() -> io::Result { - Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")) - } - } -} diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 30d8c2a1b6fa0..f7e791419038d 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -155,6 +155,7 @@ use crate::fmt; use crate::io; use crate::mem; use crate::num::NonZeroU64; +use crate::num::NonZeroUsize; use crate::panic; use crate::panicking; use crate::str; @@ -174,15 +175,9 @@ use crate::time::Duration; #[macro_use] mod local; -#[unstable(feature = "available_concurrency", issue = "74479")] -mod available_concurrency; - #[stable(feature = "rust1", since = "1.0.0")] pub use self::local::{AccessError, LocalKey}; -#[unstable(feature = "available_concurrency", issue = "74479")] -pub use available_concurrency::available_concurrency; - // The types used by the thread_local! macro to access TLS keys. Note that there // are two types, the "OS" type and the "fast" type. The OS thread local key // type is accessed via platform-specific API calls and is slow, while the fast @@ -1422,3 +1417,39 @@ fn _assert_sync_and_send() { _assert_both::>(); _assert_both::(); } + +/// Returns the number of hardware threads available to the program. +/// +/// This value should be considered only a hint. +/// +/// # Platform-specific behavior +/// +/// If interpreted as the number of actual hardware threads, it may undercount on +/// Windows systems with more than 64 hardware threads. If interpreted as the +/// available concurrency for that process, it may overcount on Windows systems +/// when limited by a process wide affinity mask or job object limitations, and +/// it may overcount on Linux systems when limited by a process wide affinity +/// mask or affected by cgroups limits. +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// - If the number of hardware threads is not known for the target platform. +/// - The process lacks permissions to view the number of hardware threads +/// available. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// #![feature(available_concurrency)] +/// use std::thread; +/// +/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1); +/// ``` +#[unstable(feature = "available_concurrency", issue = "74479")] +pub fn available_concurrency() -> io::Result { + imp::available_concurrency() +} diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 93ba8b07f5b3a..92ac3b364f6f1 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -894,6 +894,9 @@ impl Step for RustdocGUI { } } } + for test_arg in builder.config.cmd.test_args() { + command.arg(test_arg); + } builder.run(&mut command); } } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9db83c903abf0..fb82a075de0a9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -544,6 +544,44 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }) } + /// Convert a DefId to a Res, where possible. + /// + /// This is used for resolving type aliases. + fn def_id_to_res(&self, ty_id: DefId) -> Option { + use PrimitiveType::*; + Some(match *self.cx.tcx.type_of(ty_id).kind() { + ty::Bool => Res::Primitive(Bool), + ty::Char => Res::Primitive(Char), + ty::Int(ity) => Res::Primitive(ity.into()), + ty::Uint(uty) => Res::Primitive(uty.into()), + ty::Float(fty) => Res::Primitive(fty.into()), + ty::Str => Res::Primitive(Str), + ty::Tuple(ref tys) if tys.is_empty() => Res::Primitive(Unit), + ty::Tuple(_) => Res::Primitive(Tuple), + ty::Array(..) => Res::Primitive(Array), + ty::Slice(_) => Res::Primitive(Slice), + ty::RawPtr(_) => Res::Primitive(RawPointer), + ty::Ref(..) => Res::Primitive(Reference), + ty::FnDef(..) => panic!("type alias to a function definition"), + ty::FnPtr(_) => Res::Primitive(Fn), + ty::Never => Res::Primitive(Never), + ty::Adt(&ty::AdtDef { did, .. }, _) | ty::Foreign(did) => { + Res::Def(self.cx.tcx.def_kind(did), did) + } + ty::Projection(_) + | ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(_) + | ty::Opaque(..) + | ty::Dynamic(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::Error(_) => return None, + }) + } + /// Returns: /// - None if no associated item was found /// - Some((_, _, Some(_))) if an item was found and should go through a side channel @@ -559,12 +597,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { match root_res { Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name), + Res::Def(DefKind::TyAlias, did) => { + // Resolve the link on the type the alias points to. + // FIXME: if the associated item is defined directly on the type alias, + // it will show up on its documentation page, we should link there instead. + let res = self.def_id_to_res(did)?; + self.resolve_associated_item(res, item_name, ns, module_id) + } Res::Def( - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::TyAlias - | DefKind::ForeignTy, + DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::ForeignTy, did, ) => { debug!("looking for associated item named {} for item {:?}", item_name, did); diff --git a/src/test/rustdoc-gui/README.md b/src/test/rustdoc-gui/README.md index 499a98a3d2237..8efe7a578b8f0 100644 --- a/src/test/rustdoc-gui/README.md +++ b/src/test/rustdoc-gui/README.md @@ -8,5 +8,17 @@ test what's being currently displayed in the web page. You can find more information and its documentation in its [repository][browser-ui-test]. +If you need to have more information on the tests run, you can use `--test-args`: + +```bash +$ ./x.py test src/test/rustdoc-gui --stage 1 --jobs 8 --test-args --debug +``` + +There are three options supported: + + * `--debug`: allows to see puppeteer commands. + * `--no-headless`: disable headless mode so you can see what's going on. + * `--show-text`: by default, text isn't rendered because of issues with fonts, it enables it back. + [browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/ [puppeteer]: https://pptr.dev/ diff --git a/src/test/rustdoc/intra-doc/type-alias.rs b/src/test/rustdoc/intra-doc/type-alias.rs new file mode 100644 index 0000000000000..f3609ccd0a141 --- /dev/null +++ b/src/test/rustdoc/intra-doc/type-alias.rs @@ -0,0 +1,19 @@ +// Regression test for issue #86120. + +#![deny(broken_intra_doc_links)] +#![crate_name = "foo"] + +pub struct Foo; + +/// You should really try [`Self::bar`]! +pub type Bar = Foo; + +impl Bar { + pub fn bar() {} +} + +/// The minimum is [`Self::MIN`]. +pub type Int = i32; + +// @has foo/type.Bar.html '//a[@href="struct.Foo.html#method.bar"]' 'Self::bar' +// @has foo/type.Int.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MIN"]' 'Self::MIN' diff --git a/src/test/ui/consts/issue-39161-bogus-error.rs b/src/test/ui/consts/issue-39161-bogus-error.rs new file mode 100644 index 0000000000000..a954385da41a4 --- /dev/null +++ b/src/test/ui/consts/issue-39161-bogus-error.rs @@ -0,0 +1,13 @@ +// check-pass + +pub struct X { + pub a: i32, + pub b: i32, +} + +fn main() { + const DX: X = X { a: 0, b: 0 }; + const _X1: X = X { a: 1, ..DX }; + let _x2 = X { a: 1, b: 2, ..DX }; + const _X3: X = X { a: 1, b: 2, ..DX }; +} diff --git a/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs b/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs new file mode 100644 index 0000000000000..a036d10e63902 --- /dev/null +++ b/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs @@ -0,0 +1,31 @@ +// min-llvm-version: 12.0 +// compile-flags: -C opt-level=3 +// run-pass + +fn foo(_i: i32) -> i32 { + 1 +} +fn bar(_i: i32) -> i32 { + 1 +} + +fn main() { + let x: fn(i32) -> i32 = foo; + let y: fn(i32) -> i32 = bar; + + let s1; + if x == y { + s1 = "same".to_string(); + } else { + s1 = format!("{:?}, {:?}", x, y); + } + + let s2; + if x == y { + s2 = "same".to_string(); + } else { + s2 = format!("{:?}, {:?}", x, y); + } + + assert_eq!(s1, s2); +} diff --git a/src/test/ui/span/missing-unit-argument.rs b/src/test/ui/span/missing-unit-argument.rs index b8fb332120a4e..5b9861da6e854 100644 --- a/src/test/ui/span/missing-unit-argument.rs +++ b/src/test/ui/span/missing-unit-argument.rs @@ -8,7 +8,7 @@ impl S { } fn main() { - let _: Result<(), String> = Ok(); //~ ERROR this function takes + let _: Result<(), String> = Ok(); //~ ERROR this enum variant takes foo(); //~ ERROR this function takes foo(()); //~ ERROR this function takes bar(); //~ ERROR this function takes diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index b15da2cb47955..7a24ffbd81c88 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -1,4 +1,4 @@ -error[E0061]: this function takes 1 argument but 0 arguments were supplied +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:11:33 | LL | let _: Result<(), String> = Ok(); diff --git a/src/test/ui/typeck/struct-enum-wrong-args.rs b/src/test/ui/typeck/struct-enum-wrong-args.rs new file mode 100644 index 0000000000000..19de4d67729fc --- /dev/null +++ b/src/test/ui/typeck/struct-enum-wrong-args.rs @@ -0,0 +1,14 @@ +// Regression test of #86481. +struct Wrapper(i32); +struct DoubleWrapper(i32, i32); + +fn main() { + let _ = Some(3, 2); //~ ERROR this enum variant takes + let _ = Ok(3, 6, 2); //~ ERROR this enum variant takes + let _ = Ok(); //~ ERROR this enum variant takes + let _ = Wrapper(); //~ ERROR this struct takes + let _ = Wrapper(5, 2); //~ ERROR this struct takes + let _ = DoubleWrapper(); //~ ERROR this struct takes + let _ = DoubleWrapper(5); //~ ERROR this struct takes + let _ = DoubleWrapper(5, 2, 7); //~ ERROR this struct takes +} diff --git a/src/test/ui/typeck/struct-enum-wrong-args.stderr b/src/test/ui/typeck/struct-enum-wrong-args.stderr new file mode 100644 index 0000000000000..d77ef73028b0c --- /dev/null +++ b/src/test/ui/typeck/struct-enum-wrong-args.stderr @@ -0,0 +1,67 @@ +error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:6:13 + | +LL | let _ = Some(3, 2); + | ^^^^ - - supplied 2 arguments + | | + | expected 1 argument + +error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:7:13 + | +LL | let _ = Ok(3, 6, 2); + | ^^ - - - supplied 3 arguments + | | + | expected 1 argument + +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:8:13 + | +LL | let _ = Ok(); + | ^^-- supplied 0 arguments + | | + | expected 1 argument + +error[E0061]: this struct takes 1 argument but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:9:13 + | +LL | let _ = Wrapper(); + | ^^^^^^^-- supplied 0 arguments + | | + | expected 1 argument + +error[E0061]: this struct takes 1 argument but 2 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:10:13 + | +LL | let _ = Wrapper(5, 2); + | ^^^^^^^ - - supplied 2 arguments + | | + | expected 1 argument + +error[E0061]: this struct takes 2 arguments but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:11:13 + | +LL | let _ = DoubleWrapper(); + | ^^^^^^^^^^^^^-- supplied 0 arguments + | | + | expected 2 arguments + +error[E0061]: this struct takes 2 arguments but 1 argument was supplied + --> $DIR/struct-enum-wrong-args.rs:12:13 + | +LL | let _ = DoubleWrapper(5); + | ^^^^^^^^^^^^^ - supplied 1 argument + | | + | expected 2 arguments + +error[E0061]: this struct takes 2 arguments but 3 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:13:13 + | +LL | let _ = DoubleWrapper(5, 2, 7); + | ^^^^^^^^^^^^^ - - - supplied 3 arguments + | | + | expected 2 arguments + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index f0618a8f06a46..13da28cc2bc1b 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit f0618a8f06a464840079f30b3e25bcdcca3922a3 +Subproject commit 13da28cc2bc1b59f7af817eca36927a71edb023c diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index 8c8d86d5e3817..416d824c5645e 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -11,6 +11,9 @@ function showHelp() { console.log("rustdoc-js options:"); console.log(" --doc-folder [PATH] : location of the generated doc folder"); console.log(" --file [PATH] : file to run (can be repeated)"); + console.log(" --debug : show extra information about script run"); + console.log(" --show-text : render font in pages"); + 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"); } @@ -20,10 +23,16 @@ function parseOptions(args) { "doc_folder": "", "tests_folder": "", "files": [], + "debug": false, + "show_text": false, + "no_headless": false, }; var correspondances = { "--doc-folder": "doc_folder", "--tests-folder": "tests_folder", + "--debug": "debug", + "--show-text": "show_text", + "--no-headless": "no_headless", }; for (var i = 0; i < args.length; ++i) { @@ -43,6 +52,8 @@ function parseOptions(args) { } else if (args[i] === "--help") { showHelp(); process.exit(0); + } else if (correspondances[args[i]]) { + opts[correspondances[args[i]]] = true; } else { console.log("Unknown option `" + args[i] + "`."); console.log("Use `--help` to see the list of options"); @@ -68,17 +79,20 @@ async function main(argv) { const options = new Options(); try { // This is more convenient that setting fields one by one. - options.parseArguments([ + let args = [ "--no-screenshot", - // This option shows what puppeteer "code" is run - // "--debug", - // This option disable the headless mode, allowing you to see what's going on. - // "--no-headless", - // The text isn't rendered by default because of a lot of small differences - // between hosts. - // "--show-text", "--variable", "DOC_PATH", opts["doc_folder"], - ]); + ]; + if (opts["debug"]) { + args.push("--debug"); + } + if (opts["show_text"]) { + args.push("--show-text"); + } + if (opts["no_headless"]) { + args.push("--no-headless"); + } + options.parseArguments(args); } catch (error) { console.error(`invalid argument: ${error}`); process.exit(1); diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index db177f75ceae9..31cdc6865a402 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -56,7 +56,6 @@ const EXCEPTION_PATHS: &[&str] = &[ "library/std/src/f32.rs", "library/std/src/f64.rs", "library/std/src/path.rs", - "library/std/src/thread/available_concurrency.rs", "library/std/src/sys_common", // Should only contain abstractions over platforms "library/std/src/net/test.rs", // Utility helpers for tests ];