Auto merge of #86186 - JohnTitor:rollup-upaw6wx, r=JohnTitor
Rollup of 7 pull requests Successful merges: - #82037 (Make symbols stripping work on MacOS X) - #84687 (Multiple improvements to RwLocks) - #85997 (rustdoc: Print a warning if the diff when comparing to old nightlies is empty) - #86051 (Updated code examples and wording in move keyword documentation ) - #86111 (fix off by one in `std::iter::Iterator` documentation) - #86113 (build doctests with lld if use-lld = true) - #86175 (update Miri) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c5fbcd35a8
20 changed files with 220 additions and 185 deletions
|
@ -5,7 +5,7 @@ use rustc_fs_util::fix_windows_verbatim_for_gcc;
|
|||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_middle::middle::cstore::{DllImport, LibSource};
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, Strip};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
|
||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||
use rustc_session::search_paths::PathKind;
|
||||
|
@ -907,14 +907,6 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||
}
|
||||
}
|
||||
|
||||
fn escape_string(s: &[u8]) -> String {
|
||||
str::from_utf8(s).map(|s| s.to_owned()).unwrap_or_else(|_| {
|
||||
let mut x = "Non-UTF-8 output: ".to_string();
|
||||
x.extend(s.iter().flat_map(|&b| ascii::escape_default(b)).map(char::from));
|
||||
x
|
||||
})
|
||||
}
|
||||
|
||||
match prog {
|
||||
Ok(prog) => {
|
||||
if !prog.status.success() {
|
||||
|
@ -1056,6 +1048,47 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||
// ... and otherwise we're processing a `*.dwp` packed dwarf file.
|
||||
SplitDebuginfo::Packed => link_dwarf_object(sess, &out_filename),
|
||||
}
|
||||
|
||||
if sess.target.is_like_osx {
|
||||
if let Some(option) = osx_strip_opt(sess.opts.debugging_opts.strip) {
|
||||
strip_symbols_in_osx(sess, &out_filename, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: &str) {
|
||||
let prog = Command::new("strip").arg(option).arg(out_filename).output();
|
||||
match prog {
|
||||
Ok(prog) => {
|
||||
if !prog.status.success() {
|
||||
let mut output = prog.stderr.clone();
|
||||
output.extend_from_slice(&prog.stdout);
|
||||
sess.struct_warn(&format!(
|
||||
"stripping debug info with `strip` failed: {}",
|
||||
prog.status
|
||||
))
|
||||
.note(&escape_string(&output))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
Err(e) => sess.fatal(&format!("unable to run `strip`: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
fn osx_strip_opt<'a>(strip: Strip) -> Option<&'a str> {
|
||||
match strip {
|
||||
Strip::Debuginfo => Some("-S"),
|
||||
Strip::Symbols => Some("-x"),
|
||||
Strip::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn escape_string(s: &[u8]) -> String {
|
||||
str::from_utf8(s).map(|s| s.to_owned()).unwrap_or_else(|_| {
|
||||
let mut x = "Non-UTF-8 output: ".to_string();
|
||||
x.extend(s.iter().flat_map(|&b| ascii::escape_default(b)).map(char::from));
|
||||
x
|
||||
})
|
||||
}
|
||||
|
||||
fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
|
||||
|
|
|
@ -526,15 +526,18 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
fn control_flow_guard(&mut self) {}
|
||||
|
||||
fn debuginfo(&mut self, strip: Strip) {
|
||||
// MacOS linker doesn't support stripping symbols directly anymore.
|
||||
if self.sess.target.is_like_osx {
|
||||
return;
|
||||
}
|
||||
|
||||
match strip {
|
||||
Strip::None => {}
|
||||
Strip::Debuginfo => {
|
||||
// MacOS linker does not support longhand argument --strip-debug
|
||||
self.linker_arg("-S");
|
||||
self.linker_arg("--strip-debug");
|
||||
}
|
||||
Strip::Symbols => {
|
||||
// MacOS linker does not support longhand argument --strip-all
|
||||
self.linker_arg("-s");
|
||||
self.linker_arg("--strip-all");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ pub trait Iterator {
|
|||
/// A more complex example:
|
||||
///
|
||||
/// ```
|
||||
/// // The even numbers from zero to ten.
|
||||
/// // The even numbers in the range of zero to nine.
|
||||
/// let iter = (0..10).filter(|x| x % 2 == 0);
|
||||
///
|
||||
/// // We might iterate from zero to ten times. Knowing that it's five
|
||||
|
|
|
@ -987,13 +987,13 @@ mod mod_keyword {}
|
|||
/// Capture a [closure]'s environment by value.
|
||||
///
|
||||
/// `move` converts any variables captured by reference or mutable reference
|
||||
/// to owned by value variables.
|
||||
/// to variables captured by value.
|
||||
///
|
||||
/// ```rust
|
||||
/// let capture = "hello";
|
||||
/// let closure = move || {
|
||||
/// println!("rust says {}", capture);
|
||||
/// };
|
||||
/// let data = vec![1, 2, 3];
|
||||
/// let closure = move || println!("captured {:?} by value", data);
|
||||
///
|
||||
/// // data is no longer available, it is owned by the closure
|
||||
/// ```
|
||||
///
|
||||
/// Note: `move` closures may still implement [`Fn`] or [`FnMut`], even though
|
||||
|
@ -1004,31 +1004,29 @@ mod mod_keyword {}
|
|||
/// ```rust
|
||||
/// fn create_fn() -> impl Fn() {
|
||||
/// let text = "Fn".to_owned();
|
||||
///
|
||||
/// move || println!("This is a: {}", text)
|
||||
/// }
|
||||
///
|
||||
/// let fn_plain = create_fn();
|
||||
///
|
||||
/// fn_plain();
|
||||
/// ```
|
||||
///
|
||||
/// `move` is often used when [threads] are involved.
|
||||
///
|
||||
/// ```rust
|
||||
/// let x = 5;
|
||||
/// let data = vec![1, 2, 3];
|
||||
///
|
||||
/// std::thread::spawn(move || {
|
||||
/// println!("captured {} by value", x)
|
||||
/// println!("captured {:?} by value", data)
|
||||
/// }).join().unwrap();
|
||||
///
|
||||
/// // x is no longer available
|
||||
/// // data was moved to the spawned thread, so we cannot use it here
|
||||
/// ```
|
||||
///
|
||||
/// `move` is also valid before an async block.
|
||||
///
|
||||
/// ```rust
|
||||
/// let capture = "hello";
|
||||
/// let capture = "hello".to_owned();
|
||||
/// let block = async move {
|
||||
/// println!("rust says {} from async block", capture);
|
||||
/// };
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::process;
|
|||
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||
use crate::sys::stdio::panic_output;
|
||||
use crate::sys_common::backtrace::{self, RustBacktrace};
|
||||
use crate::sys_common::rwlock::RWLock;
|
||||
use crate::sys_common::rwlock::StaticRWLock;
|
||||
use crate::sys_common::thread_info;
|
||||
use crate::thread;
|
||||
|
||||
|
@ -74,7 +74,7 @@ enum Hook {
|
|||
Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
|
||||
}
|
||||
|
||||
static HOOK_LOCK: RWLock = RWLock::new();
|
||||
static HOOK_LOCK: StaticRWLock = StaticRWLock::new();
|
||||
static mut HOOK: Hook = Hook::Default;
|
||||
|
||||
/// Registers a custom panic hook, replacing any that was previously registered.
|
||||
|
@ -117,10 +117,10 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
HOOK_LOCK.write();
|
||||
let guard = HOOK_LOCK.write();
|
||||
let old_hook = HOOK;
|
||||
HOOK = Hook::Custom(Box::into_raw(hook));
|
||||
HOOK_LOCK.write_unlock();
|
||||
drop(guard);
|
||||
|
||||
if let Hook::Custom(ptr) = old_hook {
|
||||
#[allow(unused_must_use)]
|
||||
|
@ -165,10 +165,10 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
HOOK_LOCK.write();
|
||||
let guard = HOOK_LOCK.write();
|
||||
let hook = HOOK;
|
||||
HOOK = Hook::Default;
|
||||
HOOK_LOCK.write_unlock();
|
||||
drop(guard);
|
||||
|
||||
match hook {
|
||||
Hook::Default => Box::new(default_hook),
|
||||
|
@ -608,7 +608,7 @@ fn rust_panic_with_hook(
|
|||
|
||||
unsafe {
|
||||
let mut info = PanicInfo::internal_constructor(message, location);
|
||||
HOOK_LOCK.read();
|
||||
let _guard = HOOK_LOCK.read();
|
||||
match HOOK {
|
||||
// Some platforms (like wasm) know that printing to stderr won't ever actually
|
||||
// print anything, and if that's the case we can skip the default
|
||||
|
@ -626,7 +626,6 @@ fn rust_panic_with_hook(
|
|||
(*ptr)(&info);
|
||||
}
|
||||
};
|
||||
HOOK_LOCK.read_unlock();
|
||||
}
|
||||
|
||||
if panics > 1 {
|
||||
|
|
|
@ -3,9 +3,7 @@ mod tests;
|
|||
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::fmt;
|
||||
use crate::mem;
|
||||
use crate::ops::{Deref, DerefMut};
|
||||
use crate::ptr;
|
||||
use crate::sync::{poison, LockResult, TryLockError, TryLockResult};
|
||||
use crate::sys_common::rwlock as sys;
|
||||
|
||||
|
@ -66,7 +64,7 @@ use crate::sys_common::rwlock as sys;
|
|||
/// [`Mutex`]: super::Mutex
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct RwLock<T: ?Sized> {
|
||||
inner: Box<sys::RWLock>,
|
||||
inner: sys::MovableRWLock,
|
||||
poison: poison::Flag,
|
||||
data: UnsafeCell<T>,
|
||||
}
|
||||
|
@ -130,7 +128,7 @@ impl<T> RwLock<T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(t: T) -> RwLock<T> {
|
||||
RwLock {
|
||||
inner: box sys::RWLock::new(),
|
||||
inner: sys::MovableRWLock::new(),
|
||||
poison: poison::Flag::new(),
|
||||
data: UnsafeCell::new(t),
|
||||
}
|
||||
|
@ -376,24 +374,8 @@ impl<T: ?Sized> RwLock<T> {
|
|||
where
|
||||
T: Sized,
|
||||
{
|
||||
// We know statically that there are no outstanding references to
|
||||
// `self` so there's no need to lock the inner lock.
|
||||
//
|
||||
// To get the inner value, we'd like to call `data.into_inner()`,
|
||||
// but because `RwLock` impl-s `Drop`, we can't move out of it, so
|
||||
// we'll have to destructure it manually instead.
|
||||
unsafe {
|
||||
// Like `let RwLock { inner, poison, data } = self`.
|
||||
let (inner, poison, data) = {
|
||||
let RwLock { ref inner, ref poison, ref data } = self;
|
||||
(ptr::read(inner), ptr::read(poison), ptr::read(data))
|
||||
};
|
||||
mem::forget(self);
|
||||
inner.destroy(); // Keep in sync with the `Drop` impl.
|
||||
drop(inner);
|
||||
|
||||
poison::map_result(poison.borrow(), |_| data.into_inner())
|
||||
}
|
||||
let data = self.data.into_inner();
|
||||
poison::map_result(self.poison.borrow(), |_| data)
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the underlying data.
|
||||
|
@ -424,14 +406,6 @@ impl<T: ?Sized> RwLock<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock<T> {
|
||||
fn drop(&mut self) {
|
||||
// IMPORTANT: This code needs to be kept in sync with `RwLock::into_inner`.
|
||||
unsafe { self.inner.destroy() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
|
@ -8,6 +8,8 @@ pub struct RWLock {
|
|||
state: UnsafeCell<State>,
|
||||
}
|
||||
|
||||
pub type MovableRWLock = Box<RWLock>;
|
||||
|
||||
enum State {
|
||||
Unlocked,
|
||||
Reading(usize),
|
||||
|
|
|
@ -13,6 +13,8 @@ pub struct RWLock {
|
|||
writer: SpinMutex<WaitVariable<bool>>,
|
||||
}
|
||||
|
||||
pub type MovableRWLock = Box<RWLock>;
|
||||
|
||||
// Check at compile time that RWLock size matches C definition (see test_c_rwlock_initializer below)
|
||||
//
|
||||
// # Safety
|
||||
|
|
|
@ -20,8 +20,7 @@ use crate::str;
|
|||
use crate::sys::cvt;
|
||||
use crate::sys::fd;
|
||||
use crate::sys::memchr;
|
||||
use crate::sys::rwlock::{RWLockReadGuard, StaticRWLock};
|
||||
use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard};
|
||||
use crate::sys_common::rwlock::{StaticRWLock, StaticRWLockReadGuard};
|
||||
use crate::vec;
|
||||
|
||||
use libc::{c_char, c_int, c_void};
|
||||
|
@ -490,8 +489,8 @@ pub unsafe fn environ() -> *mut *const *const c_char {
|
|||
|
||||
static ENV_LOCK: StaticRWLock = StaticRWLock::new();
|
||||
|
||||
pub fn env_read_lock() -> RWLockReadGuard {
|
||||
ENV_LOCK.read_with_guard()
|
||||
pub fn env_read_lock() -> StaticRWLockReadGuard {
|
||||
ENV_LOCK.read()
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
|
@ -551,7 +550,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
|||
let v = CString::new(v.as_bytes())?;
|
||||
|
||||
unsafe {
|
||||
let _guard = ENV_LOCK.write_with_guard();
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
|
||||
}
|
||||
}
|
||||
|
@ -560,7 +559,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
|
|||
let nbuf = CString::new(n.as_bytes())?;
|
||||
|
||||
unsafe {
|
||||
let _guard = ENV_LOCK.write_with_guard();
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ pub struct RWLock {
|
|||
num_readers: AtomicUsize,
|
||||
}
|
||||
|
||||
pub type MovableRWLock = Box<RWLock>;
|
||||
|
||||
unsafe impl Send for RWLock {}
|
||||
unsafe impl Sync for RWLock {}
|
||||
|
||||
|
@ -139,55 +141,3 @@ impl RWLock {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StaticRWLock(RWLock);
|
||||
|
||||
impl StaticRWLock {
|
||||
pub const fn new() -> StaticRWLock {
|
||||
StaticRWLock(RWLock::new())
|
||||
}
|
||||
|
||||
/// Acquires shared access to the underlying lock, blocking the current
|
||||
/// thread to do so.
|
||||
///
|
||||
/// The lock is automatically unlocked when the returned guard is dropped.
|
||||
#[inline]
|
||||
pub fn read_with_guard(&'static self) -> RWLockReadGuard {
|
||||
// SAFETY: All methods require static references, therefore self
|
||||
// cannot be moved between invocations.
|
||||
unsafe {
|
||||
self.0.read();
|
||||
}
|
||||
RWLockReadGuard(&self.0)
|
||||
}
|
||||
|
||||
/// Acquires write access to the underlying lock, blocking the current thread
|
||||
/// to do so.
|
||||
///
|
||||
/// The lock is automatically unlocked when the returned guard is dropped.
|
||||
#[inline]
|
||||
pub fn write_with_guard(&'static self) -> RWLockWriteGuard {
|
||||
// SAFETY: All methods require static references, therefore self
|
||||
// cannot be moved between invocations.
|
||||
unsafe {
|
||||
self.0.write();
|
||||
}
|
||||
RWLockWriteGuard(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RWLockReadGuard(&'static RWLock);
|
||||
|
||||
impl Drop for RWLockReadGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.0.read_unlock() }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RWLockWriteGuard(&'static RWLock);
|
||||
|
||||
impl Drop for RWLockWriteGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.0.write_unlock() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ pub struct RWLock {
|
|||
mode: Cell<isize>,
|
||||
}
|
||||
|
||||
pub type MovableRWLock = RWLock;
|
||||
|
||||
unsafe impl Send for RWLock {}
|
||||
unsafe impl Sync for RWLock {} // no threads on this platform
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ pub struct RWLock {
|
|||
state: UnsafeCell<State>,
|
||||
}
|
||||
|
||||
pub type MovableRWLock = RWLock;
|
||||
|
||||
enum State {
|
||||
Unlocked,
|
||||
Reading(usize),
|
||||
|
|
|
@ -5,6 +5,8 @@ pub struct RWLock {
|
|||
inner: UnsafeCell<c::SRWLOCK>,
|
||||
}
|
||||
|
||||
pub type MovableRWLock = RWLock;
|
||||
|
||||
unsafe impl Send for RWLock {}
|
||||
unsafe impl Sync for RWLock {}
|
||||
|
||||
|
|
|
@ -1,63 +1,112 @@
|
|||
use crate::sys::rwlock as imp;
|
||||
|
||||
/// An OS-based reader-writer lock.
|
||||
/// An OS-based reader-writer lock, meant for use in static variables.
|
||||
///
|
||||
/// This structure is entirely unsafe and serves as the lowest layer of a
|
||||
/// cross-platform binding of system rwlocks. It is recommended to use the
|
||||
/// safer types at the top level of this crate instead of this type.
|
||||
pub struct RWLock(imp::RWLock);
|
||||
/// This rwlock does not implement poisoning.
|
||||
///
|
||||
/// This rwlock has a const constructor ([`StaticRWLock::new`]), does not
|
||||
/// implement `Drop` to cleanup resources.
|
||||
pub struct StaticRWLock(imp::RWLock);
|
||||
|
||||
impl RWLock {
|
||||
/// Creates a new reader-writer lock for use.
|
||||
///
|
||||
/// Behavior is undefined if the reader-writer lock is moved after it is
|
||||
/// first used with any of the functions below.
|
||||
pub const fn new() -> RWLock {
|
||||
RWLock(imp::RWLock::new())
|
||||
impl StaticRWLock {
|
||||
/// Creates a new rwlock for use.
|
||||
pub const fn new() -> Self {
|
||||
Self(imp::RWLock::new())
|
||||
}
|
||||
|
||||
/// Acquires shared access to the underlying lock, blocking the current
|
||||
/// thread to do so.
|
||||
///
|
||||
/// Behavior is undefined if the rwlock has been moved between this and any
|
||||
/// previous method call.
|
||||
/// The lock is automatically unlocked when the returned guard is dropped.
|
||||
#[inline]
|
||||
pub unsafe fn read(&self) {
|
||||
self.0.read()
|
||||
pub fn read(&'static self) -> StaticRWLockReadGuard {
|
||||
unsafe { self.0.read() };
|
||||
StaticRWLockReadGuard(&self.0)
|
||||
}
|
||||
|
||||
/// Acquires write access to the underlying lock, blocking the current thread
|
||||
/// to do so.
|
||||
///
|
||||
/// The lock is automatically unlocked when the returned guard is dropped.
|
||||
#[inline]
|
||||
pub fn write(&'static self) -> StaticRWLockWriteGuard {
|
||||
unsafe { self.0.write() };
|
||||
StaticRWLockWriteGuard(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct StaticRWLockReadGuard(&'static imp::RWLock);
|
||||
|
||||
impl Drop for StaticRWLockReadGuard {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.0.read_unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct StaticRWLockWriteGuard(&'static imp::RWLock);
|
||||
|
||||
impl Drop for StaticRWLockWriteGuard {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.0.write_unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An OS-based reader-writer lock.
|
||||
///
|
||||
/// This rwlock does *not* have a const constructor, cleans up its resources in
|
||||
/// its `Drop` implementation and may safely be moved (when not borrowed).
|
||||
///
|
||||
/// This rwlock does not implement poisoning.
|
||||
///
|
||||
/// This is either a wrapper around `Box<imp::RWLock>` or `imp::RWLock`,
|
||||
/// depending on the platform. It is boxed on platforms where `imp::RWLock` may
|
||||
/// not be moved.
|
||||
pub struct MovableRWLock(imp::MovableRWLock);
|
||||
|
||||
impl MovableRWLock {
|
||||
/// Creates a new reader-writer lock for use.
|
||||
pub fn new() -> Self {
|
||||
Self(imp::MovableRWLock::from(imp::RWLock::new()))
|
||||
}
|
||||
|
||||
/// Acquires shared access to the underlying lock, blocking the current
|
||||
/// thread to do so.
|
||||
#[inline]
|
||||
pub fn read(&self) {
|
||||
unsafe { self.0.read() }
|
||||
}
|
||||
|
||||
/// Attempts to acquire shared access to this lock, returning whether it
|
||||
/// succeeded or not.
|
||||
///
|
||||
/// This function does not block the current thread.
|
||||
///
|
||||
/// Behavior is undefined if the rwlock has been moved between this and any
|
||||
/// previous method call.
|
||||
#[inline]
|
||||
pub unsafe fn try_read(&self) -> bool {
|
||||
self.0.try_read()
|
||||
pub fn try_read(&self) -> bool {
|
||||
unsafe { self.0.try_read() }
|
||||
}
|
||||
|
||||
/// Acquires write access to the underlying lock, blocking the current thread
|
||||
/// to do so.
|
||||
///
|
||||
/// Behavior is undefined if the rwlock has been moved between this and any
|
||||
/// previous method call.
|
||||
#[inline]
|
||||
pub unsafe fn write(&self) {
|
||||
self.0.write()
|
||||
pub fn write(&self) {
|
||||
unsafe { self.0.write() }
|
||||
}
|
||||
|
||||
/// Attempts to acquire exclusive access to this lock, returning whether it
|
||||
/// succeeded or not.
|
||||
///
|
||||
/// This function does not block the current thread.
|
||||
///
|
||||
/// Behavior is undefined if the rwlock has been moved between this and any
|
||||
/// previous method call.
|
||||
#[inline]
|
||||
pub unsafe fn try_write(&self) -> bool {
|
||||
self.0.try_write()
|
||||
pub fn try_write(&self) -> bool {
|
||||
unsafe { self.0.try_write() }
|
||||
}
|
||||
|
||||
/// Unlocks previously acquired shared access to this lock.
|
||||
|
@ -76,13 +125,10 @@ impl RWLock {
|
|||
pub unsafe fn write_unlock(&self) {
|
||||
self.0.write_unlock()
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys OS-related resources with this RWLock.
|
||||
///
|
||||
/// Behavior is undefined if there are any currently active users of this
|
||||
/// lock.
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
self.0.destroy()
|
||||
impl Drop for MovableRWLock {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.0.destroy() };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,12 @@ fn main() {
|
|||
cmd.arg(arg);
|
||||
}
|
||||
if env::var_os("RUSTDOC_FUSE_LD_LLD").is_some() {
|
||||
cmd.arg("-Clink-args=-fuse-ld=lld");
|
||||
cmd.arg("-Clink-arg=-fuse-ld=lld");
|
||||
if cfg!(windows) {
|
||||
cmd.arg("-Clink-arg=-Wl,/threads:1");
|
||||
} else {
|
||||
cmd.arg("-Clink-arg=-Wl,--threads=1");
|
||||
}
|
||||
}
|
||||
|
||||
// Needed to be able to run all rustdoc tests.
|
||||
|
|
|
@ -1142,6 +1142,7 @@ impl<'a> Builder<'a> {
|
|||
}
|
||||
if self.is_fuse_ld_lld(compiler.host) {
|
||||
cargo.env("RUSTC_HOST_FUSE_LD_LLD", "1");
|
||||
cargo.env("RUSTDOC_FUSE_LD_LLD", "1");
|
||||
}
|
||||
|
||||
if let Some(target_linker) = self.linker(target) {
|
||||
|
@ -1151,6 +1152,9 @@ impl<'a> Builder<'a> {
|
|||
if self.is_fuse_ld_lld(target) {
|
||||
rustflags.arg("-Clink-args=-fuse-ld=lld");
|
||||
}
|
||||
self.lld_flags(target).for_each(|flag| {
|
||||
rustdocflags.arg(&flag);
|
||||
});
|
||||
|
||||
if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc {
|
||||
cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler));
|
||||
|
|
|
@ -923,6 +923,21 @@ impl Build {
|
|||
self.config.use_lld && !target.contains("msvc")
|
||||
}
|
||||
|
||||
fn lld_flags(&self, target: TargetSelection) -> impl Iterator<Item = String> {
|
||||
let mut options = [None, None];
|
||||
|
||||
if self.config.use_lld {
|
||||
if self.is_fuse_ld_lld(target) {
|
||||
options[0] = Some("-Clink-arg=-fuse-ld=lld".to_string());
|
||||
}
|
||||
|
||||
let threads = if target.contains("windows") { "/threads:1" } else { "--threads=1" };
|
||||
options[1] = Some(format!("-Clink-arg=-Wl,{}", threads));
|
||||
}
|
||||
|
||||
std::array::IntoIter::new(options).flatten()
|
||||
}
|
||||
|
||||
/// Returns if this target should statically link the C runtime, if specified
|
||||
fn crt_static(&self, target: TargetSelection) -> Option<bool> {
|
||||
if target.contains("pc-windows-msvc") {
|
||||
|
|
|
@ -1131,19 +1131,6 @@ struct Compiletest {
|
|||
compare_mode: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl Compiletest {
|
||||
fn add_lld_flags(builder: &Builder<'_>, target: TargetSelection, flags: &mut Vec<String>) {
|
||||
if builder.config.use_lld {
|
||||
if builder.is_fuse_ld_lld(target) {
|
||||
flags.push("-Clink-arg=-fuse-ld=lld".to_string());
|
||||
}
|
||||
|
||||
let threads = if target.contains("windows") { "/threads:1" } else { "--threads=1" };
|
||||
flags.push(format!("-Clink-arg=-Wl,{}", threads));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Step for Compiletest {
|
||||
type Output = ();
|
||||
|
||||
|
@ -1289,12 +1276,12 @@ note: if you're sure you want to do this, please open an issue as to why. In the
|
|||
|
||||
let mut hostflags = flags.clone();
|
||||
hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
|
||||
Self::add_lld_flags(builder, compiler.host, &mut hostflags);
|
||||
hostflags.extend(builder.lld_flags(compiler.host));
|
||||
cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
|
||||
|
||||
let mut targetflags = flags;
|
||||
targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
|
||||
Self::add_lld_flags(builder, target, &mut targetflags);
|
||||
targetflags.extend(builder.lld_flags(target));
|
||||
cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
|
||||
|
||||
cmd.arg("--docck-python").arg(builder.python());
|
||||
|
|
|
@ -2488,6 +2488,7 @@ impl<'test> TestCx<'test> {
|
|||
|
||||
{
|
||||
let mut diff_output = File::create(&diff_filename).unwrap();
|
||||
let mut wrote_data = false;
|
||||
for entry in walkdir::WalkDir::new(out_dir) {
|
||||
let entry = entry.expect("failed to read file");
|
||||
let extension = entry.path().extension().and_then(|p| p.to_str());
|
||||
|
@ -2500,17 +2501,28 @@ impl<'test> TestCx<'test> {
|
|||
if let Ok(s) = std::fs::read(&expected_path) { s } else { continue };
|
||||
let actual_path = entry.path();
|
||||
let actual = std::fs::read(&actual_path).unwrap();
|
||||
diff_output
|
||||
.write_all(&unified_diff::diff(
|
||||
&expected,
|
||||
&expected_path.to_string_lossy(),
|
||||
&actual,
|
||||
&actual_path.to_string_lossy(),
|
||||
3,
|
||||
))
|
||||
.unwrap();
|
||||
let diff = unified_diff::diff(
|
||||
&expected,
|
||||
&expected_path.to_string_lossy(),
|
||||
&actual,
|
||||
&actual_path.to_string_lossy(),
|
||||
3,
|
||||
);
|
||||
wrote_data |= !diff.is_empty();
|
||||
diff_output.write_all(&diff).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
if !wrote_data {
|
||||
println!("note: diff is identical to nightly rustdoc");
|
||||
assert!(diff_output.metadata().unwrap().len() == 0);
|
||||
return;
|
||||
} else if self.config.verbose {
|
||||
eprintln!("printing diff:");
|
||||
let mut buf = Vec::new();
|
||||
diff_output.read_to_end(&mut buf).unwrap();
|
||||
std::io::stderr().lock().write_all(&mut buf).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
match self.config.color {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c8713c2f9fc1e28c90876b9ec9557d8c5729757b
|
||||
Subproject commit e5c3af6f516311cc4b1fc017c58d83b7442cbc34
|
Loading…
Add table
Add a link
Reference in a new issue