diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 6a2005b4d23ed..cb56e3f9e8a19 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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) { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 1d53e9ad8b34c..43ff664c3e641 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -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"); } } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 96b924f6e2ad4..11dea400a46ef 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -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 diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index ba2b8b6955d66..5b8e83766f0e8 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -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); /// }; diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index e591e073e7bbb..0b9c9fb479f51 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -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) + '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) + '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 { diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 9d521ab14cbf3..0d00f74eaa1ec 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -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 { - inner: Box, + inner: sys::MovableRWLock, poison: poison::Flag, data: UnsafeCell, } @@ -130,7 +128,7 @@ impl RwLock { #[stable(feature = "rust1", since = "1.0.0")] pub fn new(t: T) -> RwLock { RwLock { - inner: box sys::RWLock::new(), + inner: sys::MovableRWLock::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t), } @@ -376,24 +374,8 @@ impl RwLock { 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 RwLock { } } -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock { - 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 fmt::Debug for RwLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/std/src/sys/hermit/rwlock.rs b/library/std/src/sys/hermit/rwlock.rs index 06442e925f4c8..d2058180121dc 100644 --- a/library/std/src/sys/hermit/rwlock.rs +++ b/library/std/src/sys/hermit/rwlock.rs @@ -8,6 +8,8 @@ pub struct RWLock { state: UnsafeCell, } +pub type MovableRWLock = Box; + enum State { Unlocked, Reading(usize), diff --git a/library/std/src/sys/sgx/rwlock.rs b/library/std/src/sys/sgx/rwlock.rs index 0c96e3fcddcdf..2d038b518965b 100644 --- a/library/std/src/sys/sgx/rwlock.rs +++ b/library/std/src/sys/sgx/rwlock.rs @@ -13,6 +13,8 @@ pub struct RWLock { writer: SpinMutex>, } +pub type MovableRWLock = Box; + // Check at compile time that RWLock size matches C definition (see test_c_rwlock_initializer below) // // # Safety diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index bbc4691d963c6..41ca9762390c6 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -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) } } diff --git a/library/std/src/sys/unix/rwlock.rs b/library/std/src/sys/unix/rwlock.rs index d97d9d712fc93..b1faf12c22614 100644 --- a/library/std/src/sys/unix/rwlock.rs +++ b/library/std/src/sys/unix/rwlock.rs @@ -7,6 +7,8 @@ pub struct RWLock { num_readers: AtomicUsize, } +pub type MovableRWLock = Box; + 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() } - } -} diff --git a/library/std/src/sys/unsupported/rwlock.rs b/library/std/src/sys/unsupported/rwlock.rs index 6982b2b155fa5..8438adeb5b533 100644 --- a/library/std/src/sys/unsupported/rwlock.rs +++ b/library/std/src/sys/unsupported/rwlock.rs @@ -5,6 +5,8 @@ pub struct RWLock { mode: Cell, } +pub type MovableRWLock = RWLock; + unsafe impl Send for RWLock {} unsafe impl Sync for RWLock {} // no threads on this platform diff --git a/library/std/src/sys/wasm/atomics/rwlock.rs b/library/std/src/sys/wasm/atomics/rwlock.rs index 06442e925f4c8..64eaa2fc482dc 100644 --- a/library/std/src/sys/wasm/atomics/rwlock.rs +++ b/library/std/src/sys/wasm/atomics/rwlock.rs @@ -8,6 +8,8 @@ pub struct RWLock { state: UnsafeCell, } +pub type MovableRWLock = RWLock; + enum State { Unlocked, Reading(usize), diff --git a/library/std/src/sys/windows/rwlock.rs b/library/std/src/sys/windows/rwlock.rs index a769326352c40..b7a5b1e7accd0 100644 --- a/library/std/src/sys/windows/rwlock.rs +++ b/library/std/src/sys/windows/rwlock.rs @@ -5,6 +5,8 @@ pub struct RWLock { inner: UnsafeCell, } +pub type MovableRWLock = RWLock; + unsafe impl Send for RWLock {} unsafe impl Sync for RWLock {} diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs index 3705d641a1be6..07ec20f4dc617 100644 --- a/library/std/src/sys_common/rwlock.rs +++ b/library/std/src/sys_common/rwlock.rs @@ -1,63 +1,112 @@ use crate::sys::rwlock as imp; +/// An OS-based reader-writer lock, meant for use in static variables. +/// +/// 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 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. + /// + /// The lock is automatically unlocked when the returned guard is dropped. + #[inline] + 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 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* 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` 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 RWLock { +impl MovableRWLock { /// 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()) + 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. - /// - /// Behavior is undefined if the rwlock has been moved between this and any - /// previous method call. #[inline] - pub unsafe fn read(&self) { - self.0.read() + 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() }; } } diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index cba17c8e6085b..e4396d53016ea 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -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. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 06f8bf89daecd..bc499fdba5996 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -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)); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 21c7dd11d248b..347236c655a02 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -923,6 +923,21 @@ impl Build { self.config.use_lld && !target.contains("msvc") } + fn lld_flags(&self, target: TargetSelection) -> impl Iterator { + 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 { if target.contains("pc-windows-msvc") { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index cc7c143d47461..70cf1b105c062 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1131,19 +1131,6 @@ struct Compiletest { compare_mode: Option<&'static str>, } -impl Compiletest { - fn add_lld_flags(builder: &Builder<'_>, target: TargetSelection, flags: &mut Vec) { - 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()); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 931c822ffe265..1e7c3930246b3 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -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 { diff --git a/src/tools/miri b/src/tools/miri index c8713c2f9fc1e..e5c3af6f51631 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit c8713c2f9fc1e28c90876b9ec9557d8c5729757b +Subproject commit e5c3af6f516311cc4b1fc017c58d83b7442cbc34