Auto merge of #86527 - JohnTitor:rollup-cbu78g4, r=JohnTitor

Rollup of 11 pull requests

Successful merges:

 - #85054 (Revert SGX inline asm syntax)
 - #85182 (Move `available_concurrency` implementation to `sys`)
 - #86037 (Add `io::Cursor::{remaining, remaining_slice, is_empty}`)
 - #86114 (Reopen #79692 (Format symbols under shared frames))
 - #86297 (Allow to pass arguments to rustdoc-gui tool)
 - #86334 (Resolve type aliases to the type they point to in intra-doc links)
 - #86367 (Fix comment about rustc_inherit_overflow_checks in abs().)
 - #86381 (Add regression test for issue #39161)
 - #86387 (Remove `#[allow(unused_lifetimes)]` which is now unnecessary)
 - #86398 (Add regression test for issue #54685)
 - #86493 (Say "this enum variant takes"/"this struct takes" instead of "this function takes")

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-06-22 01:14:31 +00:00
commit 2c04f0bb17
30 changed files with 535 additions and 204 deletions

View File

@ -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 {}

View File

@ -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"),

View File

@ -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 {

View File

@ -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 {

View File

@ -205,6 +205,88 @@ impl<T> Cursor<T> {
}
}
impl<T> Cursor<T>
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<T> Clone for Cursor<T>
where
@ -268,7 +350,7 @@ where
T: AsRef<[u8]>,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
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;

View File

@ -33,13 +33,13 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, 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()

View File

@ -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<NonZeroUsize> {
unsupported()
}
pub mod guard {
pub type Guard = !;
pub unsafe fn current() -> Option<Guard> {

View File

@ -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

View File

@ -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<NonZeroUsize> {
unsupported()
}
pub mod guard {
pub type Guard = !;
pub unsafe fn current() -> Option<Guard> {

View File

@ -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<NonZeroUsize> {
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"),

View File

@ -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<NonZeroUsize> {
unsupported()
}
pub mod guard {
pub type Guard = !;
pub unsafe fn current() -> Option<Guard> {

View File

@ -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<NonZeroUsize> {
unsupported()
}
pub mod guard {
pub type Guard = !;
pub unsafe fn current() -> Option<Guard> {

View File

@ -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<NonZeroUsize> {
unsupported()
}
pub mod guard {
pub type Guard = !;
pub unsafe fn current() -> Option<Guard> {

View File

@ -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,

View File

@ -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<NonZeroUsize> {
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 = !;

View File

@ -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<NonZeroUsize> {
available_concurrency_internal()
}
cfg_if::cfg_if! {
if #[cfg(windows)] {
#[allow(nonstandard_style)]
fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
#[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<NonZeroUsize> {
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<NonZeroUsize> {
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<NonZeroUsize> {
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<NonZeroUsize> {
Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"))
}
}
}

View File

@ -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::<JoinHandle<()>>();
_assert_both::<Thread>();
}
/// 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<NonZeroUsize> {
imp::available_concurrency()
}

View File

@ -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);
}
}

View File

@ -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<Res> {
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);

View File

@ -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/

View File

@ -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'

View File

@ -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 };
}

View File

@ -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);
}

View File

@ -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

View File

@ -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();

View File

@ -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
}

View File

@ -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`.

@ -1 +1 @@
Subproject commit f0618a8f06a464840079f30b3e25bcdcca3922a3
Subproject commit 13da28cc2bc1b59f7af817eca36927a71edb023c

View File

@ -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);

View File

@ -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
];