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:
commit
2c04f0bb17
30 changed files with 535 additions and 204 deletions
|
@ -3,8 +3,6 @@
|
||||||
/// Basically a workaround; see [this comment] for details.
|
/// Basically a workaround; see [this comment] for details.
|
||||||
///
|
///
|
||||||
/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
|
/// [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> {}
|
pub trait Captures<'a> {}
|
||||||
|
|
||||||
impl<'a, T: ?Sized> Captures<'a> for T {}
|
impl<'a, T: ?Sized> Captures<'a> for T {}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::check::{
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||||
use rustc_hir as hir;
|
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::def_id::DefId;
|
||||||
use rustc_hir::{ExprKind, Node, QPath};
|
use rustc_hir::{ExprKind, Node, QPath};
|
||||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||||
|
@ -120,8 +120,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
error_code: &str,
|
error_code: &str,
|
||||||
c_variadic: bool,
|
c_variadic: bool,
|
||||||
sugg_unit: bool| {
|
sugg_unit: bool| {
|
||||||
let (span, start_span, args) = match &expr.kind {
|
let (span, start_span, args, ctor_of) = match &expr.kind {
|
||||||
hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]),
|
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, _) => (
|
hir::ExprKind::MethodCall(path_segment, span, args, _) => (
|
||||||
*span,
|
*span,
|
||||||
// `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
|
// `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),
|
.unwrap_or(*span),
|
||||||
&args[1..], // Skip the receiver.
|
&args[1..], // Skip the receiver.
|
||||||
|
None, // methods are never ctors
|
||||||
),
|
),
|
||||||
k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k),
|
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(
|
let mut err = tcx.sess.struct_span_err_with_code(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&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 { "" },
|
if c_variadic { "at least " } else { "" },
|
||||||
potentially_plural_count(expected_count, "argument"),
|
potentially_plural_count(expected_count, "argument"),
|
||||||
potentially_plural_count(arg_count, "argument"),
|
potentially_plural_count(arg_count, "argument"),
|
||||||
|
|
|
@ -1772,9 +1772,9 @@ macro_rules! int_impl {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_inherit_overflow_checks]
|
#[rustc_inherit_overflow_checks]
|
||||||
pub const fn abs(self) -> Self {
|
pub const fn abs(self) -> Self {
|
||||||
// Note that the #[inline] above means that the overflow
|
// Note that the #[rustc_inherit_overflow_checks] and #[inline]
|
||||||
// semantics of the subtraction depend on the crate we're being
|
// above mean that the overflow semantics of the subtraction
|
||||||
// inlined into.
|
// depend on the crate we're being called from.
|
||||||
if self.is_negative() {
|
if self.is_negative() {
|
||||||
-self
|
-self
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -399,12 +399,11 @@ impl fmt::Display for Backtrace {
|
||||||
let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path);
|
let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path);
|
||||||
f.add_context()?;
|
f.add_context()?;
|
||||||
for frame in frames {
|
for frame in frames {
|
||||||
let mut f = f.frame();
|
|
||||||
if frame.symbols.is_empty() {
|
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 {
|
} else {
|
||||||
for symbol in frame.symbols.iter() {
|
for symbol in frame.symbols.iter() {
|
||||||
f.print_raw_with_column(
|
f.frame().print_raw_with_column(
|
||||||
frame.frame.ip(),
|
frame.frame.ip(),
|
||||||
symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)),
|
symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)),
|
||||||
symbol.filename.as_ref().map(|b| match b {
|
symbol.filename.as_ref().map(|b| match b {
|
||||||
|
|
|
@ -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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Clone for Cursor<T>
|
impl<T> Clone for Cursor<T>
|
||||||
where
|
where
|
||||||
|
@ -268,7 +350,7 @@ where
|
||||||
T: AsRef<[u8]>,
|
T: AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
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;
|
self.pos += n as u64;
|
||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
@ -291,7 +373,7 @@ where
|
||||||
|
|
||||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||||
let n = buf.len();
|
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;
|
self.pos += n as u64;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -308,8 +390,7 @@ where
|
||||||
T: AsRef<[u8]>,
|
T: AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||||
let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64);
|
Ok(self.remaining_slice())
|
||||||
Ok(&self.inner.as_ref()[(amt as usize)..])
|
|
||||||
}
|
}
|
||||||
fn consume(&mut self, amt: usize) {
|
fn consume(&mut self, amt: usize) {
|
||||||
self.pos += amt as u64;
|
self.pos += amt as u64;
|
||||||
|
|
|
@ -33,13 +33,13 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32>
|
||||||
|
|
||||||
asm!(
|
asm!(
|
||||||
// rbx is reserved by LLVM
|
// rbx is reserved by LLVM
|
||||||
"xchg {0}, rbx",
|
"xchg %rbx, {0}",
|
||||||
"enclu",
|
"enclu",
|
||||||
"mov rbx, {0}",
|
"mov {0}, %rbx",
|
||||||
inout(reg) request => _,
|
inout(reg) request => _,
|
||||||
inlateout("eax") ENCLU_EGETKEY => error,
|
inlateout("eax") ENCLU_EGETKEY => error,
|
||||||
in("rcx") out.as_mut_ptr(),
|
in("rcx") out.as_mut_ptr(),
|
||||||
options(nostack),
|
options(att_syntax, nostack),
|
||||||
);
|
);
|
||||||
|
|
||||||
match error {
|
match error {
|
||||||
|
@ -64,14 +64,14 @@ pub fn ereport(
|
||||||
|
|
||||||
asm!(
|
asm!(
|
||||||
// rbx is reserved by LLVM
|
// rbx is reserved by LLVM
|
||||||
"xchg {0}, rbx",
|
"xchg %rbx, {0}",
|
||||||
"enclu",
|
"enclu",
|
||||||
"mov rbx, {0}",
|
"mov {0}, %rbx",
|
||||||
inout(reg) targetinfo => _,
|
inout(reg) targetinfo => _,
|
||||||
in("eax") ENCLU_EREPORT,
|
in("eax") ENCLU_EREPORT,
|
||||||
in("rcx") reportdata,
|
in("rcx") reportdata,
|
||||||
in("rdx") report.as_mut_ptr(),
|
in("rdx") report.as_mut_ptr(),
|
||||||
options(preserves_flags, nostack),
|
options(att_syntax, preserves_flags, nostack),
|
||||||
);
|
);
|
||||||
|
|
||||||
report.assume_init()
|
report.assume_init()
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use super::unsupported;
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::sys::hermit::abi;
|
use crate::sys::hermit::abi;
|
||||||
use crate::sys::hermit::thread_local_dtor::run_dtors;
|
use crate::sys::hermit::thread_local_dtor::run_dtors;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
@ -95,6 +97,10 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -36,9 +36,9 @@ pub fn image_base() -> u64 {
|
||||||
let base: u64;
|
let base: u64;
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"lea {}, qword ptr [rip + IMAGE_BASE]",
|
"lea IMAGE_BASE(%rip), {}",
|
||||||
lateout(reg) base,
|
lateout(reg) base,
|
||||||
options(nostack, preserves_flags, nomem, pure),
|
options(att_syntax, nostack, preserves_flags, nomem, pure),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
base
|
base
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
|
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
|
||||||
|
use super::unsupported;
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
use super::abi::usercalls;
|
use super::abi::usercalls;
|
||||||
|
@ -135,6 +137,10 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::cmp;
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
use crate::sys::{os, stack_overflow};
|
use crate::sys::{os, stack_overflow};
|
||||||
use crate::time::Duration;
|
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(
|
#[cfg(all(
|
||||||
not(target_os = "linux"),
|
not(target_os = "linux"),
|
||||||
not(target_os = "freebsd"),
|
not(target_os = "freebsd"),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use super::unsupported;
|
use super::unsupported;
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
pub struct Thread(!);
|
pub struct Thread(!);
|
||||||
|
@ -30,6 +31,10 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
@ -63,6 +64,10 @@ impl Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
use super::unsupported;
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
@ -39,6 +41,10 @@ impl Thread {
|
||||||
pub fn join(self) {}
|
pub fn join(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
|
|
|
@ -13,6 +13,7 @@ use libc::{c_void, size_t, wchar_t};
|
||||||
pub use self::EXCEPTION_DISPOSITION::*;
|
pub use self::EXCEPTION_DISPOSITION::*;
|
||||||
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
|
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
|
||||||
|
|
||||||
|
pub type DWORD_PTR = ULONG_PTR;
|
||||||
pub type DWORD = c_ulong;
|
pub type DWORD = c_ulong;
|
||||||
pub type NonZeroDWORD = NonZero_c_ulong;
|
pub type NonZeroDWORD = NonZero_c_ulong;
|
||||||
pub type HANDLE = LPVOID;
|
pub type HANDLE = LPVOID;
|
||||||
|
@ -53,6 +54,7 @@ pub type LPWSADATA = *mut WSADATA;
|
||||||
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
|
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
|
||||||
pub type LPWSTR = *mut WCHAR;
|
pub type LPWSTR = *mut WCHAR;
|
||||||
pub type LPFILETIME = *mut FILETIME;
|
pub type LPFILETIME = *mut FILETIME;
|
||||||
|
pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
|
||||||
pub type LPWSABUF = *mut WSABUF;
|
pub type LPWSABUF = *mut WSABUF;
|
||||||
pub type LPWSAOVERLAPPED = *mut c_void;
|
pub type LPWSAOVERLAPPED = *mut c_void;
|
||||||
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
|
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
|
||||||
|
@ -533,6 +535,21 @@ pub struct FILETIME {
|
||||||
pub dwHighDateTime: DWORD,
|
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)]
|
#[repr(C)]
|
||||||
pub struct OVERLAPPED {
|
pub struct OVERLAPPED {
|
||||||
pub Internal: *mut c_ulong,
|
pub Internal: *mut c_ulong,
|
||||||
|
@ -934,6 +951,7 @@ extern "system" {
|
||||||
pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
|
pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
|
||||||
|
|
||||||
pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
|
pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
|
||||||
|
pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
|
||||||
|
|
||||||
pub fn CreateEventW(
|
pub fn CreateEventW(
|
||||||
lpEventAttributes: LPSECURITY_ATTRIBUTES,
|
lpEventAttributes: LPSECURITY_ATTRIBUTES,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
use crate::sys::c;
|
use crate::sys::c;
|
||||||
use crate::sys::handle::Handle;
|
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))]
|
#[cfg_attr(test, allow(dead_code))]
|
||||||
pub mod guard {
|
pub mod guard {
|
||||||
pub type Guard = !;
|
pub type Guard = !;
|
||||||
|
|
|
@ -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"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -155,6 +155,7 @@ use crate::fmt;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::num::NonZeroU64;
|
use crate::num::NonZeroU64;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
use crate::panic;
|
use crate::panic;
|
||||||
use crate::panicking;
|
use crate::panicking;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
|
@ -174,15 +175,9 @@ use crate::time::Duration;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod local;
|
mod local;
|
||||||
|
|
||||||
#[unstable(feature = "available_concurrency", issue = "74479")]
|
|
||||||
mod available_concurrency;
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::local::{AccessError, LocalKey};
|
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
|
// 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
|
// 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
|
// 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::<JoinHandle<()>>();
|
||||||
_assert_both::<Thread>();
|
_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()
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
builder.run(&mut command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
/// Returns:
|
||||||
/// - None if no associated item was found
|
/// - None if no associated item was found
|
||||||
/// - Some((_, _, Some(_))) if an item was found and should go through a side channel
|
/// - 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 {
|
match root_res {
|
||||||
Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name),
|
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(
|
Res::Def(
|
||||||
DefKind::Struct
|
DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::ForeignTy,
|
||||||
| DefKind::Union
|
|
||||||
| DefKind::Enum
|
|
||||||
| DefKind::TyAlias
|
|
||||||
| DefKind::ForeignTy,
|
|
||||||
did,
|
did,
|
||||||
) => {
|
) => {
|
||||||
debug!("looking for associated item named {} for item {:?}", item_name, did);
|
debug!("looking for associated item named {} for item {:?}", item_name, did);
|
||||||
|
|
|
@ -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].
|
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/
|
[browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/
|
||||||
[puppeteer]: https://pptr.dev/
|
[puppeteer]: https://pptr.dev/
|
||||||
|
|
19
src/test/rustdoc/intra-doc/type-alias.rs
Normal file
19
src/test/rustdoc/intra-doc/type-alias.rs
Normal 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'
|
13
src/test/ui/consts/issue-39161-bogus-error.rs
Normal file
13
src/test/ui/consts/issue-39161-bogus-error.rs
Normal 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 };
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ impl S {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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
|
||||||
foo(()); //~ ERROR this function takes
|
foo(()); //~ ERROR this function takes
|
||||||
bar(); //~ ERROR this function takes
|
bar(); //~ ERROR this function takes
|
||||||
|
|
|
@ -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
|
--> $DIR/missing-unit-argument.rs:11:33
|
||||||
|
|
|
|
||||||
LL | let _: Result<(), String> = Ok();
|
LL | let _: Result<(), String> = Ok();
|
||||||
|
|
14
src/test/ui/typeck/struct-enum-wrong-args.rs
Normal file
14
src/test/ui/typeck/struct-enum-wrong-args.rs
Normal 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
|
||||||
|
}
|
67
src/test/ui/typeck/struct-enum-wrong-args.stderr
Normal file
67
src/test/ui/typeck/struct-enum-wrong-args.stderr
Normal 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
|
|
@ -11,6 +11,9 @@ function showHelp() {
|
||||||
console.log("rustdoc-js options:");
|
console.log("rustdoc-js options:");
|
||||||
console.log(" --doc-folder [PATH] : location of the generated doc folder");
|
console.log(" --doc-folder [PATH] : location of the generated doc folder");
|
||||||
console.log(" --file [PATH] : file to run (can be repeated)");
|
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(" --help : show this message then quit");
|
||||||
console.log(" --tests-folder [PATH] : location of the .GOML tests folder");
|
console.log(" --tests-folder [PATH] : location of the .GOML tests folder");
|
||||||
}
|
}
|
||||||
|
@ -20,10 +23,16 @@ function parseOptions(args) {
|
||||||
"doc_folder": "",
|
"doc_folder": "",
|
||||||
"tests_folder": "",
|
"tests_folder": "",
|
||||||
"files": [],
|
"files": [],
|
||||||
|
"debug": false,
|
||||||
|
"show_text": false,
|
||||||
|
"no_headless": false,
|
||||||
};
|
};
|
||||||
var correspondances = {
|
var correspondances = {
|
||||||
"--doc-folder": "doc_folder",
|
"--doc-folder": "doc_folder",
|
||||||
"--tests-folder": "tests_folder",
|
"--tests-folder": "tests_folder",
|
||||||
|
"--debug": "debug",
|
||||||
|
"--show-text": "show_text",
|
||||||
|
"--no-headless": "no_headless",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var i = 0; i < args.length; ++i) {
|
for (var i = 0; i < args.length; ++i) {
|
||||||
|
@ -43,6 +52,8 @@ function parseOptions(args) {
|
||||||
} else if (args[i] === "--help") {
|
} else if (args[i] === "--help") {
|
||||||
showHelp();
|
showHelp();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
} else if (correspondances[args[i]]) {
|
||||||
|
opts[correspondances[args[i]]] = true;
|
||||||
} else {
|
} else {
|
||||||
console.log("Unknown option `" + args[i] + "`.");
|
console.log("Unknown option `" + args[i] + "`.");
|
||||||
console.log("Use `--help` to see the list of options");
|
console.log("Use `--help` to see the list of options");
|
||||||
|
@ -68,17 +79,20 @@ async function main(argv) {
|
||||||
const options = new Options();
|
const options = new Options();
|
||||||
try {
|
try {
|
||||||
// This is more convenient that setting fields one by one.
|
// This is more convenient that setting fields one by one.
|
||||||
options.parseArguments([
|
let args = [
|
||||||
"--no-screenshot",
|
"--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"],
|
"--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) {
|
} catch (error) {
|
||||||
console.error(`invalid argument: ${error}`);
|
console.error(`invalid argument: ${error}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|
|
@ -56,7 +56,6 @@ const EXCEPTION_PATHS: &[&str] = &[
|
||||||
"library/std/src/f32.rs",
|
"library/std/src/f32.rs",
|
||||||
"library/std/src/f64.rs",
|
"library/std/src/f64.rs",
|
||||||
"library/std/src/path.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/sys_common", // Should only contain abstractions over platforms
|
||||||
"library/std/src/net/test.rs", // Utility helpers for tests
|
"library/std/src/net/test.rs", // Utility helpers for tests
|
||||||
];
|
];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue