From c4b02659c16d2ad0ac36d2c8602edd002e559f7a Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Thu, 11 Jun 2020 17:44:21 -0700 Subject: [PATCH 01/50] Enable some timeouts in SGX platform This would partially resolve https://github.com/fortanix/rust-sgx/issues/31 --- src/libstd/sync/condvar.rs | 4 - src/libstd/sync/mpsc/mod.rs | 9 -- src/libstd/sys/sgx/abi/usercalls/mod.rs | 24 ++++- src/libstd/sys/sgx/condvar.rs | 6 +- src/libstd/sys/sgx/mod.rs | 45 +++++++++- src/libstd/sys/sgx/thread.rs | 6 +- src/libstd/sys/sgx/waitqueue.rs | 113 ++++++++++++++++++++++-- src/libstd/thread/mod.rs | 3 - 8 files changed, 179 insertions(+), 31 deletions(-) diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 77e521eae9afe..6778ab9dcde4a 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -695,7 +695,6 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_wait() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); @@ -715,7 +714,6 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_while_wait() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); @@ -740,7 +738,6 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_while_wake() { let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair_copy = pair.clone(); @@ -764,7 +761,6 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_wake() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index e70204d6839fc..db765bde5438e 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -2088,7 +2088,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn oneshot_single_thread_recv_timeout() { let (tx, rx) = channel(); tx.send(()).unwrap(); @@ -2099,7 +2098,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_two_threads() { let (tx, rx) = channel(); let stress = stress_factor() + 100; @@ -2130,7 +2128,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn recv_timeout_upgrade() { let (tx, rx) = channel::<()>(); let timeout = Duration::from_millis(1); @@ -2142,7 +2139,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_shared() { let (tx, rx) = channel(); let stress = stress_factor() + 100; @@ -2173,7 +2169,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn very_long_recv_timeout_wont_panic() { let (tx, rx) = channel::<()>(); let join_handle = @@ -2196,7 +2191,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn shared_recv_timeout() { let (tx, rx) = channel(); let total = 5; @@ -2426,7 +2420,6 @@ mod sync_tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn recv_timeout() { let (tx, rx) = sync_channel::(1); assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout)); @@ -2518,7 +2511,6 @@ mod sync_tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_two_threads() { let (tx, rx) = sync_channel::(0); @@ -2544,7 +2536,6 @@ mod sync_tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_shared() { const AMT: u32 = 1000; const NTHREADS: u32 = 8; diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index ae803ee47a6cb..b223da9d7e4a2 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -1,5 +1,6 @@ use crate::cmp; use crate::io::{Error as IoError, IoSlice, IoSliceMut, Result as IoResult}; +use crate::sys::rand::rdrand64; use crate::time::Duration; pub(crate) mod alloc; @@ -149,7 +150,28 @@ pub fn exit(panic: bool) -> ! { /// Usercall `wait`. See the ABI documentation for more information. #[unstable(feature = "sgx_platform", issue = "56975")] -pub fn wait(event_mask: u64, timeout: u64) -> IoResult { +pub fn wait(event_mask: u64, mut timeout: u64) -> IoResult { + if timeout != WAIT_NO && timeout != WAIT_INDEFINITE { + // We don't want people to rely on accuracy of timeouts to make + // security decisions in an SGX enclave. That's why we add a random + // amount not exceeding +/- 10% to the timeout value to discourage + // people from relying on accuracy of timeouts while providing a way + // to make things work in other cases. Note that in the SGX threat + // model the enclave runner which is serving the wait usercall is not + // trusted to ensure accurate timeouts. + let base = cmp::max(1, timeout / 10) * 2 + 1; + let zero = base / 2; + match rdrand64() % base { + jitter if jitter > zero => { + timeout = timeout.checked_add(jitter - zero).unwrap_or(timeout) + } + jitter if jitter < zero => { + timeout = timeout.checked_sub(zero - jitter).unwrap_or(timeout) + } + _ => {} + }; + timeout = cmp::min(u64::MAX - 1, cmp::max(1, timeout)); + } unsafe { raw::wait(event_mask, timeout).from_sgx_result() } } diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs index 9c5c086184d68..ed6dbcf497147 100644 --- a/src/libstd/sys/sgx/condvar.rs +++ b/src/libstd/sys/sgx/condvar.rs @@ -31,8 +31,10 @@ impl Condvar { mutex.lock() } - pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { - rtabort!("timeout not supported in SGX"); + pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + let success = WaitQueue::wait_timeout(&self.inner, dur, || mutex.unlock()); + mutex.lock(); + success } #[inline] diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index 397dd496ae8af..dff9d3b1f07ea 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -110,6 +110,42 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { } } +// This function makes an effort to sleep at least as long as `duration`. +// Note that in general there is no guarantee about accuracy of time and +// timeouts in SGX model. The enclave runner serving usercalls may lie about +// current time and/or ignore timeout values. +// +// FIXME: note these caveats in documentation of all public types that use this +// function in their execution path. +pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration) { + use self::abi::usercalls; + use crate::cmp; + use crate::io::ErrorKind; + use crate::time::Instant; + + let start = Instant::now(); + let mut remaining = duration; + loop { + let timeout = cmp::min((u64::MAX - 1) as u128, remaining.as_nanos()) as u64; + match usercalls::wait(event_mask, timeout) { + Ok(eventset) => { + if event_mask != 0 { + rtassert!(eventset & event_mask == event_mask); + return; + } + rtabort!("expected usercalls::wait() to return Err, found Ok."); + } + Err(e) => { + rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock) + } + } + remaining = match duration.checked_sub(start.elapsed()) { + Some(remaining) => remaining, + None => break, + } + } +} + // This enum is used as the storage for a bunch of types which can't actually // exist. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] @@ -137,8 +173,8 @@ pub extern "C" fn __rust_abort() { abort_internal(); } -pub fn hashmap_random_keys() -> (u64, u64) { - fn rdrand64() -> u64 { +pub mod rand { + pub fn rdrand64() -> u64 { unsafe { let mut ret: u64 = 0; for _ in 0..10 { @@ -149,7 +185,10 @@ pub fn hashmap_random_keys() -> (u64, u64) { rtabort!("Failed to obtain random data"); } } - (rdrand64(), rdrand64()) +} + +pub fn hashmap_random_keys() -> (u64, u64) { + (self::rand::rdrand64(), self::rand::rdrand64()) } pub use crate::sys_common::{AsInner, FromInner, IntoInner}; diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index 9b515eb82de35..8ff0f1fde91c2 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -1,6 +1,8 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? + use crate::ffi::CStr; use crate::io; +use crate::sys::wait_timeout_sgx; use crate::time::Duration; use super::abi::usercalls; @@ -73,8 +75,8 @@ impl Thread { // FIXME: could store this pointer in TLS somewhere } - pub fn sleep(_dur: Duration) { - rtabort!("can't sleep"); // FIXME + pub fn sleep(dur: Duration) { + wait_timeout_sgx(0, dur); } pub fn join(self) { diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index 6e50f161b3b41..71d1c22cd6191 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -1,4 +1,3 @@ -use crate::num::NonZeroUsize; /// A simple queue implementation for synchronization primitives. /// /// This queue is used to implement condition variable and mutexes. @@ -10,7 +9,10 @@ use crate::num::NonZeroUsize; /// Since userspace may send spurious wake-ups, the wakeup event state is /// recorded in the enclave. The wakeup event state is protected by a spinlock. /// The queue and associated wait state are stored in a `WaitVariable`. +use crate::num::NonZeroUsize; use crate::ops::{Deref, DerefMut}; +use crate::sys::wait_timeout_sgx; +use crate::time::Duration; use super::abi::thread; use super::abi::usercalls; @@ -158,6 +160,37 @@ impl WaitQueue { } } + /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait + /// until a wakeup event or timeout. If event was observed, returns true. + /// If not, it will remove the calling thread from the wait queue. + pub fn wait_timeout( + lock: &SpinMutex>, + timeout: Duration, + before_wait: F, + ) -> bool { + // very unsafe: check requirements of UnsafeList::push + unsafe { + let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry { + tcs: thread::current(), + wake: false, + })); + let entry_lock = lock.lock().queue.inner.push(&mut entry); + before_wait(); + // don't panic, this would invalidate `entry` during unwinding + wait_timeout_sgx(EV_UNPARK, timeout); + // acquire the wait queue's lock first to avoid deadlock. + let mut guard = lock.lock(); + let entry_guard = entry_lock.lock(); + let success = entry_guard.wake; + if !success { + // nobody is waking us up, so remove the entry from the wait queue. + drop(entry_guard); + guard.queue.inner.remove(&mut entry); + } + success + } + } + /// Either find the next waiter on the wait queue, or return the mutex /// guard unchanged. /// @@ -325,6 +358,31 @@ mod unsafe_list { Some((*first.as_ptr()).value.as_ref().unwrap()) } } + + /// Removes an entry from the list. + /// + /// # Safety + /// + /// The caller must ensure that entry has been pushed prior to this + /// call and has not moved since push. + pub unsafe fn remove(&mut self, entry: &mut UnsafeListEntry) { + rtassert!(!self.is_empty()); + // BEFORE: + // /----\ next ---> /-----\ next ---> /----\ + // ... |prev| |entry| |next| ... + // \----/ <--- prev \-----/ <--- prev \----/ + // + // AFTER: + // /----\ next ---> /----\ + // ... |prev| |next| ... + // \----/ <--- prev \----/ + let mut prev = entry.prev; + let mut next = entry.next; + prev.as_mut().next = next; + next.as_mut().prev = prev; + entry.next = NonNull::dangling(); + entry.prev = NonNull::dangling(); + } } #[cfg(test)] @@ -354,6 +412,51 @@ mod unsafe_list { } } + #[test] + fn push_remove() { + unsafe { + let mut node = UnsafeListEntry::new(1234); + let mut list = UnsafeList::new(); + assert_eq!(list.push(&mut node), &1234); + list.remove(&mut node); + assert_empty(&mut list); + } + } + + #[test] + fn push_remove_pop() { + unsafe { + let mut node1 = UnsafeListEntry::new(11); + let mut node2 = UnsafeListEntry::new(12); + let mut node3 = UnsafeListEntry::new(13); + let mut node4 = UnsafeListEntry::new(14); + let mut node5 = UnsafeListEntry::new(15); + let mut list = UnsafeList::new(); + assert_eq!(list.push(&mut node1), &11); + assert_eq!(list.push(&mut node2), &12); + assert_eq!(list.push(&mut node3), &13); + assert_eq!(list.push(&mut node4), &14); + assert_eq!(list.push(&mut node5), &15); + + list.remove(&mut node1); + assert_eq!(list.pop().unwrap(), &12); + list.remove(&mut node3); + assert_eq!(list.pop().unwrap(), &14); + list.remove(&mut node5); + assert_empty(&mut list); + + assert_eq!(list.push(&mut node1), &11); + assert_eq!(list.pop().unwrap(), &11); + assert_empty(&mut list); + + assert_eq!(list.push(&mut node3), &13); + assert_eq!(list.push(&mut node4), &14); + list.remove(&mut node3); + list.remove(&mut node4); + assert_empty(&mut list); + } + } + #[test] fn complex_pushes_pops() { unsafe { @@ -474,7 +577,7 @@ mod spin_mutex { use super::*; use crate::sync::Arc; use crate::thread; - use crate::time::{Duration, SystemTime}; + use crate::time::Duration; #[test] fn sleep() { @@ -485,11 +588,7 @@ mod spin_mutex { *mutex2.lock() = 1; }); - // "sleep" for 50ms - // FIXME: https://github.com/fortanix/rust-sgx/issues/31 - let start = SystemTime::now(); - let max = Duration::from_millis(50); - while start.elapsed().unwrap() < max {} + thread::sleep(Duration::from_millis(50)); assert_eq!(*guard, 0); drop(guard); diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 3134a5967566b..9bcb89d81443d 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1743,7 +1743,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn test_park_timeout_unpark_not_called() { for _ in 0..10 { thread::park_timeout(Duration::from_millis(10)); @@ -1751,7 +1750,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn test_park_timeout_unpark_called_other_thread() { for _ in 0..10 { let th = thread::current(); @@ -1766,7 +1764,6 @@ mod tests { } #[test] - #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn sleep_ms_smoke() { thread::sleep(Duration::from_millis(2)); } From d7dc64bdfea4fbf8974774800ab51e04eaa4f082 Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Fri, 12 Jun 2020 12:06:41 -0700 Subject: [PATCH 02/50] Handle spurious wakeups in wait_timeout_sgx --- src/libstd/sys/sgx/mod.rs | 16 ++++++++++++---- src/libstd/sys/sgx/thread.rs | 2 +- src/libstd/sys/sgx/waitqueue.rs | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index dff9d3b1f07ea..b72e4fb06f35b 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -115,9 +115,15 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { // timeouts in SGX model. The enclave runner serving usercalls may lie about // current time and/or ignore timeout values. // +// Once the event is observed, `stop` will be used to determine whether or not +// we should continue to wait. +// // FIXME: note these caveats in documentation of all public types that use this // function in their execution path. -pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration) { +pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration, stop: F) +where + F: Fn() -> bool, +{ use self::abi::usercalls; use crate::cmp; use crate::io::ErrorKind; @@ -129,11 +135,13 @@ pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration) { let timeout = cmp::min((u64::MAX - 1) as u128, remaining.as_nanos()) as u64; match usercalls::wait(event_mask, timeout) { Ok(eventset) => { - if event_mask != 0 { - rtassert!(eventset & event_mask == event_mask); + if event_mask == 0 { + rtabort!("expected usercalls::wait() to return Err, found Ok."); + } + rtassert!(eventset & event_mask == event_mask); + if stop() { return; } - rtabort!("expected usercalls::wait() to return Err, found Ok."); } Err(e) => { rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock) diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index 8ff0f1fde91c2..5636a6f7eabde 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -76,7 +76,7 @@ impl Thread { } pub fn sleep(dur: Duration) { - wait_timeout_sgx(0, dur); + wait_timeout_sgx(0, dur, || true); } pub fn join(self) { diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index 71d1c22cd6191..36b3f5bcc41d8 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -177,7 +177,7 @@ impl WaitQueue { let entry_lock = lock.lock().queue.inner.push(&mut entry); before_wait(); // don't panic, this would invalidate `entry` during unwinding - wait_timeout_sgx(EV_UNPARK, timeout); + wait_timeout_sgx(EV_UNPARK, timeout, || entry_lock.lock().wake); // acquire the wait queue's lock first to avoid deadlock. let mut guard = lock.lock(); let entry_guard = entry_lock.lock(); From c5d1fcd2309b6903fed82aba6e0fdc2fa85bc874 Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Fri, 12 Jun 2020 13:41:46 -0700 Subject: [PATCH 03/50] Allow more ui tests for SGX --- src/test/ui/issues/issue-59020.rs | 1 - src/test/ui/issues/issue-9396.rs | 1 - src/test/ui/mpsc_stress.rs | 2 +- src/test/ui/sleep.rs | 1 - src/test/ui/tcp-stress.rs | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/ui/issues/issue-59020.rs b/src/test/ui/issues/issue-59020.rs index e7544934da0c8..a2b11764a2fc6 100644 --- a/src/test/ui/issues/issue-59020.rs +++ b/src/test/ui/issues/issue-59020.rs @@ -1,7 +1,6 @@ // edition:2018 // run-pass // ignore-emscripten no threads support -// ignore-sgx no thread sleep support use std::thread; use std::time::Duration; diff --git a/src/test/ui/issues/issue-9396.rs b/src/test/ui/issues/issue-9396.rs index 27b5185377d97..3e7e9a51cdd3a 100644 --- a/src/test/ui/issues/issue-9396.rs +++ b/src/test/ui/issues/issue-9396.rs @@ -2,7 +2,6 @@ #![allow(unused_must_use)] #![allow(deprecated)] // ignore-emscripten no threads support -// ignore-sgx no thread sleep support use std::sync::mpsc::{TryRecvError, channel}; use std::thread; diff --git a/src/test/ui/mpsc_stress.rs b/src/test/ui/mpsc_stress.rs index bce5fdcd119f7..81c000839bd4d 100644 --- a/src/test/ui/mpsc_stress.rs +++ b/src/test/ui/mpsc_stress.rs @@ -1,7 +1,6 @@ // run-pass // compile-flags:--test // ignore-emscripten -// ignore-sgx no thread sleep support use std::sync::mpsc::channel; use std::sync::mpsc::TryRecvError; @@ -37,6 +36,7 @@ impl Barrier { fn wait(self) { self.shared.fetch_add(1, Ordering::SeqCst); while self.shared.load(Ordering::SeqCst) != self.count { + thread::yield_now(); } } } diff --git a/src/test/ui/sleep.rs b/src/test/ui/sleep.rs index 757578b84750c..3b3a4a4f3250c 100644 --- a/src/test/ui/sleep.rs +++ b/src/test/ui/sleep.rs @@ -1,6 +1,5 @@ // run-pass // ignore-emscripten no threads support -// ignore-sgx no thread sleep support use std::thread::{self, sleep}; use std::time::Duration; diff --git a/src/test/ui/tcp-stress.rs b/src/test/ui/tcp-stress.rs index 1f1948fa8fa2c..08b47dc531857 100644 --- a/src/test/ui/tcp-stress.rs +++ b/src/test/ui/tcp-stress.rs @@ -4,7 +4,6 @@ // ignore-emscripten no threads or sockets support // ignore-netbsd system ulimit (Too many open files) // ignore-openbsd system ulimit (Too many open files) -// ignore-sgx no thread sleep support use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; From 3442d23c1a12f1f01a0e07b6bec72b58998f49ef Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Thu, 18 Jun 2020 12:50:10 -0700 Subject: [PATCH 04/50] Improve wait_timeout_sgx, simplify usercalls::wait --- src/libstd/sys/sgx/abi/usercalls/mod.rs | 17 +++---- src/libstd/sys/sgx/mod.rs | 67 ++++++++++++++++++------- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index b223da9d7e4a2..69ff7ebf9a19d 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -1,4 +1,5 @@ use crate::cmp; +use crate::convert::TryFrom; use crate::io::{Error as IoError, IoSlice, IoSliceMut, Result as IoResult}; use crate::sys::rand::rdrand64; use crate::time::Duration; @@ -159,17 +160,11 @@ pub fn wait(event_mask: u64, mut timeout: u64) -> IoResult { // to make things work in other cases. Note that in the SGX threat // model the enclave runner which is serving the wait usercall is not // trusted to ensure accurate timeouts. - let base = cmp::max(1, timeout / 10) * 2 + 1; - let zero = base / 2; - match rdrand64() % base { - jitter if jitter > zero => { - timeout = timeout.checked_add(jitter - zero).unwrap_or(timeout) - } - jitter if jitter < zero => { - timeout = timeout.checked_sub(zero - jitter).unwrap_or(timeout) - } - _ => {} - }; + if let Ok(timeout_signed) = i64::try_from(timeout) { + let tenth = 1 + timeout_signed / 10; + let deviation = (rdrand64() as i64).checked_rem(tenth).unwrap_or(0); + timeout = timeout_signed.saturating_add(deviation) as _; + } timeout = cmp::min(u64::MAX - 1, cmp::max(1, timeout)); } unsafe { raw::wait(event_mask, timeout).from_sgx_result() } diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index b72e4fb06f35b..1c957d8ff8032 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -110,43 +110,76 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { } } -// This function makes an effort to sleep at least as long as `duration`. -// Note that in general there is no guarantee about accuracy of time and -// timeouts in SGX model. The enclave runner serving usercalls may lie about -// current time and/or ignore timeout values. +// This function makes an effort to wait for a non-spurious event at least as +// long as `duration`. Note that in general there is no guarantee about accuracy +// of time and timeouts in SGX model. The enclave runner serving usercalls may +// lie about current time and/or ignore timeout values. // -// Once the event is observed, `stop` will be used to determine whether or not -// we should continue to wait. +// Once the event is observed, `woken_up` will be used to determine whether or +// not the event was spurious. // // FIXME: note these caveats in documentation of all public types that use this // function in their execution path. -pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration, stop: F) +pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration, woken_up: F) where F: Fn() -> bool, { use self::abi::usercalls; use crate::cmp; use crate::io::ErrorKind; - use crate::time::Instant; - - let start = Instant::now(); - let mut remaining = duration; - loop { - let timeout = cmp::min((u64::MAX - 1) as u128, remaining.as_nanos()) as u64; + use crate::time::{Duration, Instant}; + + // Calls the wait usercall and checks the result. Returns true if event was + // returned, and false if WouldBlock/TimedOut was returned. + // If duration is None, it will use WAIT_NO. + fn wait_checked(event_mask: u64, duration: Option) -> bool { + let timeout = duration.map_or(usercalls::raw::WAIT_NO, |duration| { + cmp::min((u64::MAX - 1) as u128, duration.as_nanos()) as u64 + }); match usercalls::wait(event_mask, timeout) { Ok(eventset) => { if event_mask == 0 { rtabort!("expected usercalls::wait() to return Err, found Ok."); } rtassert!(eventset & event_mask == event_mask); - if stop() { - return; - } + true } Err(e) => { - rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock) + rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock); + false } } + } + + match wait_checked(event_mask, Some(duration)) { + false => return, // timed out + true if woken_up() => return, // woken up + true => {} // spurious event + } + + // Drain all cached events. + // Note that `event_mask != 0` is implied if we get here. + loop { + match wait_checked(event_mask, None) { + false => break, // no more cached events + true if woken_up() => return, // woken up + true => {} // spurious event + } + } + + // Continue waiting, but take note of time spent waiting so we don't wait + // forever. We intentionally don't call `Instant::now()` before this point + // to avoid the cost of the `insecure_time` usercall in case there are no + // spurious wakeups. + + let start = Instant::now(); + let mut remaining = duration; + loop { + match wait_checked(event_mask, Some(remaining)) { + false => return, // timed out + true if woken_up() => return, // woken up + true => {} // spurious event + } remaining = match duration.checked_sub(start.elapsed()) { Some(remaining) => remaining, None => break, From c457b67af394c37826f75d73cca10319ee96b910 Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 1 Jul 2020 12:45:11 -0700 Subject: [PATCH 05/50] Remove unnecessary check in SGX wait usercall --- src/libstd/sys/sgx/abi/usercalls/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index 69ff7ebf9a19d..6ee147d1704ad 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -161,11 +161,10 @@ pub fn wait(event_mask: u64, mut timeout: u64) -> IoResult { // model the enclave runner which is serving the wait usercall is not // trusted to ensure accurate timeouts. if let Ok(timeout_signed) = i64::try_from(timeout) { - let tenth = 1 + timeout_signed / 10; + let tenth = timeout_signed / 10; let deviation = (rdrand64() as i64).checked_rem(tenth).unwrap_or(0); timeout = timeout_signed.saturating_add(deviation) as _; } - timeout = cmp::min(u64::MAX - 1, cmp::max(1, timeout)); } unsafe { raw::wait(event_mask, timeout).from_sgx_result() } } From a18848beb7526ea260bc0a500a76b02529ef980d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Sat, 13 Jun 2020 14:18:02 +0200 Subject: [PATCH 06/50] Create implib for dlls when testing MinGW targets --- src/test/run-make-fulldeps/tools.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index 04bf78ed2105b..1effa46e101eb 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -150,7 +150,7 @@ ifdef IS_MSVC $(CC) $< -link -dll -out:`cygpath -w $@` else %.dll: lib%.o - $(CC) -o $@ $< -shared + $(CC) -o $@ $< -shared -Wl,--out-implib=$@.a endif $(TMPDIR)/lib%.o: %.c From 177a49501f750fa06a412becadf6d4748f985aaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 3 Jul 2020 20:18:51 +0200 Subject: [PATCH 07/50] Allow matching test by target and env --- src/tools/compiletest/src/header.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 571e7a59113ad..d6e28e93c9667 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -867,6 +867,7 @@ impl Config { &self.target == name || // triple util::matches_os(&self.target, name) || // target util::matches_env(&self.target, name) || // env + self.target.ends_with(name) || // target and env name == util::get_arch(&self.target) || // architecture name == util::get_pointer_width(&self.target) || // pointer width name == self.stage_id.split('-').next().unwrap() || // stage From 3324bc5affc9a9cf25253b38bf186073c09cf83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 3 Jul 2020 20:40:00 +0200 Subject: [PATCH 08/50] Remove invalid test When ran on Windows `cp` will follow symlink: `checkout/build///lib/rustlib/src/rust`. It points to `checkout` which means the test will get stuck in copying loop until there is no space left. --- src/test/run-make-fulldeps/libs-search-path/Makefile | 10 ---------- src/test/run-make-fulldeps/libs-search-path/empty.rs | 1 - 2 files changed, 11 deletions(-) delete mode 100644 src/test/run-make-fulldeps/libs-search-path/Makefile delete mode 100644 src/test/run-make-fulldeps/libs-search-path/empty.rs diff --git a/src/test/run-make-fulldeps/libs-search-path/Makefile b/src/test/run-make-fulldeps/libs-search-path/Makefile deleted file mode 100644 index f31036ffa1959..0000000000000 --- a/src/test/run-make-fulldeps/libs-search-path/Makefile +++ /dev/null @@ -1,10 +0,0 @@ --include ../tools.mk - -# only-mingw - -all: empty.rs - cp -r $(shell cygpath -u $(shell $(RUSTC) --print sysroot)) $(TMPDIR)/sysroot - $(RUSTC) --target $(TARGET) --sysroot $(TMPDIR)/sysroot -L$(TMPDIR)/obj -Z print-link-args empty.rs | $(CGREP) 'lib\\crt2.o' - mkdir -p $(TMPDIR)/obj - mv $(TMPDIR)/sysroot/lib/rustlib/$(TARGET)/lib/crt2.o $(TMPDIR)/obj/crt2.o - $(RUSTC) --target $(TARGET) --sysroot $(TMPDIR)/sysroot -L$(TMPDIR)/obj -Z print-link-args empty.rs | $(CGREP) 'obj\\crt2.o' diff --git a/src/test/run-make-fulldeps/libs-search-path/empty.rs b/src/test/run-make-fulldeps/libs-search-path/empty.rs deleted file mode 100644 index f328e4d9d04c3..0000000000000 --- a/src/test/run-make-fulldeps/libs-search-path/empty.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} From 17bc07dc543ecef65d8488543fd14fb68a4f68ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 3 Jul 2020 20:55:13 +0200 Subject: [PATCH 09/50] Fix various tests to run on windows-gnu --- .../compiler-rt-works-on-mingw/Makefile | 2 +- .../include_bytes_deps/Makefile | 4 -- .../intrinsic-unreachable/Makefile | 2 +- .../run-make-fulldeps/issue-51671/Makefile | 2 +- .../run-make-fulldeps/redundant-libs/Makefile | 6 +- .../symbol-visibility/Makefile | 63 ++++++++++--------- src/test/run-make-fulldeps/used/Makefile | 2 +- 7 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile index d7d078e56b2e7..0cf5d1855212d 100644 --- a/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile +++ b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk -# only-mingw +# only-windows-gnu all: $(CXX) foo.cpp -c -o $(TMPDIR)/foo.o diff --git a/src/test/run-make-fulldeps/include_bytes_deps/Makefile b/src/test/run-make-fulldeps/include_bytes_deps/Makefile index ce79cec67dc37..f91af88efe1b7 100644 --- a/src/test/run-make-fulldeps/include_bytes_deps/Makefile +++ b/src/test/run-make-fulldeps/include_bytes_deps/Makefile @@ -1,10 +1,6 @@ -include ../tools.mk -# ignore-windows # ignore-freebsd -# FIXME: on windows `rustc --dep-info` produces Makefile dependency with -# windows native paths (e.g. `c:\path\to\libfoo.a`) -# but msys make seems to fail to recognize such paths, so test fails. all: $(RUSTC) --emit dep-info main.rs diff --git a/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile b/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile index 483091ad4ee8b..2037728568e24 100644 --- a/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile +++ b/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk -# ignore-windows +# ignore-windows-msvc # # Because of Windows exception handling, the code is not necessarily any shorter. # https://github.com/llvm-mirror/llvm/commit/64b2297786f7fd6f5fa24cdd4db0298fbf211466 diff --git a/src/test/run-make-fulldeps/issue-51671/Makefile b/src/test/run-make-fulldeps/issue-51671/Makefile index 3027ee578c79f..ba3d3b7100745 100644 --- a/src/test/run-make-fulldeps/issue-51671/Makefile +++ b/src/test/run-make-fulldeps/issue-51671/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk -# ignore-windows +# ignore-windows-msvc all: $(RUSTC) --emit=obj app.rs diff --git a/src/test/run-make-fulldeps/redundant-libs/Makefile b/src/test/run-make-fulldeps/redundant-libs/Makefile index 9486e07d21bf7..8468d102bec83 100644 --- a/src/test/run-make-fulldeps/redundant-libs/Makefile +++ b/src/test/run-make-fulldeps/redundant-libs/Makefile @@ -1,8 +1,6 @@ -include ../tools.mk -ifdef IS_WINDOWS -all: -else +# ignore-windows-msvc # rustc will remove one of the two redundant references to foo below. Depending # on which one gets removed, we'll get a linker error on SOME platforms (like @@ -23,5 +21,3 @@ RUSTC_FLAGS = \ all: $(call DYLIB,foo) $(call STATICLIB,bar) $(call STATICLIB,baz) $(RUSTC) $(RUSTC_FLAGS) main.rs $(call RUN,main) - -endif diff --git a/src/test/run-make-fulldeps/symbol-visibility/Makefile b/src/test/run-make-fulldeps/symbol-visibility/Makefile index 7901866015bf2..ed88a88a0bb8c 100644 --- a/src/test/run-make-fulldeps/symbol-visibility/Makefile +++ b/src/test/run-make-fulldeps/symbol-visibility/Makefile @@ -1,9 +1,6 @@ include ../tools.mk -# ignore-windows -# -# On MINGW the --version-script, --dynamic-list, and --retain-symbol args don't -# seem to work reliably. +# ignore-windows-msvc NM=nm -D CDYLIB_NAME=liba_cdylib.so @@ -19,6 +16,14 @@ EXE_NAME=an_executable COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib endif +ifdef IS_WINDOWS +NM=nm -g +CDYLIB_NAME=liba_cdylib.dll.a +RDYLIB_NAME=liba_rust_dylib.dll.a +EXE_NAME=an_executable.exe +COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dll.a +endif + # `grep` regex for symbols produced by either `legacy` or `v0` mangling RE_ANY_RUST_SYMBOL="_ZN.*h.*E\|_R[a-zA-Z0-9_]+" @@ -30,38 +35,38 @@ all: $(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib # Check that a cdylib exports its public #[no_mangle] functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c public_c_function_from_cdylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_cdylib)" -eq "1" ] # Check that a cdylib exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_rlib)" -eq "1" ] # Check that a cdylib DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v _imp__ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] # Check that a Rust dylib exports its monomorphic functions - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] # Check that a Rust dylib does not export generics if -Zshare-generics=no - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_generic_function_from_rust_dylib)" -eq "0" ] # Check that a Rust dylib exports the monomorphic functions from its dependencies - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_rust_function_from_rlib)" -eq "1" ] # Check that a Rust dylib does not export generics if -Zshare-generics=no - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_generic_function_from_rlib)" -eq "0" ] # Check that an executable does not export any dynamic symbols - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ] - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_rust_function_from_exe)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v _imp__ | grep -c public_c_function_from_rlib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v _imp__ | grep -c public_rust_function_from_exe)" -eq "0" ] # Check the combined case, where we generate a cdylib and an rlib in the same # compilation session: # Check that a cdylib exports its public #[no_mangle] functions - [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -c public_c_function_from_cdylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_cdylib)" -eq "1" ] # Check that a cdylib exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_rlib)" -eq "1" ] # Check that a cdylib DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v _imp__ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] $(RUSTC) -Zshare-generics=yes an_rlib.rs @@ -70,22 +75,22 @@ all: $(RUSTC) -Zshare-generics=yes an_executable.rs # Check that a cdylib exports its public #[no_mangle] functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c public_c_function_from_cdylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_cdylib)" -eq "1" ] # Check that a cdylib exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_rlib)" -eq "1" ] # Check that a cdylib DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v _imp__ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] # Check that a Rust dylib exports its monomorphic functions, including generics this time - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_generic_function_from_rust_dylib)" -eq "1" ] # Check that a Rust dylib exports the monomorphic functions from its dependencies - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_c_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_rust_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v _imp__ | grep -c public_generic_function_from_rlib)" -eq "1" ] # Check that an executable does not export any dynamic symbols - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ] - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_rust_function_from_exe)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v _imp__ | grep -c public_c_function_from_rlib)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v _imp__ | grep -c public_rust_function_from_exe)" -eq "0" ] diff --git a/src/test/run-make-fulldeps/used/Makefile b/src/test/run-make-fulldeps/used/Makefile index 8d913e3993502..4d904472931ec 100644 --- a/src/test/run-make-fulldeps/used/Makefile +++ b/src/test/run-make-fulldeps/used/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk -# ignore-windows +# ignore-windows-msvc all: $(RUSTC) -C opt-level=3 --emit=obj used.rs From 1466598e19321bc6b97aef8271a317e78211d54d Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Fri, 10 Jul 2020 19:57:31 -0700 Subject: [PATCH 10/50] Address review comments --- src/libstd/sys/sgx/mod.rs | 31 +++++++++++++-------------- src/libstd/sys/sgx/thread.rs | 5 ++--- src/libstd/sys/sgx/waitqueue.rs | 37 +++++++++++++++------------------ src/test/ui/mpsc_stress.rs | 1 + 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index 1c957d8ff8032..c412053112bc5 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -115,12 +115,9 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { // of time and timeouts in SGX model. The enclave runner serving usercalls may // lie about current time and/or ignore timeout values. // -// Once the event is observed, `woken_up` will be used to determine whether or -// not the event was spurious. -// -// FIXME: note these caveats in documentation of all public types that use this -// function in their execution path. -pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration, woken_up: F) +// Once the event is observed, `should_wake_up` will be used to determine +// whether or not the event was spurious. +pub fn usercall_wait_timeout(event_mask: u64, duration: crate::time::Duration, should_wake_up: F) where F: Fn() -> bool, { @@ -141,7 +138,9 @@ where if event_mask == 0 { rtabort!("expected usercalls::wait() to return Err, found Ok."); } - rtassert!(eventset & event_mask == event_mask); + // A matching event is one whose bits are equal to or a subset + // of `event_mask`. + rtassert!(eventset & !event_mask == 0); true } Err(e) => { @@ -152,18 +151,18 @@ where } match wait_checked(event_mask, Some(duration)) { - false => return, // timed out - true if woken_up() => return, // woken up - true => {} // spurious event + false => return, // timed out + true if should_wake_up() => return, // woken up + true => {} // spurious event } // Drain all cached events. // Note that `event_mask != 0` is implied if we get here. loop { match wait_checked(event_mask, None) { - false => break, // no more cached events - true if woken_up() => return, // woken up - true => {} // spurious event + false => break, // no more cached events + true if should_wake_up() => return, // woken up + true => {} // spurious event } } @@ -176,9 +175,9 @@ where let mut remaining = duration; loop { match wait_checked(event_mask, Some(remaining)) { - false => return, // timed out - true if woken_up() => return, // woken up - true => {} // spurious event + false => return, // timed out + true if should_wake_up() => return, // woken up + true => {} // spurious event } remaining = match duration.checked_sub(start.elapsed()) { Some(remaining) => remaining, diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index 5636a6f7eabde..58b6f4346bc14 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -1,8 +1,7 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? - use crate::ffi::CStr; use crate::io; -use crate::sys::wait_timeout_sgx; +use crate::sys::usercall_wait_timeout; use crate::time::Duration; use super::abi::usercalls; @@ -76,7 +75,7 @@ impl Thread { } pub fn sleep(dur: Duration) { - wait_timeout_sgx(0, dur, || true); + usercall_wait_timeout(0, dur, || true); } pub fn join(self) { diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index 36b3f5bcc41d8..c8ccab2247a9c 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -1,17 +1,17 @@ -/// A simple queue implementation for synchronization primitives. -/// -/// This queue is used to implement condition variable and mutexes. -/// -/// Users of this API are expected to use the `WaitVariable` type. Since -/// that type is not `Sync`, it needs to be protected by e.g., a `SpinMutex` to -/// allow shared access. -/// -/// Since userspace may send spurious wake-ups, the wakeup event state is -/// recorded in the enclave. The wakeup event state is protected by a spinlock. -/// The queue and associated wait state are stored in a `WaitVariable`. +//! A simple queue implementation for synchronization primitives. +//! +//! This queue is used to implement condition variable and mutexes. +//! +//! Users of this API are expected to use the `WaitVariable` type. Since +//! that type is not `Sync`, it needs to be protected by e.g., a `SpinMutex` to +//! allow shared access. +//! +//! Since userspace may send spurious wake-ups, the wakeup event state is +//! recorded in the enclave. The wakeup event state is protected by a spinlock. +//! The queue and associated wait state are stored in a `WaitVariable`. use crate::num::NonZeroUsize; use crate::ops::{Deref, DerefMut}; -use crate::sys::wait_timeout_sgx; +use crate::sys::usercall_wait_timeout; use crate::time::Duration; use super::abi::thread; @@ -176,15 +176,12 @@ impl WaitQueue { })); let entry_lock = lock.lock().queue.inner.push(&mut entry); before_wait(); - // don't panic, this would invalidate `entry` during unwinding - wait_timeout_sgx(EV_UNPARK, timeout, || entry_lock.lock().wake); + usercall_wait_timeout(EV_UNPARK, timeout, || entry_lock.lock().wake); // acquire the wait queue's lock first to avoid deadlock. let mut guard = lock.lock(); - let entry_guard = entry_lock.lock(); - let success = entry_guard.wake; + let success = entry_lock.lock().wake; if !success { - // nobody is waking us up, so remove the entry from the wait queue. - drop(entry_guard); + // nobody is waking us up, so remove our entry from the wait queue. guard.queue.inner.remove(&mut entry); } success @@ -363,8 +360,8 @@ mod unsafe_list { /// /// # Safety /// - /// The caller must ensure that entry has been pushed prior to this - /// call and has not moved since push. + /// The caller must ensure that `entry` has been pushed onto `self` + /// prior to this call and has not moved since then. pub unsafe fn remove(&mut self, entry: &mut UnsafeListEntry) { rtassert!(!self.is_empty()); // BEFORE: diff --git a/src/test/ui/mpsc_stress.rs b/src/test/ui/mpsc_stress.rs index 81c000839bd4d..a889542fec0be 100644 --- a/src/test/ui/mpsc_stress.rs +++ b/src/test/ui/mpsc_stress.rs @@ -36,6 +36,7 @@ impl Barrier { fn wait(self) { self.shared.fetch_add(1, Ordering::SeqCst); while self.shared.load(Ordering::SeqCst) != self.count { + #[cfg(target_env = "sgx")] thread::yield_now(); } } From f97063259ede6ca4249b3a805820b474a61ed4d6 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 15 Jul 2020 04:13:25 +0000 Subject: [PATCH 11/50] Don't render unstable for rustc docs As rustc is permanently unstable. So marking every items with unstable is essential useless. --- src/librustdoc/html/render.rs | 45 +++++++++++++---------------------- src/test/rustdoc/internal.rs | 10 ++++---- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8fa581180ef60..dc231d3520d08 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2229,12 +2229,15 @@ fn stability_tags(item: &clean::Item) -> String { tags += &tag_html("deprecated", message); } - if let Some(stab) = item.stability.as_ref().filter(|s| s.level == stability::Unstable) { - if stab.feature.as_deref() == Some("rustc_private") { - tags += &tag_html("internal", "Internal"); - } else { - tags += &tag_html("unstable", "Experimental"); - } + // The "rustc_private" crates are permanently unstable so it makes no sense + // to render "unstable" everywhere. + if item + .stability + .as_ref() + .map(|s| s.level == stability::Unstable && s.feature.as_deref() != Some("rustc_private")) + == Some(true) + { + tags += &tag_html("unstable", "Experimental"); } if let Some(ref cfg) = item.attrs.cfg { @@ -2285,15 +2288,13 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { )); } - if let Some(stab) = item.stability.as_ref().filter(|stab| stab.level == stability::Unstable) { - let is_rustc_private = stab.feature.as_deref() == Some("rustc_private"); - - let mut message = if is_rustc_private { - "⚙️ This is an internal compiler API." - } else { - "🔬 This is a nightly-only experimental API." - } - .to_owned(); + // Render unstable items. But don't render "rustc_private" crates (internal compiler crates). + // Those crates are permanently unstable so it makes no sense to render "unstable" everywhere. + if let Some(stab) = item.stability.as_ref().filter(|stab| { + stab.level == stability::Unstable && stab.feature.as_deref() != Some("rustc_private") + }) { + let mut message = + "🔬 This is a nightly-only experimental API.".to_owned(); if let Some(feature) = stab.feature.as_deref() { let mut feature = format!("{}", Escape(&feature)); @@ -2309,17 +2310,6 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { } if let Some(unstable_reason) = &stab.unstable_reason { - // Provide a more informative message than the compiler help. - let unstable_reason = if is_rustc_private { - "This crate is being loaded from the sysroot, a permanently unstable location \ - for private compiler dependencies. It is not intended for general use. Prefer \ - using a public version of this crate from \ - [crates.io](https://crates.io) via [`Cargo.toml`]\ - (https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html)." - } else { - unstable_reason - }; - let mut ids = cx.id_map.borrow_mut(); message = format!( "
{}{}
", @@ -2335,8 +2325,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { ); } - let class = if is_rustc_private { "internal" } else { "unstable" }; - stability.push(format!("
{}
", class, message)); + stability.push(format!("
{}
", message)); } if let Some(ref cfg) = item.attrs.cfg { diff --git a/src/test/rustdoc/internal.rs b/src/test/rustdoc/internal.rs index 2cb7c472cc84b..a1e322fb9a307 100644 --- a/src/test/rustdoc/internal.rs +++ b/src/test/rustdoc/internal.rs @@ -1,11 +1,13 @@ // compile-flags: -Z force-unstable-if-unmarked -// @matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab internal"]' \ -// 'Internal' +// Check that the unstable marker is not added for "rustc_private". + +// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab unstable"]' +// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab internal"]' // @matches - '//*[@class="docblock-short"]' 'Docs' -// @has internal/struct.S.html '//*[@class="stab internal"]' \ -// 'This is an internal compiler API. (rustc_private)' +// @!has internal/struct.S.html '//*[@class="stab unstable"]' +// @!has internal/struct.S.html '//*[@class="stab internal"]' /// Docs pub struct S; From 47fea961ba2cada1ca9a28f971cbe79ec525697e Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 15 Jul 2020 10:52:49 +0000 Subject: [PATCH 12/50] Remove unused CSS rules for internal rustc items --- src/librustdoc/html/static/themes/ayu.css | 6 ------ src/librustdoc/html/static/themes/dark.css | 5 ----- src/librustdoc/html/static/themes/light.css | 5 ----- 3 files changed, 16 deletions(-) diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index bc21c28750fd8..53a4897c672de 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -216,10 +216,6 @@ a { color: #39AFD7; } -.stab.internal a { - color: #304FFE; -} - .collapse-toggle { color: #999; } @@ -254,7 +250,6 @@ a { } .stab.unstable, -.stab.internal, .stab.deprecated, .stab.portability { color: #c5c5c5; @@ -457,7 +452,6 @@ pre.rust .doccomment {} .content .highlighted.type {} pre.rust .kw-2,pre.rust .prelude-ty {} .content span.trait,.content a.trait,.block a.current.trait {} -.stab.internal {} @media (max-width: 700px) { .sidebar-menu { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 41dcb5c24507c..d0ddff5c00a97 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -172,10 +172,6 @@ a { color: #D2991D; } -.stab.internal a { - color: #304FFE; -} - a.test-arrow { color: #dedede; } @@ -214,7 +210,6 @@ a.test-arrow { } .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; } -.stab.internal { background: #FFB9B3; border-color: #B71C1C; color: #2f2f2f; } .stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; } .stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 386fe2398e63a..d12823cdbcf03 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -173,10 +173,6 @@ a { color: #3873AD; } -.stab.internal a { - color: #304FFE; -} - a.test-arrow { color: #f5f5f5; } @@ -215,7 +211,6 @@ a.test-arrow { } .stab.unstable { background: #FFF5D6; border-color: #FFC600; } -.stab.internal { background: #FFB9B3; border-color: #B71C1C; } .stab.deprecated { background: #F3DFFF; border-color: #7F0087; } .stab.portability { background: #C4ECFF; border-color: #7BA5DB; } From 98ce1ce23ff8a57726ec3a56a92a5f27021ab4d0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jul 2020 14:09:37 +0200 Subject: [PATCH 13/50] Convert whitespaces to tabs --- src/librustdoc/html/static/themes/ayu.css | 88 +++++++++++------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index bc21c28750fd8..eabb53e331ecf 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -41,13 +41,13 @@ h3 > code, h4 > code, h5 > code { color: #e6e1cf; } pre > code { - color: #e6e1cf; + color: #e6e1cf; } span code { - color: #e6e1cf; + color: #e6e1cf; } .docblock a > code { - color: #39AFD7 !important; + color: #39AFD7 !important; } .docblock code, .docblock-short code { background-color: #191f26; @@ -100,11 +100,11 @@ pre { } .sidebar-elems .location { - color: #ff7733; + color: #ff7733; } .sidebar-elems .location a { - color: #fff; + color: #fff; } .sidebar .version { @@ -123,9 +123,9 @@ pre { .line-numbers span { color: #5c6773ab; } .line-numbers .line-highlighted { - background-color: rgba(255, 236, 164, 0.06) !important; - padding-right: 4px; - border-right: 1px solid #ffb44c; + background-color: rgba(255, 236, 164, 0.06) !important; + padding-right: 4px; + border-right: 1px solid #ffb44c; } .docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { @@ -168,28 +168,28 @@ pre { .content span.keyword, .content a.keyword { color: #de5249; } .content span.externcrate, .content span.mod, .content a.mod { - color: #acccf9; + color: #acccf9; } .content span.struct, .content a.struct { - color: #ffa0a5; + color: #ffa0a5; } .content span.enum, .content a.enum { - color: #99e0c9; + color: #99e0c9; } .content span.trait, .content a.trait { - color: #39AFD7; + color: #39AFD7; } .content span.type, .content a.type { - color: #cfbcf5; + color: #cfbcf5; } .content span.fn, .content a.fn, .content span.method, .content a.method, .content span.tymethod, .content a.tymethod, .content .fnname { - color: #fdd687; + color: #fdd687; } .content span.attr, .content a.attr, .content span.derive, .content a.derive, .content span.macro, .content a.macro { - color: #a37acc; + color: #a37acc; } pre.rust .comment, pre.rust .doccomment { @@ -233,16 +233,16 @@ a { } .search-input { - color: #ffffff; - background-color: #141920; - box-shadow: none; - transition: box-shadow 150ms ease-in-out; - border-radius: 4px; - margin-left: 8px; + color: #ffffff; + background-color: #141920; + box-shadow: none; + transition: box-shadow 150ms ease-in-out; + border-radius: 4px; + margin-left: 8px; } #crate-search+.search-input:focus { - box-shadow: 0px 6px 20px 0px black; + box-shadow: 0px 6px 20px 0px black; } .search-focus:disabled { @@ -257,7 +257,7 @@ a { .stab.internal, .stab.deprecated, .stab.portability { - color: #c5c5c5; + color: #c5c5c5; background: #314559 !important; border-style: none !important; border-radius: 4px; @@ -270,10 +270,10 @@ a { } #help > div { - background: #14191f; - box-shadow: 0px 6px 20px 0px black; - border: none; - border-radius: 4px; + background: #14191f; + box-shadow: 0px 6px 20px 0px black; + border: none; + border-radius: 4px; } .since { @@ -296,14 +296,14 @@ pre.rust .question-mark { color: #ff9011; } pre.rust .self { - color: #36a3d9; - font-style: italic; + color: #36a3d9; + font-style: italic; } pre.rust .attribute { - color: #e6e1cf; + color: #e6e1cf; } pre.rust .attribute .ident, pre.rust .attribute .op { - color: #e6e1cf; + color: #e6e1cf; } .example-wrap > pre.line-number { @@ -312,15 +312,15 @@ pre.rust .attribute .ident, pre.rust .attribute .op { } a.test-arrow { - font-size: 100%; - color: #788797; - border-radius: 4px; - background-color: rgba(255, 255, 255, 0); + font-size: 100%; + color: #788797; + border-radius: 4px; + background-color: rgba(255, 255, 255, 0); } a.test-arrow:hover { - background-color: rgba(242, 151, 24, 0.05); - color: #ffb44c; + background-color: rgba(242, 151, 24, 0.05); + color: #ffb44c; } .toggle-label { @@ -385,9 +385,9 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip .tooltiptext { - background-color: #314559; - color: #c5c5c5; - border: 1px solid #5c6773; + background-color: #314559; + color: #c5c5c5; + border: 1px solid #5c6773; } .tooltip .tooltiptext::after { @@ -395,7 +395,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } #titles > div.selected { - background-color: #141920 !important; + background-color: #141920 !important; border-bottom: 1px solid #ffb44c !important; border-top: none; } @@ -406,7 +406,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } #titles > div:hover { - border-bottom: 1px solid rgba(242, 151, 24, 0.3); + border-bottom: 1px solid rgba(242, 151, 24, 0.3); } #titles > div > div.count { @@ -487,11 +487,11 @@ kbd { #theme-picker, #settings-menu { border-color: #5c6773; - background-color: #0f1419; + background-color: #0f1419; } #theme-picker > img, #settings-menu > img { - filter: invert(100); + filter: invert(100); } #theme-picker:hover, #theme-picker:focus, From 8c6c1dd3d3690859c8c8ee2056e7627f41a5afda Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 21 May 2020 16:43:59 -0700 Subject: [PATCH 14/50] Automatically calculate std::env::consts::ARCH. This simplifies the definition for ARCH. Note that this changes asmjs-unknown-emscripten ARCH to `wasm32`, which reflects the actual target arch. --- src/libstd/build.rs | 1 + src/libstd/env.rs | 77 +-------------------------------------------- 2 files changed, 2 insertions(+), 76 deletions(-) diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 743a1778fbda3..f33af1ef7f668 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -63,4 +63,5 @@ fn main() { println!("cargo:rustc-link-lib=c"); println!("cargo:rustc-link-lib=compiler_rt"); } + println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); } diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 97c20ca9459ef..6489e0709cb91 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -882,7 +882,7 @@ pub mod consts { /// - s390x /// - sparc64 #[stable(feature = "env", since = "1.0.0")] - pub const ARCH: &str = super::arch::ARCH; + pub const ARCH: &str = env!("STD_ENV_ARCH"); /// The family of the operating system. Example value is `unix`. /// @@ -966,81 +966,6 @@ pub mod consts { pub const EXE_EXTENSION: &str = os::EXE_EXTENSION; } -#[cfg(target_arch = "x86")] -mod arch { - pub const ARCH: &str = "x86"; -} - -#[cfg(target_arch = "x86_64")] -mod arch { - pub const ARCH: &str = "x86_64"; -} - -#[cfg(target_arch = "arm")] -mod arch { - pub const ARCH: &str = "arm"; -} - -#[cfg(target_arch = "aarch64")] -mod arch { - pub const ARCH: &str = "aarch64"; -} - -#[cfg(target_arch = "mips")] -mod arch { - pub const ARCH: &str = "mips"; -} - -#[cfg(target_arch = "mips64")] -mod arch { - pub const ARCH: &str = "mips64"; -} - -#[cfg(target_arch = "powerpc")] -mod arch { - pub const ARCH: &str = "powerpc"; -} - -#[cfg(target_arch = "powerpc64")] -mod arch { - pub const ARCH: &str = "powerpc64"; -} - -#[cfg(target_arch = "s390x")] -mod arch { - pub const ARCH: &str = "s390x"; -} - -#[cfg(target_arch = "sparc64")] -mod arch { - pub const ARCH: &str = "sparc64"; -} - -#[cfg(target_arch = "le32")] -mod arch { - pub const ARCH: &str = "le32"; -} - -#[cfg(target_arch = "asmjs")] -mod arch { - pub const ARCH: &str = "asmjs"; -} - -#[cfg(target_arch = "wasm32")] -mod arch { - pub const ARCH: &str = "wasm32"; -} - -#[cfg(target_arch = "hexagon")] -mod arch { - pub const ARCH: &'static str = "hexagon"; -} - -#[cfg(target_arch = "riscv64")] -mod arch { - pub const ARCH: &'static str = "riscv64"; -} - #[cfg(test)] mod tests { use super::*; From 432b4c14aad49f27bad3c59bb3bc85595e21a71b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 21 May 2020 19:01:19 -0700 Subject: [PATCH 15/50] Use cfg_if in libtest. Simplifies some of the expressions, and provides a default. --- Cargo.lock | 1 + src/libtest/Cargo.toml | 1 + src/libtest/helpers/concurrency.rs | 171 ++++++++++++----------------- src/libtest/helpers/isatty.rs | 56 +++++----- 4 files changed, 98 insertions(+), 131 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5309c03ee23ae..386d5e960016a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4552,6 +4552,7 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ + "cfg-if", "core", "getopts", "libc", diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml index 170fbb984cf9b..7dddfd264ef8a 100644 --- a/src/libtest/Cargo.toml +++ b/src/libtest/Cargo.toml @@ -10,6 +10,7 @@ path = "lib.rs" crate-type = ["dylib", "rlib"] [dependencies] +cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } term = { path = "../libterm" } std = { path = "../libstd" } diff --git a/src/libtest/helpers/concurrency.rs b/src/libtest/helpers/concurrency.rs index e8f3820558a6d..2fe87247e3acf 100644 --- a/src/libtest/helpers/concurrency.rs +++ b/src/libtest/helpers/concurrency.rs @@ -14,61 +14,36 @@ pub fn get_concurrency() -> usize { } Err(..) => num_cpus(), }; +} - #[cfg(windows)] - #[allow(nonstandard_style)] - fn num_cpus() -> usize { - #[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; - } - unsafe { - let mut sysinfo = std::mem::zeroed(); - GetSystemInfo(&mut sysinfo); - sysinfo.dwNumberOfProcessors as usize +cfg_if::cfg_if! { + if #[cfg(windows)] { + #[allow(nonstandard_style)] + fn num_cpus() -> usize { + #[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; + } + unsafe { + let mut sysinfo = std::mem::zeroed(); + GetSystemInfo(&mut sysinfo); + sysinfo.dwNumberOfProcessors as usize + } } - } - - #[cfg(target_os = "vxworks")] - fn num_cpus() -> usize { - // FIXME: Implement num_cpus on vxWorks - 1 - } - - #[cfg(target_os = "redox")] - fn num_cpus() -> usize { - // FIXME: Implement num_cpus on Redox - 1 - } - - #[cfg(target_os = "hermit")] - fn num_cpus() -> usize { - // FIXME: Implement num_cpus on HermitCore - 1 - } - - #[cfg(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), - all(target_vendor = "fortanix", target_env = "sgx") - ))] - fn num_cpus() -> usize { - 1 - } - - #[cfg(any( + } else if #[cfg(any( target_os = "android", target_os = "cloudabi", target_os = "emscripten", @@ -78,23 +53,46 @@ pub fn get_concurrency() -> usize { target_os = "macos", target_os = "solaris", target_os = "illumos", - ))] - fn num_cpus() -> usize { - unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } - } - - #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] - fn num_cpus() -> usize { - use std::ptr; + ))] { + fn num_cpus() -> usize { + unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } + } + } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { + fn num_cpus() -> usize { + use std::ptr; - let mut cpus: libc::c_uint = 0; - let mut cpus_size = std::mem::size_of_val(&cpus); + let mut cpus: libc::c_uint = 0; + let mut cpus_size = std::mem::size_of_val(&cpus); - unsafe { - cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint; + unsafe { + cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint; + } + if cpus < 1 { + let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + 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, + ); + } + if cpus < 1 { + cpus = 1; + } + } + cpus as usize } - if cpus < 1 { + } else if #[cfg(target_os = "openbsd")] { + fn num_cpus() -> usize { + use std::ptr; + + let mut cpus: libc::c_uint = 0; + let mut cpus_size = std::mem::size_of_val(&cpus); let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + unsafe { libc::sysctl( mib.as_mut_ptr(), @@ -108,43 +106,12 @@ pub fn get_concurrency() -> usize { if cpus < 1 { cpus = 1; } + cpus as usize } - cpus as usize - } - - #[cfg(target_os = "openbsd")] - fn num_cpus() -> usize { - use std::ptr; - - let mut cpus: libc::c_uint = 0; - let mut cpus_size = std::mem::size_of_val(&cpus); - let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; - - 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, - ); - } - if cpus < 1 { - cpus = 1; + } else { + // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re + fn num_cpus() -> usize { + 1 } - cpus as usize - } - - #[cfg(target_os = "haiku")] - fn num_cpus() -> usize { - // FIXME: implement - 1 - } - - #[cfg(target_os = "l4re")] - fn num_cpus() -> usize { - // FIXME: implement - 1 } } diff --git a/src/libtest/helpers/isatty.rs b/src/libtest/helpers/isatty.rs index 831094f7545c1..874ecc3764572 100644 --- a/src/libtest/helpers/isatty.rs +++ b/src/libtest/helpers/isatty.rs @@ -1,34 +1,32 @@ //! Helper module which provides a function to test //! if stdout is a tty. -#[cfg(any( - target_os = "cloudabi", - target_os = "hermit", - all(target_arch = "wasm32", not(target_os = "emscripten")), - all(target_vendor = "fortanix", target_env = "sgx") -))] -pub fn stdout_isatty() -> bool { - // FIXME: Implement isatty on SGX - false -} -#[cfg(unix)] -pub fn stdout_isatty() -> bool { - unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } -} -#[cfg(windows)] -pub fn stdout_isatty() -> bool { - type DWORD = u32; - type BOOL = i32; - type HANDLE = *mut u8; - type LPDWORD = *mut u32; - const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; - extern "system" { - fn GetStdHandle(which: DWORD) -> HANDLE; - fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; - } - unsafe { - let handle = GetStdHandle(STD_OUTPUT_HANDLE); - let mut out = 0; - GetConsoleMode(handle, &mut out) != 0 +cfg_if::cfg_if! { + if #[cfg(unix)] { + pub fn stdout_isatty() -> bool { + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } + } + } else if #[cfg(windows)] { + pub fn stdout_isatty() -> bool { + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + type LPDWORD = *mut u32; + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; + } + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } + } + } else { + // FIXME: Implement isatty on SGX + pub fn stdout_isatty() -> bool { + false + } } } From 9e58908e27d47683800ab0869a98502a6f485a62 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 21 May 2020 20:04:57 -0700 Subject: [PATCH 16/50] Use cfg_if in libpanic_abort. This allows setting a default abort using the core intrinsic. --- Cargo.lock | 1 + src/libpanic_abort/Cargo.toml | 1 + src/libpanic_abort/lib.rs | 34 ++++++++++++++++++---------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 386d5e960016a..28ff6b3b1ebf2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2056,6 +2056,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ + "cfg-if", "compiler_builtins", "core", "libc", diff --git a/src/libpanic_abort/Cargo.toml b/src/libpanic_abort/Cargo.toml index 2bee0b716c750..dc385022440e0 100644 --- a/src/libpanic_abort/Cargo.toml +++ b/src/libpanic_abort/Cargo.toml @@ -11,6 +11,7 @@ bench = false doc = false [dependencies] +cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } core = { path = "../libcore" } libc = { version = "0.2", default-features = false } compiler_builtins = "0.1.0" diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 27056d5f934fd..497f40cafd3ed 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -40,23 +40,25 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { abort(); - #[cfg(any(unix, target_os = "cloudabi"))] - unsafe fn abort() -> ! { - libc::abort(); - } - - #[cfg(any(windows, all(target_arch = "wasm32", not(target_os = "emscripten"))))] - unsafe fn abort() -> ! { - core::intrinsics::abort(); - } - - #[cfg(any(target_os = "hermit", all(target_vendor = "fortanix", target_env = "sgx")))] - unsafe fn abort() -> ! { - // call std::sys::abort_internal - extern "C" { - pub fn __rust_abort() -> !; + cfg_if::cfg_if! { + if #[cfg(any(unix, target_os = "cloudabi"))] { + unsafe fn abort() -> ! { + libc::abort(); + } + } else if #[cfg(any(target_os = "hermit", + all(target_vendor = "fortanix", target_env = "sgx")))] { + unsafe fn abort() -> ! { + // call std::sys::abort_internal + extern "C" { + pub fn __rust_abort() -> !; + } + __rust_abort(); + } + } else { + unsafe fn abort() -> ! { + core::intrinsics::abort(); + } } - __rust_abort(); } } From 6e9a1de0d146734e51cc7e761b288e9b9b138d4f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 31 May 2020 18:09:25 -0700 Subject: [PATCH 17/50] Introduce restricted-std feature. --- src/libpanic_unwind/lib.rs | 2 +- src/libproc_macro/lib.rs | 1 + src/librustc_passes/stability.rs | 3 +- src/libstd/build.rs | 3 + src/libstd/lib.rs | 9 ++- src/libstd/sys/mod.rs | 3 +- src/libstd/sys/unsupported/alloc.rs | 22 +++++++ src/libstd/sys/unsupported/args.rs | 38 +++++++++++ src/libstd/sys/{wasm => unsupported}/cmath.rs | 0 src/libstd/sys/unsupported/common.rs | 48 ++++++++++++++ .../sys/{wasm => unsupported}/condvar.rs | 4 +- src/libstd/sys/unsupported/env.rs | 9 +++ src/libstd/sys/{wasm => unsupported}/fs.rs | 0 src/libstd/sys/{wasm => unsupported}/io.rs | 0 src/libstd/sys/unsupported/mod.rs | 24 +++++++ src/libstd/sys/{wasm => unsupported}/mutex.rs | 7 ++- src/libstd/sys/{wasm => unsupported}/net.rs | 0 src/libstd/sys/{wasm => unsupported}/os.rs | 21 +++---- src/libstd/sys/{wasm => unsupported}/path.rs | 0 src/libstd/sys/{wasm => unsupported}/pipe.rs | 0 .../sys/{wasm => unsupported}/process.rs | 0 .../sys/{wasm => unsupported}/rwlock.rs | 2 +- .../{wasm => unsupported}/stack_overflow.rs | 0 src/libstd/sys/{wasm => unsupported}/stdio.rs | 0 src/libstd/sys/unsupported/thread.rs | 41 ++++++++++++ .../thread_local_dtor.rs | 0 .../{wasm => unsupported}/thread_local_key.rs | 10 +-- src/libstd/sys/{wasm => unsupported}/time.rs | 4 +- src/libstd/sys/wasi/mod.rs | 45 ++++--------- src/libstd/sys/wasm/memchr.rs | 1 - src/libstd/sys/wasm/mod.rs | 63 ++++++------------- src/libstd/sys_common/mod.rs | 2 + src/libstd/sys_common/mutex.rs | 1 + src/libunwind/lib.rs | 11 +++- src/tools/rustc-std-workspace-std/lib.rs | 1 + 35 files changed, 266 insertions(+), 109 deletions(-) create mode 100644 src/libstd/sys/unsupported/alloc.rs create mode 100644 src/libstd/sys/unsupported/args.rs rename src/libstd/sys/{wasm => unsupported}/cmath.rs (100%) create mode 100644 src/libstd/sys/unsupported/common.rs rename src/libstd/sys/{wasm => unsupported}/condvar.rs (84%) create mode 100644 src/libstd/sys/unsupported/env.rs rename src/libstd/sys/{wasm => unsupported}/fs.rs (100%) rename src/libstd/sys/{wasm => unsupported}/io.rs (100%) create mode 100644 src/libstd/sys/unsupported/mod.rs rename src/libstd/sys/{wasm => unsupported}/mutex.rs (82%) rename src/libstd/sys/{wasm => unsupported}/net.rs (100%) rename src/libstd/sys/{wasm => unsupported}/os.rs (82%) rename src/libstd/sys/{wasm => unsupported}/path.rs (100%) rename src/libstd/sys/{wasm => unsupported}/pipe.rs (100%) rename src/libstd/sys/{wasm => unsupported}/process.rs (100%) rename src/libstd/sys/{wasm => unsupported}/rwlock.rs (95%) rename src/libstd/sys/{wasm => unsupported}/stack_overflow.rs (100%) rename src/libstd/sys/{wasm => unsupported}/stdio.rs (100%) create mode 100644 src/libstd/sys/unsupported/thread.rs rename src/libstd/sys/{wasm => unsupported}/thread_local_dtor.rs (100%) rename src/libstd/sys/{wasm => unsupported}/thread_local_key.rs (55%) rename src/libstd/sys/{wasm => unsupported}/time.rs (91%) delete mode 100644 src/libstd/sys/wasm/memchr.rs diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index f361354da2ac2..26b503cb7920b 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -41,7 +41,7 @@ cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] mod real_imp; - } else if #[cfg(target_arch = "wasm32")] { + } else if #[cfg(any(target_arch = "wasm32", target_os = "none"))] { #[path = "dummy.rs"] mod real_imp; } else if #[cfg(target_os = "hermit")] { diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 2d5bd7e872bd5..f960bdecc579f 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -26,6 +26,7 @@ #![feature(in_band_lifetimes)] #![feature(negative_impls)] #![feature(optin_builtin_traits)] +#![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(min_specialization)] #![recursion_limit = "256"] diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 76bc6b6c85f02..5d972c70d1392 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -502,7 +502,8 @@ impl Visitor<'tcx> for Checker<'tcx> { match item.kind { hir::ItemKind::ExternCrate(_) => { // compiler-generated `extern crate` items have a dummy span. - if item.span.is_dummy() { + // `std` is still checked for the `restricted-std` feature. + if item.span.is_dummy() && item.ident.as_str() != "std" { return; } diff --git a/src/libstd/build.rs b/src/libstd/build.rs index f33af1ef7f668..8317eedd53fff 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -64,4 +64,7 @@ fn main() { println!("cargo:rustc-link-lib=compiler_rt"); } println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); + if target.contains("-none") || target.contains("nvptx") { + println!("cargo:rustc-cfg=feature=\"restricted-std\""); + } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 5215db7cdb3ce..23863b7706858 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -197,7 +197,8 @@ //! [primitive types]: ../book/ch03-02-data-types.html //! [rust-discord]: https://discord.gg/rust-lang -#![stable(feature = "rust1", since = "1.0.0")] +#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] +#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))] #![doc( html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", @@ -552,3 +553,9 @@ include!("primitive_docs.rs"); // the rustdoc documentation for the existing keywords. Using `include!` // because rustdoc only looks for these modules at the crate level. include!("keyword_docs.rs"); + +// This is required to avoid an unstable error when `restricted-std` is not +// enabled. The use of #![feature(restricted_std)] in rustc-std-workspace-std +// is unconditional, so the unstable feature needs to be defined somewhere. +#[cfg_attr(not(feature = "restricted-std"), unstable(feature = "restricted_std", issue = "none"))] +mod __restricted_std_workaround {} diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index 875ff1af92013..7b5fac922d08a 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -48,7 +48,8 @@ cfg_if::cfg_if! { mod sgx; pub use self::sgx::*; } else { - compile_error!("libstd doesn't compile for this platform yet"); + mod unsupported; + pub use self::unsupported::*; } } diff --git a/src/libstd/sys/unsupported/alloc.rs b/src/libstd/sys/unsupported/alloc.rs new file mode 100644 index 0000000000000..8d5d0a2f5ccd1 --- /dev/null +++ b/src/libstd/sys/unsupported/alloc.rs @@ -0,0 +1,22 @@ +use crate::alloc::{GlobalAlloc, Layout, System}; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { + 0 as *mut u8 + } + + #[inline] + unsafe fn alloc_zeroed(&self, _layout: Layout) -> *mut u8 { + 0 as *mut u8 + } + + #[inline] + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} + + #[inline] + unsafe fn realloc(&self, _ptr: *mut u8, _layout: Layout, _new_size: usize) -> *mut u8 { + 0 as *mut u8 + } +} diff --git a/src/libstd/sys/unsupported/args.rs b/src/libstd/sys/unsupported/args.rs new file mode 100644 index 0000000000000..71d0c5fa13e18 --- /dev/null +++ b/src/libstd/sys/unsupported/args.rs @@ -0,0 +1,38 @@ +use crate::ffi::OsString; + +pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} +pub unsafe fn cleanup() {} + +pub struct Args {} + +pub fn args() -> Args { + Args {} +} + +impl Args { + pub fn inner_debug(&self) -> &[OsString] { + &[] + } +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { + None + } + fn size_hint(&self) -> (usize, Option) { + (0, Some(0)) + } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { + 0 + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option { + None + } +} diff --git a/src/libstd/sys/wasm/cmath.rs b/src/libstd/sys/unsupported/cmath.rs similarity index 100% rename from src/libstd/sys/wasm/cmath.rs rename to src/libstd/sys/unsupported/cmath.rs diff --git a/src/libstd/sys/unsupported/common.rs b/src/libstd/sys/unsupported/common.rs new file mode 100644 index 0000000000000..80311d26819ad --- /dev/null +++ b/src/libstd/sys/unsupported/common.rs @@ -0,0 +1,48 @@ +use crate::io as std_io; + +pub mod memchr { + pub use core::slice::memchr::{memchr, memrchr}; +} + +pub use crate::sys_common::os_str_bytes as os_str; + +// This is not necessarily correct. May want to consider making it part of the +// spec definition? +use crate::os::raw::c_char; + +#[cfg(not(test))] +pub fn init() {} + +pub fn unsupported() -> std_io::Result { + Err(unsupported_err()) +} + +pub fn unsupported_err() -> std_io::Error { + std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform") +} + +pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { + crate::io::ErrorKind::Other +} + +pub fn abort_internal() -> ! { + core::intrinsics::abort(); +} + +pub fn hashmap_random_keys() -> (u64, u64) { + (1, 2) +} + +// This enum is used as the storage for a bunch of types which can't actually +// exist. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum Void {} + +pub unsafe fn strlen(mut s: *const c_char) -> usize { + let mut n = 0; + while *s != 0 { + n += 1; + s = s.offset(1); + } + return n; +} diff --git a/src/libstd/sys/wasm/condvar.rs b/src/libstd/sys/unsupported/condvar.rs similarity index 84% rename from src/libstd/sys/wasm/condvar.rs rename to src/libstd/sys/unsupported/condvar.rs index 9fd781c728215..a578eee8ccce2 100644 --- a/src/libstd/sys/wasm/condvar.rs +++ b/src/libstd/sys/unsupported/condvar.rs @@ -18,11 +18,11 @@ impl Condvar { pub unsafe fn notify_all(&self) {} pub unsafe fn wait(&self, _mutex: &Mutex) { - panic!("can't block with web assembly") + panic!("condvar wait not supported") } pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { - panic!("can't block with web assembly"); + panic!("condvar wait not supported"); } #[inline] diff --git a/src/libstd/sys/unsupported/env.rs b/src/libstd/sys/unsupported/env.rs new file mode 100644 index 0000000000000..d2efec506c56b --- /dev/null +++ b/src/libstd/sys/unsupported/env.rs @@ -0,0 +1,9 @@ +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = ""; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ""; + pub const DLL_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/unsupported/fs.rs similarity index 100% rename from src/libstd/sys/wasm/fs.rs rename to src/libstd/sys/unsupported/fs.rs diff --git a/src/libstd/sys/wasm/io.rs b/src/libstd/sys/unsupported/io.rs similarity index 100% rename from src/libstd/sys/wasm/io.rs rename to src/libstd/sys/unsupported/io.rs diff --git a/src/libstd/sys/unsupported/mod.rs b/src/libstd/sys/unsupported/mod.rs new file mode 100644 index 0000000000000..87f655eecd54e --- /dev/null +++ b/src/libstd/sys/unsupported/mod.rs @@ -0,0 +1,24 @@ +pub mod alloc; +pub mod args; +pub mod cmath; +pub mod condvar; +pub mod env; +pub mod fs; +pub mod io; +pub mod mutex; +pub mod net; +pub mod os; +pub mod path; +pub mod pipe; +pub mod process; +pub mod rwlock; +pub mod stack_overflow; +pub mod stdio; +pub mod thread; +#[cfg(target_thread_local)] +pub mod thread_local_dtor; +pub mod thread_local_key; +pub mod time; + +mod common; +pub use common::*; diff --git a/src/libstd/sys/wasm/mutex.rs b/src/libstd/sys/unsupported/mutex.rs similarity index 82% rename from src/libstd/sys/wasm/mutex.rs rename to src/libstd/sys/unsupported/mutex.rs index 7aaf1b3a343b6..9ef8af52eb5c2 100644 --- a/src/libstd/sys/wasm/mutex.rs +++ b/src/libstd/sys/unsupported/mutex.rs @@ -5,9 +5,10 @@ pub struct Mutex { } unsafe impl Send for Mutex {} -unsafe impl Sync for Mutex {} // no threads on wasm +unsafe impl Sync for Mutex {} // no threads on this platform impl Mutex { + #[rustc_const_stable(feature = "const_sys_mutex_new", since = "1.0.0")] pub const fn new() -> Mutex { Mutex { locked: UnsafeCell::new(false) } } @@ -42,8 +43,8 @@ impl Mutex { pub unsafe fn destroy(&self) {} } -// All empty stubs because wasm has no threads yet, so lock acquisition always -// succeeds. +// All empty stubs because this platform does not yet support threads, so lock +// acquisition always succeeds. pub struct ReentrantMutex {} impl ReentrantMutex { diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/unsupported/net.rs similarity index 100% rename from src/libstd/sys/wasm/net.rs rename to src/libstd/sys/unsupported/net.rs diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/unsupported/os.rs similarity index 82% rename from src/libstd/sys/wasm/os.rs rename to src/libstd/sys/unsupported/os.rs index 91afdc8a5a0cc..0615780c24212 100644 --- a/src/libstd/sys/wasm/os.rs +++ b/src/libstd/sys/unsupported/os.rs @@ -1,10 +1,9 @@ +use super::{unsupported, Void}; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::fmt; use crate::io; use crate::path::{self, PathBuf}; -use crate::str; -use crate::sys::{unsupported, Void}; pub fn errno() -> i32 { 0 @@ -48,14 +47,14 @@ where impl fmt::Display for JoinPathsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on wasm yet".fmt(f) + "not supported on this platform yet".fmt(f) } } impl StdError for JoinPathsError { #[allow(deprecated)] fn description(&self) -> &str { - "not supported on wasm yet" + "not supported on this platform yet" } } @@ -73,7 +72,7 @@ impl Iterator for Env { } pub fn env() -> Env { - panic!("not supported on web assembly") + panic!("not supported on this platform") } pub fn getenv(_: &OsStr) -> io::Result> { @@ -81,15 +80,15 @@ pub fn getenv(_: &OsStr) -> io::Result> { } pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on wasm32-unknown-unknown")) + Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on this platform")) } pub fn unsetenv(_: &OsStr) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on wasm32-unknown-unknown")) + Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on this platform")) } pub fn temp_dir() -> PathBuf { - panic!("no filesystem on wasm") + panic!("no filesystem on this platform") } pub fn home_dir() -> Option { @@ -97,11 +96,9 @@ pub fn home_dir() -> Option { } pub fn exit(_code: i32) -> ! { - unsafe { - crate::arch::wasm32::unreachable(); - } + crate::intrinsics::abort() } pub fn getpid() -> u32 { - panic!("no pids on wasm") + panic!("no pids on this platform") } diff --git a/src/libstd/sys/wasm/path.rs b/src/libstd/sys/unsupported/path.rs similarity index 100% rename from src/libstd/sys/wasm/path.rs rename to src/libstd/sys/unsupported/path.rs diff --git a/src/libstd/sys/wasm/pipe.rs b/src/libstd/sys/unsupported/pipe.rs similarity index 100% rename from src/libstd/sys/wasm/pipe.rs rename to src/libstd/sys/unsupported/pipe.rs diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/unsupported/process.rs similarity index 100% rename from src/libstd/sys/wasm/process.rs rename to src/libstd/sys/unsupported/process.rs diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/unsupported/rwlock.rs similarity index 95% rename from src/libstd/sys/wasm/rwlock.rs rename to src/libstd/sys/unsupported/rwlock.rs index a59944482e9e9..d37f34ac9352d 100644 --- a/src/libstd/sys/wasm/rwlock.rs +++ b/src/libstd/sys/unsupported/rwlock.rs @@ -5,7 +5,7 @@ pub struct RWLock { } unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} // no threads on wasm +unsafe impl Sync for RWLock {} // no threads on this platform impl RWLock { pub const fn new() -> RWLock { diff --git a/src/libstd/sys/wasm/stack_overflow.rs b/src/libstd/sys/unsupported/stack_overflow.rs similarity index 100% rename from src/libstd/sys/wasm/stack_overflow.rs rename to src/libstd/sys/unsupported/stack_overflow.rs diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/unsupported/stdio.rs similarity index 100% rename from src/libstd/sys/wasm/stdio.rs rename to src/libstd/sys/unsupported/stdio.rs diff --git a/src/libstd/sys/unsupported/thread.rs b/src/libstd/sys/unsupported/thread.rs new file mode 100644 index 0000000000000..20ae309db30d7 --- /dev/null +++ b/src/libstd/sys/unsupported/thread.rs @@ -0,0 +1,41 @@ +use super::{unsupported, Void}; +use crate::ffi::CStr; +use crate::io; +use crate::time::Duration; + +pub struct Thread(Void); + +pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; + +impl Thread { + // unsafe: see thread::Builder::spawn_unchecked for safety requirements + pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { + unsupported() + } + + pub fn yield_now() { + // do nothing + } + + pub fn set_name(_name: &CStr) { + // nope + } + + pub fn sleep(_dur: Duration) { + panic!("can't sleep"); + } + + pub fn join(self) { + match self.0 {} + } +} + +pub mod guard { + pub type Guard = !; + pub unsafe fn current() -> Option { + None + } + pub unsafe fn init() -> Option { + None + } +} diff --git a/src/libstd/sys/wasm/thread_local_dtor.rs b/src/libstd/sys/unsupported/thread_local_dtor.rs similarity index 100% rename from src/libstd/sys/wasm/thread_local_dtor.rs rename to src/libstd/sys/unsupported/thread_local_dtor.rs diff --git a/src/libstd/sys/wasm/thread_local_key.rs b/src/libstd/sys/unsupported/thread_local_key.rs similarity index 55% rename from src/libstd/sys/wasm/thread_local_key.rs rename to src/libstd/sys/unsupported/thread_local_key.rs index f8be9863ed56f..c31b61cbf56d3 100644 --- a/src/libstd/sys/wasm/thread_local_key.rs +++ b/src/libstd/sys/unsupported/thread_local_key.rs @@ -2,25 +2,25 @@ pub type Key = usize; #[inline] pub unsafe fn create(_dtor: Option) -> Key { - panic!("should not be used on the wasm target"); + panic!("should not be used on this target"); } #[inline] pub unsafe fn set(_key: Key, _value: *mut u8) { - panic!("should not be used on the wasm target"); + panic!("should not be used on this target"); } #[inline] pub unsafe fn get(_key: Key) -> *mut u8 { - panic!("should not be used on the wasm target"); + panic!("should not be used on this target"); } #[inline] pub unsafe fn destroy(_key: Key) { - panic!("should not be used on the wasm target"); + panic!("should not be used on this target"); } #[inline] pub fn requires_synchronized_create() -> bool { - panic!("should not be used on the wasm target"); + panic!("should not be used on this target"); } diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/unsupported/time.rs similarity index 91% rename from src/libstd/sys/wasm/time.rs rename to src/libstd/sys/unsupported/time.rs index d9edc7fdc4451..8aaf1777f2427 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/unsupported/time.rs @@ -10,7 +10,7 @@ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); impl Instant { pub fn now() -> Instant { - panic!("time not implemented on wasm32-unknown-unknown") + panic!("time not implemented on this platform") } pub const fn zero() -> Instant { @@ -36,7 +36,7 @@ impl Instant { impl SystemTime { pub fn now() -> SystemTime { - panic!("time not implemented on wasm32-unknown-unknown") + panic!("time not implemented on this platform") } pub fn sub_time(&self, other: &SystemTime) -> Result { diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index 85f5282034ff1..2704ff484f991 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -16,21 +16,18 @@ use crate::io as std_io; use crate::mem; -use crate::os::raw::c_char; pub mod alloc; pub mod args; -#[path = "../wasm/cmath.rs"] +#[path = "../unsupported/cmath.rs"] pub mod cmath; -#[path = "../wasm/condvar.rs"] +#[path = "../unsupported/condvar.rs"] pub mod condvar; pub mod env; pub mod fd; pub mod fs; pub mod io; -#[path = "../wasm/memchr.rs"] -pub mod memchr; -#[path = "../wasm/mutex.rs"] +#[path = "../unsupported/mutex.rs"] pub mod mutex; pub mod net; pub mod os; @@ -39,28 +36,22 @@ pub mod ext; pub mod path; pub mod pipe; pub mod process; -#[path = "../wasm/rwlock.rs"] +#[path = "../unsupported/rwlock.rs"] pub mod rwlock; -#[path = "../wasm/stack_overflow.rs"] +#[path = "../unsupported/stack_overflow.rs"] pub mod stack_overflow; pub mod stdio; pub mod thread; -#[path = "../wasm/thread_local_dtor.rs"] +#[path = "../unsupported/thread_local_dtor.rs"] pub mod thread_local_dtor; -#[path = "../wasm/thread_local_key.rs"] +#[path = "../unsupported/thread_local_key.rs"] pub mod thread_local_key; pub mod time; -#[cfg(not(test))] -pub fn init() {} - -pub fn unsupported() -> std_io::Result { - Err(unsupported_err()) -} - -pub fn unsupported_err() -> std_io::Error { - std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on wasm yet") -} +#[path = "../unsupported/common.rs"] +#[allow(unused)] +mod common; +pub use common::*; pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { use std_io::ErrorKind::*; @@ -86,20 +77,6 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { } } -// This enum is used as the storage for a bunch of types which can't actually -// exist. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub enum Void {} - -pub unsafe fn strlen(mut s: *const c_char) -> usize { - let mut n = 0; - while *s != 0 { - n += 1; - s = s.offset(1); - } - return n; -} - pub fn abort_internal() -> ! { unsafe { libc::abort() } } diff --git a/src/libstd/sys/wasm/memchr.rs b/src/libstd/sys/wasm/memchr.rs deleted file mode 100644 index 9967482197eb3..0000000000000 --- a/src/libstd/sys/wasm/memchr.rs +++ /dev/null @@ -1 +0,0 @@ -pub use core::slice::memchr::{memchr, memrchr}; diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index 6939596e52d78..3de5890404357 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -14,25 +14,35 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -use crate::os::raw::c_char; - pub mod alloc; pub mod args; +#[path = "../unsupported/cmath.rs"] pub mod cmath; pub mod env; +#[path = "../unsupported/fs.rs"] pub mod fs; +#[path = "../unsupported/io.rs"] pub mod io; -pub mod memchr; +#[path = "../unsupported/net.rs"] pub mod net; +#[path = "../unsupported/os.rs"] pub mod os; +#[path = "../unsupported/path.rs"] pub mod path; +#[path = "../unsupported/pipe.rs"] pub mod pipe; +#[path = "../unsupported/process.rs"] pub mod process; +#[path = "../unsupported/stack_overflow.rs"] pub mod stack_overflow; +#[path = "../unsupported/stdio.rs"] pub mod stdio; pub mod thread; +#[path = "../unsupported/thread_local_dtor.rs"] pub mod thread_local_dtor; +#[path = "../unsupported/thread_local_key.rs"] pub mod thread_local_key; +#[path = "../unsupported/time.rs"] pub mod time; pub use crate::sys_common::os_str_bytes as os_str; @@ -46,50 +56,15 @@ cfg_if::cfg_if! { #[path = "rwlock_atomics.rs"] pub mod rwlock; } else { + #[path = "../unsupported/condvar.rs"] pub mod condvar; + #[path = "../unsupported/mutex.rs"] pub mod mutex; + #[path = "../unsupported/rwlock.rs"] pub mod rwlock; } } -#[cfg(not(test))] -pub fn init() {} - -pub fn unsupported() -> crate::io::Result { - Err(unsupported_err()) -} - -pub fn unsupported_err() -> crate::io::Error { - crate::io::Error::new(crate::io::ErrorKind::Other, "operation not supported on wasm yet") -} - -pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { - crate::io::ErrorKind::Other -} - -// This enum is used as the storage for a bunch of types which can't actually -// exist. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub enum Void {} - -pub unsafe fn strlen(mut s: *const c_char) -> usize { - let mut n = 0; - while *s != 0 { - n += 1; - s = s.offset(1); - } - return n; -} - -pub fn abort_internal() -> ! { - unsafe { crate::arch::wasm32::unreachable() } -} - -// We don't have randomness yet, but I totally used a random number generator to -// generate these numbers. -// -// More seriously though this is just for DOS protection in hash maps. It's ok -// if we don't do that on wasm just yet. -pub fn hashmap_random_keys() -> (u64, u64) { - (1, 2) -} +#[path = "../unsupported/common.rs"] +mod common; +pub use common::*; diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index e57bb267cbd0f..c3e6a5570e6ae 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -57,6 +57,7 @@ pub mod mutex; target_os = "cloudabi", target_os = "hermit", target_arch = "wasm32", + feature = "restricted-std", all(target_vendor = "fortanix", target_env = "sgx")))] pub mod os_str_bytes; pub mod poison; @@ -74,6 +75,7 @@ cfg_if::cfg_if! { if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "hermit", + feature = "restricted-std", all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))] { pub use crate::sys::net; diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs index 899fc6a723530..e66d8994147e1 100644 --- a/src/libstd/sys_common/mutex.rs +++ b/src/libstd/sys_common/mutex.rs @@ -17,6 +17,7 @@ impl Mutex { /// Also, until `init` is called, behavior is undefined if this /// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock` /// are called by the thread currently holding the lock. + #[rustc_const_stable(feature = "const_sys_mutex_new", since = "1.0.0")] pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) } diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index cc025da1af555..c705ed31fd5a4 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -10,7 +10,16 @@ cfg_if::cfg_if! { if #[cfg(target_env = "msvc")] { // no extra unwinder support needed - } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { + } else if #[cfg( + any( + all(target_arch = "wasm32", not(target_os = "emscripten")), + target_os = "none", + target_os = "hermit", + target_os = "uefi", + target_os = "cuda", + target_os = "l4re", + ))] + { // no unwinder on the system! } else { mod libunwind; diff --git a/src/tools/rustc-std-workspace-std/lib.rs b/src/tools/rustc-std-workspace-std/lib.rs index f40d09cafbb47..1e955c61ac85f 100644 --- a/src/tools/rustc-std-workspace-std/lib.rs +++ b/src/tools/rustc-std-workspace-std/lib.rs @@ -1 +1,2 @@ +#![feature(restricted_std)] pub use std::*; From cee9f05c2d369cda1d8487fe6e475a2ae990b9f8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 6 Jul 2020 20:25:44 -0700 Subject: [PATCH 18/50] Tweak formatting. --- src/libpanic_abort/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 497f40cafd3ed..95f3966228a2f 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -46,7 +46,8 @@ pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { libc::abort(); } } else if #[cfg(any(target_os = "hermit", - all(target_vendor = "fortanix", target_env = "sgx")))] { + all(target_vendor = "fortanix", target_env = "sgx") + ))] { unsafe fn abort() -> ! { // call std::sys::abort_internal extern "C" { From 0eb293ddb72ce080b3d0a6bdf643bd645849fa9e Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 6 Jul 2020 20:31:12 -0700 Subject: [PATCH 19/50] Use an allow-list of platforms that support std. Use a fall-through for no_std targets. --- src/libpanic_unwind/lib.rs | 20 ++++++++++++++++---- src/libstd/build.rs | 26 +++++++++++++++++++++++--- src/libunwind/lib.rs | 36 +++++++++++++++++++++++------------- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 26b503cb7920b..430062d4ac44e 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -41,21 +41,33 @@ cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] mod real_imp; - } else if #[cfg(any(target_arch = "wasm32", target_os = "none"))] { - #[path = "dummy.rs"] - mod real_imp; } else if #[cfg(target_os = "hermit")] { #[path = "hermit.rs"] mod real_imp; } else if #[cfg(target_env = "msvc")] { #[path = "seh.rs"] mod real_imp; - } else { + } else if #[cfg(any( + all(target_family = "windows", target_env = "gnu"), + target_os = "cloudabi", + target_family = "unix", + all(target_vendor = "fortanix", target_env = "sgx"), + ))] { // Rust runtime's startup objects depend on these symbols, so make them public. #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] pub use real_imp::eh_frame_registry::*; #[path = "gcc.rs"] mod real_imp; + } else { + // Targets that don't support unwinding. + // - arch=wasm32 + // - os=none ("bare metal" targets) + // - os=uefi + // - nvptx64-nvidia-cuda + // - avr-unknown-unknown + // - mipsel-sony-psp + #[path = "dummy.rs"] + mod real_imp; } } diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 8317eedd53fff..eb2753d62457a 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -62,9 +62,29 @@ fn main() { } println!("cargo:rustc-link-lib=c"); println!("cargo:rustc-link-lib=compiler_rt"); - } - println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); - if target.contains("-none") || target.contains("nvptx") { + } else if (target.contains("sgx") && target.contains("fortanix")) + || target.contains("hermit") + || target.contains("l4re") + || target.contains("redox") + || target.contains("haiku") + || target.contains("vxworks") + || target.contains("wasm32") + || target.contains("asmjs") + { + // These platforms don't have any special requirements. + } else { + // This is for Cargo's build-std support, to mark std as unstable for + // typically no_std platforms. + // This covers: + // - os=none ("bare metal" targets) + // - mipsel-sony-psp + // - nvptx64-nvidia-cuda + // - avr-unknown-unknown + // - tvos (aarch64-apple-tvos, x86_64-apple-tvos) + // - uefi (x86_64-unknown-uefi, i686-unknown-uefi) + // - JSON targets + // - Any new targets that have not been explicitly added above. println!("cargo:rustc-cfg=feature=\"restricted-std\""); } + println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); } diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index c705ed31fd5a4..c4d10ab177be9 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -9,21 +9,31 @@ cfg_if::cfg_if! { if #[cfg(target_env = "msvc")] { - // no extra unwinder support needed - } else if #[cfg( - any( - all(target_arch = "wasm32", not(target_os = "emscripten")), - target_os = "none", - target_os = "hermit", - target_os = "uefi", - target_os = "cuda", - target_os = "l4re", - ))] - { - // no unwinder on the system! - } else { + // Windows MSVC no extra unwinder support needed + } else if #[cfg(any( + target_os = "l4re", + target_os = "none", + ))] { + // These "unix" family members do not have unwinder. + // Note this also matches x86_64-linux-kernel. + } else if #[cfg(any( + unix, + windows, + target_os = "cloudabi", + all(target_vendor = "fortanix", target_env = "sgx"), + ))] { mod libunwind; pub use libunwind::*; + } else { + // no unwinder on the system! + // - wasm32 (not emscripten, which is "unix" family) + // - os=none ("bare metal" targets) + // - os=hermit + // - os=uefi + // - os=cuda + // - nvptx64-nvidia-cuda + // - mipsel-sony-psp + // - Any new targets not listed above. } } From 3d44d3ccfd0a17c6d45bc504be182b47efe1018d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 7 Jul 2020 10:51:45 -0700 Subject: [PATCH 20/50] Simplify os_str_bytes cfg expression. --- src/libstd/sys_common/mod.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index c3e6a5570e6ae..840f9093e00f1 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -51,14 +51,9 @@ pub mod condvar; pub mod fs; pub mod io; pub mod mutex; -#[cfg(any(doc, // see `mod os`, docs are generated for multiple platforms - unix, - target_os = "redox", - target_os = "cloudabi", - target_os = "hermit", - target_arch = "wasm32", - feature = "restricted-std", - all(target_vendor = "fortanix", target_env = "sgx")))] +// `doc` is required because `sys/mod.rs` imports `unix/ext/mod.rs` on Windows +// when generating documentation. +#[cfg(any(doc, not(windows)))] pub mod os_str_bytes; pub mod poison; pub mod process; From 85c25aed510ce599504b172f7c7bef280e91637b Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 15 Jul 2020 15:48:36 -0700 Subject: [PATCH 21/50] Move usercall_wait_timeout to abi::usercalls::wait_timeout --- src/libstd/sys/sgx/abi/usercalls/mod.rs | 74 +++++++++++++++++++++++- src/libstd/sys/sgx/mod.rs | 76 ------------------------- src/libstd/sys/sgx/thread.rs | 3 +- src/libstd/sys/sgx/waitqueue.rs | 3 +- 4 files changed, 74 insertions(+), 82 deletions(-) diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index 6ee147d1704ad..73f1b951e7430 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -1,8 +1,8 @@ use crate::cmp; use crate::convert::TryFrom; -use crate::io::{Error as IoError, IoSlice, IoSliceMut, Result as IoResult}; +use crate::io::{Error as IoError, ErrorKind, IoSlice, IoSliceMut, Result as IoResult}; use crate::sys::rand::rdrand64; -use crate::time::Duration; +use crate::time::{Duration, Instant}; pub(crate) mod alloc; #[macro_use] @@ -169,6 +169,76 @@ pub fn wait(event_mask: u64, mut timeout: u64) -> IoResult { unsafe { raw::wait(event_mask, timeout).from_sgx_result() } } +/// This function makes an effort to wait for a non-spurious event at least as +/// long as `duration`. Note that in general there is no guarantee about accuracy +/// of time and timeouts in SGX model. The enclave runner serving usercalls may +/// lie about current time and/or ignore timeout values. +/// +/// Once the event is observed, `should_wake_up` will be used to determine +/// whether or not the event was spurious. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub fn wait_timeout(event_mask: u64, duration: Duration, should_wake_up: F) +where + F: Fn() -> bool, +{ + // Calls the wait usercall and checks the result. Returns true if event was + // returned, and false if WouldBlock/TimedOut was returned. + // If duration is None, it will use WAIT_NO. + fn wait_checked(event_mask: u64, duration: Option) -> bool { + let timeout = duration.map_or(raw::WAIT_NO, |duration| { + cmp::min((u64::MAX - 1) as u128, duration.as_nanos()) as u64 + }); + match wait(event_mask, timeout) { + Ok(eventset) => { + if event_mask == 0 { + rtabort!("expected wait() to return Err, found Ok."); + } + rtassert!(eventset != 0 && eventset & !event_mask == 0); + true + } + Err(e) => { + rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock); + false + } + } + } + + match wait_checked(event_mask, Some(duration)) { + false => return, // timed out + true if should_wake_up() => return, // woken up + true => {} // spurious event + } + + // Drain all cached events. + // Note that `event_mask != 0` is implied if we get here. + loop { + match wait_checked(event_mask, None) { + false => break, // no more cached events + true if should_wake_up() => return, // woken up + true => {} // spurious event + } + } + + // Continue waiting, but take note of time spent waiting so we don't wait + // forever. We intentionally don't call `Instant::now()` before this point + // to avoid the cost of the `insecure_time` usercall in case there are no + // spurious wakeups. + + let start = Instant::now(); + let mut remaining = duration; + loop { + match wait_checked(event_mask, Some(remaining)) { + false => return, // timed out + true if should_wake_up() => return, // woken up + true => {} // spurious event + } + remaining = match duration.checked_sub(start.elapsed()) { + Some(remaining) => remaining, + None => break, + } + } +} + /// Usercall `send`. See the ABI documentation for more information. #[unstable(feature = "sgx_platform", issue = "56975")] pub fn send(event_set: u64, tcs: Option) -> IoResult<()> { diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index c412053112bc5..7a3a3eb2049b3 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -110,82 +110,6 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { } } -// This function makes an effort to wait for a non-spurious event at least as -// long as `duration`. Note that in general there is no guarantee about accuracy -// of time and timeouts in SGX model. The enclave runner serving usercalls may -// lie about current time and/or ignore timeout values. -// -// Once the event is observed, `should_wake_up` will be used to determine -// whether or not the event was spurious. -pub fn usercall_wait_timeout(event_mask: u64, duration: crate::time::Duration, should_wake_up: F) -where - F: Fn() -> bool, -{ - use self::abi::usercalls; - use crate::cmp; - use crate::io::ErrorKind; - use crate::time::{Duration, Instant}; - - // Calls the wait usercall and checks the result. Returns true if event was - // returned, and false if WouldBlock/TimedOut was returned. - // If duration is None, it will use WAIT_NO. - fn wait_checked(event_mask: u64, duration: Option) -> bool { - let timeout = duration.map_or(usercalls::raw::WAIT_NO, |duration| { - cmp::min((u64::MAX - 1) as u128, duration.as_nanos()) as u64 - }); - match usercalls::wait(event_mask, timeout) { - Ok(eventset) => { - if event_mask == 0 { - rtabort!("expected usercalls::wait() to return Err, found Ok."); - } - // A matching event is one whose bits are equal to or a subset - // of `event_mask`. - rtassert!(eventset & !event_mask == 0); - true - } - Err(e) => { - rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock); - false - } - } - } - - match wait_checked(event_mask, Some(duration)) { - false => return, // timed out - true if should_wake_up() => return, // woken up - true => {} // spurious event - } - - // Drain all cached events. - // Note that `event_mask != 0` is implied if we get here. - loop { - match wait_checked(event_mask, None) { - false => break, // no more cached events - true if should_wake_up() => return, // woken up - true => {} // spurious event - } - } - - // Continue waiting, but take note of time spent waiting so we don't wait - // forever. We intentionally don't call `Instant::now()` before this point - // to avoid the cost of the `insecure_time` usercall in case there are no - // spurious wakeups. - - let start = Instant::now(); - let mut remaining = duration; - loop { - match wait_checked(event_mask, Some(remaining)) { - false => return, // timed out - true if should_wake_up() => return, // woken up - true => {} // spurious event - } - remaining = match duration.checked_sub(start.elapsed()) { - Some(remaining) => remaining, - None => break, - } - } -} - // This enum is used as the storage for a bunch of types which can't actually // exist. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index 58b6f4346bc14..5895f70436efa 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -1,7 +1,6 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? use crate::ffi::CStr; use crate::io; -use crate::sys::usercall_wait_timeout; use crate::time::Duration; use super::abi::usercalls; @@ -75,7 +74,7 @@ impl Thread { } pub fn sleep(dur: Duration) { - usercall_wait_timeout(0, dur, || true); + usercalls::wait_timeout(0, dur, || true); } pub fn join(self) { diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index c8ccab2247a9c..070afa55f3019 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -11,7 +11,6 @@ //! The queue and associated wait state are stored in a `WaitVariable`. use crate::num::NonZeroUsize; use crate::ops::{Deref, DerefMut}; -use crate::sys::usercall_wait_timeout; use crate::time::Duration; use super::abi::thread; @@ -176,7 +175,7 @@ impl WaitQueue { })); let entry_lock = lock.lock().queue.inner.push(&mut entry); before_wait(); - usercall_wait_timeout(EV_UNPARK, timeout, || entry_lock.lock().wake); + usercalls::wait_timeout(EV_UNPARK, timeout, || entry_lock.lock().wake); // acquire the wait queue's lock first to avoid deadlock. let mut guard = lock.lock(); let success = entry_lock.lock().wake; From 1813ae7d524406fe85f9df9eeb110584fa60b8d2 Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Thu, 16 Jul 2020 13:37:42 +0700 Subject: [PATCH 22/50] Add RISC-V GNU/Linux to src/tools/build-manifest as a host platform --- src/tools/build-manifest/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 2c64abb4be6bd..6ac89f2b1b82a 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -34,6 +34,7 @@ static HOSTS: &[&str] = &[ "powerpc-unknown-linux-gnu", "powerpc64-unknown-linux-gnu", "powerpc64le-unknown-linux-gnu", + "riscv64gc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-pc-windows-gnu", From 78d6cb01ffe759eb2bfd321b7040c4a5fd7a8079 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jul 2020 15:57:11 +0200 Subject: [PATCH 23/50] Add tidy checks for rustdoc css files --- src/tools/tidy/src/style.rs | 39 +++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 396d6c0cfcdef..470fab496a442 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -119,6 +119,7 @@ fn contains_ignore_directive(can_contain: bool, contents: &str, check: &str) -> // Update `can_contain` when changing this if contents.contains(&format!("// ignore-tidy-{}", check)) || contents.contains(&format!("# ignore-tidy-{}", check)) + || contents.contains(&format!("/* ignore-tidy-{} */", check)) { Directive::Ignore(false) } else { @@ -136,15 +137,37 @@ macro_rules! suppressible_tidy_err { }; } +pub fn is_in(full_path: &Path, parent_folder_to_find: &str, folder_to_find: &str) -> bool { + if let Some(parent) = full_path.parent() { + if parent.file_name().map_or_else( + || false, + |f| { + f.to_string_lossy() == folder_to_find + && parent + .parent() + .and_then(|f| f.file_name()) + .map_or_else(|| false, |f| f == parent_folder_to_find) + }, + ) { + true + } else { + is_in(parent, parent_folder_to_find, folder_to_find) + } + } else { + false + } +} + pub fn check(path: &Path, bad: &mut bool) { super::walk(path, &mut super::filter_dirs, &mut |entry, contents| { let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); - let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md"]; + let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css"]; if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") { return; } + let is_style_file = filename.ends_with(".css"); let under_rustfmt = filename.ends_with(".rs") && // This list should ideally be sourced from rustfmt.toml but we don't want to add a toml // parser to tidy. @@ -161,6 +184,10 @@ pub fn check(path: &Path, bad: &mut bool) { // currently), just the long error code explanation ones. return; } + if is_style_file && !is_in(file, "src", "librustdoc") { + // We only check CSS files in rustdoc. + return; + } if contents.is_empty() { tidy_error!(bad, "{}: empty file", file.display()); @@ -172,8 +199,9 @@ pub fn check(path: &Path, bad: &mut bool) { COLS }; - let can_contain = - contents.contains("// ignore-tidy-") || contents.contains("# ignore-tidy-"); + let can_contain = contents.contains("// ignore-tidy-") + || contents.contains("# ignore-tidy-") + || contents.contains("/* ignore-tidy-"); // Enable testing ICE's that require specific (untidy) // file formats easily eg. `issue-1234-ignore-tidy.rs` if filename.contains("ignore-tidy") { @@ -208,12 +236,15 @@ pub fn check(path: &Path, bad: &mut bool) { &format!("line longer than {} chars", max_columns) ); } - if line.contains('\t') { + if !is_style_file && line.contains('\t') { suppressible_tidy_err!(err, skip_tab, "tab character"); } if line.ends_with(' ') || line.ends_with('\t') { suppressible_tidy_err!(err, skip_end_whitespace, "trailing whitespace"); } + if is_style_file && line.starts_with(' ') { + err("CSS files use tabs for indent"); + } if line.contains('\r') { suppressible_tidy_err!(err, skip_cr, "CR character"); } From 63ffa13734e9fae4169ead6bbc40dfe4e9fbd4f8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jul 2020 17:20:46 +0200 Subject: [PATCH 24/50] Fix tidy issues --- src/librustdoc/html/static/normalize.css | 1 + src/librustdoc/html/static/rustdoc.css | 12 ++++++----- src/librustdoc/html/static/themes/ayu.css | 22 +++++++++++++-------- src/librustdoc/html/static/themes/dark.css | 6 ++++-- src/librustdoc/html/static/themes/light.css | 6 ++++-- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/static/normalize.css b/src/librustdoc/html/static/normalize.css index 2804c26a29662..0e0426279183f 100644 --- a/src/librustdoc/html/static/normalize.css +++ b/src/librustdoc/html/static/normalize.css @@ -1 +1,2 @@ +/* ignore-tidy-linelength */ /*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index a3f4dc55fe757..53596aabb1d39 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -49,9 +49,9 @@ } * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } /* This part handles the "default" theme being used depending on the system one. */ @@ -91,7 +91,8 @@ h2 { h3 { font-size: 1.3em; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important), +h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { font-weight: 500; margin: 20px 0 15px 0; padding-bottom: 6px; @@ -103,7 +104,8 @@ h1.fqn { h1.fqn > .in-band > a:hover { text-decoration: underline; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { +h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), +h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { border-bottom: 1px solid; } h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant { diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index eabb53e331ecf..ac4f9cb35eacb 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -10,7 +10,8 @@ body { color: #c5c5c5; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), +h4:not(.method):not(.type):not(.tymethod) { color: white; } h1.fqn { @@ -41,7 +42,7 @@ h3 > code, h4 > code, h5 > code { color: #e6e1cf; } pre > code { - color: #e6e1cf; + color: #e6e1cf; } span code { color: #e6e1cf; @@ -192,7 +193,7 @@ pre { color: #a37acc; } -pre.rust .comment, pre.rust .doccomment { +pre.rust .comment, pre.rust .doccomment { color: #788797; font-style: italic; } @@ -416,12 +417,13 @@ pre.ignore:hover, .information:hover + pre.ignore { /* rules that this theme does not need to set, here to satisfy the rule checker */ /* note that a lot of these are partially set in some way (meaning they are set individually rather than as a group) */ -/* TODO: these rules should be at the bottom of the file but currently must be +/* FIXME: these rules should be at the bottom of the file but currently must be above the `@media (max-width: 700px)` rules due to a bug in the css checker */ /* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */ .content .highlighted.mod, .content .highlighted.externcrate {} .search-input:focus {} -.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {} +.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive, +.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {} .content .highlighted.trait {} .content span.struct,.content a.struct,.block a.current.struct {} #titles>div:hover,#titles>div.selected {} @@ -436,16 +438,20 @@ pre.rust .lifetime {} .content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod {} h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod) {} .content span.enum,.content a.enum,.block a.current.enum {} -.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static {} +.content span.constant,.content a.constant,.block a.current.constant,.content span.static, +.content a.static,.block a.current.static {} .content span.keyword,.content a.keyword,.block a.current.keyword {} pre.rust .comment {} .content .highlighted.enum {} .content .highlighted.struct {} .content .highlighted.keyword {} .content span.traitalias,.content a.traitalias,.block a.current.traitalias {} -.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname {} +.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method, +.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod, +.content .fnname {} pre.rust .kw {} -pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident {} +pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute, +pre.rust .attribute .ident {} .content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype {} pre.rust .doccomment {} .stab.deprecated {} diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 41dcb5c24507c..bd6ed7685d952 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -3,13 +3,15 @@ body { color: #ddd; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), +h4:not(.method):not(.type):not(.tymethod) { color: #ddd; } h1.fqn { border-bottom-color: #d2d2d2; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { +h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), +h4:not(.method):not(.type):not(.tymethod) { border-bottom-color: #d2d2d2; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 386fe2398e63a..52cf53bee22e3 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -5,13 +5,15 @@ body { color: black; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), +h4:not(.method):not(.type):not(.tymethod) { color: black; } h1.fqn { border-bottom-color: #D5D5D5; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { +h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), +h4:not(.method):not(.type):not(.tymethod) { border-bottom-color: #DDDDDD; } From 03bbe9d2c93623f789758df67b86f6ce4154951a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 Jul 2020 17:04:34 +0200 Subject: [PATCH 25/50] Clean up E0723 explanation --- src/librustc_error_codes/error_codes/E0723.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0723.md b/src/librustc_error_codes/error_codes/E0723.md index 394ee057b0b0c..95d47ab21cbd3 100644 --- a/src/librustc_error_codes/error_codes/E0723.md +++ b/src/librustc_error_codes/error_codes/E0723.md @@ -1,4 +1,4 @@ -An feature unstable in `const` contexts was used. +An unstable feature in `const` contexts was used. Erroneous code example: From 8e92f4fb912e42d7bb177b1c5a6ee4b530172f45 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 Jul 2020 14:59:39 +1000 Subject: [PATCH 26/50] Remove unused `cx` parameter from `pathvec_std` and `path_std`. --- src/librustc_builtin_macros/deriving/bounds.rs | 2 +- src/librustc_builtin_macros/deriving/clone.rs | 4 ++-- src/librustc_builtin_macros/deriving/cmp/eq.rs | 4 ++-- src/librustc_builtin_macros/deriving/cmp/ord.rs | 4 ++-- src/librustc_builtin_macros/deriving/cmp/partial_eq.rs | 4 ++-- src/librustc_builtin_macros/deriving/cmp/partial_ord.rs | 6 +++--- src/librustc_builtin_macros/deriving/debug.rs | 6 +++--- src/librustc_builtin_macros/deriving/decodable.rs | 2 +- src/librustc_builtin_macros/deriving/default.rs | 2 +- src/librustc_builtin_macros/deriving/encodable.rs | 2 +- src/librustc_builtin_macros/deriving/hash.rs | 4 ++-- src/librustc_builtin_macros/deriving/mod.rs | 2 +- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc_builtin_macros/deriving/bounds.rs b/src/librustc_builtin_macros/deriving/bounds.rs index a1c818caff3bf..86e875934780d 100644 --- a/src/librustc_builtin_macros/deriving/bounds.rs +++ b/src/librustc_builtin_macros/deriving/bounds.rs @@ -16,7 +16,7 @@ pub fn expand_deriving_copy( let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(cx, marker::Copy), + path: path_std!(marker::Copy), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/clone.rs b/src/librustc_builtin_macros/deriving/clone.rs index 5a8648f2aaa4c..471894828f594 100644 --- a/src/librustc_builtin_macros/deriving/clone.rs +++ b/src/librustc_builtin_macros/deriving/clone.rs @@ -56,7 +56,7 @@ pub fn expand_deriving_clone( } } ItemKind::Union(..) => { - bounds = vec![Literal(path_std!(cx, marker::Copy))]; + bounds = vec![Literal(path_std!(marker::Copy))]; is_shallow = true; substructure = combine_substructure(Box::new(|c, s, sub| { cs_clone_shallow("Clone", c, s, sub, true) @@ -78,7 +78,7 @@ pub fn expand_deriving_clone( let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(cx, clone::Clone), + path: path_std!(clone::Clone), additional_bounds: bounds, generics: LifetimeBounds::empty(), is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/cmp/eq.rs b/src/librustc_builtin_macros/deriving/cmp/eq.rs index e1677ae70ccab..b14f8a245b99e 100644 --- a/src/librustc_builtin_macros/deriving/cmp/eq.rs +++ b/src/librustc_builtin_macros/deriving/cmp/eq.rs @@ -22,7 +22,7 @@ pub fn expand_deriving_eq( let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(cx, cmp::Eq), + path: path_std!(cmp::Eq), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, @@ -47,7 +47,7 @@ pub fn expand_deriving_eq( cx, span, item, - path_std!(cx, marker::StructuralEq), + path_std!(marker::StructuralEq), push, ); diff --git a/src/librustc_builtin_macros/deriving/cmp/ord.rs b/src/librustc_builtin_macros/deriving/cmp/ord.rs index a9bc03db8b706..06ef7826b6452 100644 --- a/src/librustc_builtin_macros/deriving/cmp/ord.rs +++ b/src/librustc_builtin_macros/deriving/cmp/ord.rs @@ -20,7 +20,7 @@ pub fn expand_deriving_ord( let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(cx, cmp::Ord), + path: path_std!(cmp::Ord), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, @@ -30,7 +30,7 @@ pub fn expand_deriving_ord( generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![(borrowed_self(), "other")], - ret_ty: Literal(path_std!(cx, cmp::Ordering)), + ret_ty: Literal(path_std!(cmp::Ordering)), attributes: attrs, is_unsafe: false, unify_fieldless_variants: true, diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs index e7d8f78118098..3c209a66790c7 100644 --- a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs +++ b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs @@ -85,7 +85,7 @@ pub fn expand_deriving_partial_eq( cx, span, item, - path_std!(cx, marker::StructuralPartialEq), + path_std!(marker::StructuralPartialEq), push, ); @@ -100,7 +100,7 @@ pub fn expand_deriving_partial_eq( let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(cx, cmp::PartialEq), + path: path_std!(cmp::PartialEq), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs index a3eb96fb782e5..e9afacbe4b5c5 100644 --- a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs +++ b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs @@ -37,9 +37,9 @@ pub fn expand_deriving_partial_ord( }}; } - let ordering_ty = Literal(path_std!(cx, cmp::Ordering)); + let ordering_ty = Literal(path_std!(cmp::Ordering)); let ret_ty = Literal(Path::new_( - pathvec_std!(cx, option::Option), + pathvec_std!(option::Option), None, vec![Box::new(ordering_ty)], PathKind::Std, @@ -80,7 +80,7 @@ pub fn expand_deriving_partial_ord( let trait_def = TraitDef { span, attributes: vec![], - path: path_std!(cx, cmp::PartialOrd), + path: path_std!(cmp::PartialOrd), additional_bounds: vec![], generics: LifetimeBounds::empty(), is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/debug.rs b/src/librustc_builtin_macros/deriving/debug.rs index 6befeb746bd6d..29badee4e4a2f 100644 --- a/src/librustc_builtin_macros/deriving/debug.rs +++ b/src/librustc_builtin_macros/deriving/debug.rs @@ -18,12 +18,12 @@ pub fn expand_deriving_debug( ) { // &mut ::std::fmt::Formatter let fmtr = - Ptr(Box::new(Literal(path_std!(cx, fmt::Formatter))), Borrowed(None, ast::Mutability::Mut)); + Ptr(Box::new(Literal(path_std!(fmt::Formatter))), Borrowed(None, ast::Mutability::Mut)); let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(cx, fmt::Debug), + path: path_std!(fmt::Debug), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, @@ -33,7 +33,7 @@ pub fn expand_deriving_debug( generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![(fmtr, "f")], - ret_ty: Literal(path_std!(cx, fmt::Result)), + ret_ty: Literal(path_std!(fmt::Result)), attributes: Vec::new(), is_unsafe: false, unify_fieldless_variants: false, diff --git a/src/librustc_builtin_macros/deriving/decodable.rs b/src/librustc_builtin_macros/deriving/decodable.rs index 0792be7326331..9d6177c6c99c2 100644 --- a/src/librustc_builtin_macros/deriving/decodable.rs +++ b/src/librustc_builtin_macros/deriving/decodable.rs @@ -44,7 +44,7 @@ pub fn expand_deriving_rustc_decodable( "d", )], ret_ty: Literal(Path::new_( - pathvec_std!(cx, result::Result), + pathvec_std!(result::Result), None, vec![ Box::new(Self_), diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs index 5dfb0e8f37c63..54a64edeac349 100644 --- a/src/librustc_builtin_macros/deriving/default.rs +++ b/src/librustc_builtin_macros/deriving/default.rs @@ -21,7 +21,7 @@ pub fn expand_deriving_default( let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(cx, default::Default), + path: path_std!(default::Default), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/encodable.rs b/src/librustc_builtin_macros/deriving/encodable.rs index 4a90b7a193886..e6dffc6db1dc7 100644 --- a/src/librustc_builtin_macros/deriving/encodable.rs +++ b/src/librustc_builtin_macros/deriving/encodable.rs @@ -128,7 +128,7 @@ pub fn expand_deriving_rustc_encodable( "s", )], ret_ty: Literal(Path::new_( - pathvec_std!(cx, result::Result), + pathvec_std!(result::Result), None, vec![ Box::new(Tuple(Vec::new())), diff --git a/src/librustc_builtin_macros/deriving/hash.rs b/src/librustc_builtin_macros/deriving/hash.rs index f975b75f0be13..5c8a5501a208e 100644 --- a/src/librustc_builtin_macros/deriving/hash.rs +++ b/src/librustc_builtin_macros/deriving/hash.rs @@ -15,7 +15,7 @@ pub fn expand_deriving_hash( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std); + let path = Path::new_(pathvec_std!(hash::Hash), None, vec![], PathKind::Std); let typaram = "__H"; @@ -32,7 +32,7 @@ pub fn expand_deriving_hash( name: sym::hash, generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec![(typaram, vec![path_std!(cx, hash::Hasher)])], + bounds: vec![(typaram, vec![path_std!(hash::Hasher)])], }, explicit_self: borrowed_explicit_self(), args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), "state")], diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs index 6cee21fc6e69d..777640035677a 100644 --- a/src/librustc_builtin_macros/deriving/mod.rs +++ b/src/librustc_builtin_macros/deriving/mod.rs @@ -10,7 +10,7 @@ macro path_local($x:ident) { generic::ty::Path::new_local(stringify!($x)) } -macro pathvec_std($cx:expr, $($rest:ident)::+) {{ +macro pathvec_std($($rest:ident)::+) {{ vec![ $( stringify!($rest) ),+ ] }} From bccff14a2084784d70bb3caefb24f1694212c0b4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 Jul 2020 16:19:44 +1000 Subject: [PATCH 27/50] Simplify `LifetimeBounds`. The `lifetimes` field is always empty. This commit removes it, and renames the type as `Bounds`. --- .../deriving/bounds.rs | 2 +- src/librustc_builtin_macros/deriving/clone.rs | 4 ++-- .../deriving/cmp/eq.rs | 12 +++------- .../deriving/cmp/ord.rs | 4 ++-- .../deriving/cmp/partial_eq.rs | 4 ++-- .../deriving/cmp/partial_ord.rs | 6 ++--- src/librustc_builtin_macros/deriving/debug.rs | 4 ++-- .../deriving/decodable.rs | 5 ++-- .../deriving/default.rs | 4 ++-- .../deriving/encodable.rs | 5 ++-- .../deriving/generic/mod.rs | 6 ++--- .../deriving/generic/ty.rs | 23 +++++++------------ src/librustc_builtin_macros/deriving/hash.rs | 7 ++---- 13 files changed, 34 insertions(+), 52 deletions(-) diff --git a/src/librustc_builtin_macros/deriving/bounds.rs b/src/librustc_builtin_macros/deriving/bounds.rs index 86e875934780d..cef0da60a61c8 100644 --- a/src/librustc_builtin_macros/deriving/bounds.rs +++ b/src/librustc_builtin_macros/deriving/bounds.rs @@ -18,7 +18,7 @@ pub fn expand_deriving_copy( attributes: Vec::new(), path: path_std!(marker::Copy), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: true, methods: Vec::new(), diff --git a/src/librustc_builtin_macros/deriving/clone.rs b/src/librustc_builtin_macros/deriving/clone.rs index 471894828f594..b307ee26c91d5 100644 --- a/src/librustc_builtin_macros/deriving/clone.rs +++ b/src/librustc_builtin_macros/deriving/clone.rs @@ -80,12 +80,12 @@ pub fn expand_deriving_clone( attributes: Vec::new(), path: path_std!(clone::Clone), additional_bounds: bounds, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: true, methods: vec![MethodDef { name: sym::clone, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), args: Vec::new(), ret_ty: Self_, diff --git a/src/librustc_builtin_macros/deriving/cmp/eq.rs b/src/librustc_builtin_macros/deriving/cmp/eq.rs index b14f8a245b99e..d1b799cd6a112 100644 --- a/src/librustc_builtin_macros/deriving/cmp/eq.rs +++ b/src/librustc_builtin_macros/deriving/cmp/eq.rs @@ -24,12 +24,12 @@ pub fn expand_deriving_eq( attributes: Vec::new(), path: path_std!(cmp::Eq), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: true, methods: vec![MethodDef { name: sym::assert_receiver_is_total_eq, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![], ret_ty: nil_ty(), @@ -43,13 +43,7 @@ pub fn expand_deriving_eq( associated_types: Vec::new(), }; - super::inject_impl_of_structural_trait( - cx, - span, - item, - path_std!(marker::StructuralEq), - push, - ); + super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push); trait_def.expand_ext(cx, mitem, item, push, true) } diff --git a/src/librustc_builtin_macros/deriving/cmp/ord.rs b/src/librustc_builtin_macros/deriving/cmp/ord.rs index 06ef7826b6452..a4009f9f58b8d 100644 --- a/src/librustc_builtin_macros/deriving/cmp/ord.rs +++ b/src/librustc_builtin_macros/deriving/cmp/ord.rs @@ -22,12 +22,12 @@ pub fn expand_deriving_ord( attributes: Vec::new(), path: path_std!(cmp::Ord), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::cmp, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![(borrowed_self(), "other")], ret_ty: Literal(path_std!(cmp::Ordering)), diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs index 3c209a66790c7..d0676d8d8235e 100644 --- a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs +++ b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs @@ -69,7 +69,7 @@ pub fn expand_deriving_partial_eq( let attrs = vec![cx.attribute(inline)]; MethodDef { name: $name, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![(borrowed_self(), "other")], ret_ty: Literal(path_local!(bool)), @@ -102,7 +102,7 @@ pub fn expand_deriving_partial_eq( attributes: Vec::new(), path: path_std!(cmp::PartialEq), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods, diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs index e9afacbe4b5c5..e562c6c4092ff 100644 --- a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs +++ b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs @@ -23,7 +23,7 @@ pub fn expand_deriving_partial_ord( let attrs = vec![cx.attribute(inline)]; MethodDef { name: $name, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![(borrowed_self(), "other")], ret_ty: Literal(path_local!(bool)), @@ -50,7 +50,7 @@ pub fn expand_deriving_partial_ord( let partial_cmp_def = MethodDef { name: sym::partial_cmp, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![(borrowed_self(), "other")], ret_ty, @@ -82,7 +82,7 @@ pub fn expand_deriving_partial_ord( attributes: vec![], path: path_std!(cmp::PartialOrd), additional_bounds: vec![], - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods, diff --git a/src/librustc_builtin_macros/deriving/debug.rs b/src/librustc_builtin_macros/deriving/debug.rs index 29badee4e4a2f..830eeb87f8d8f 100644 --- a/src/librustc_builtin_macros/deriving/debug.rs +++ b/src/librustc_builtin_macros/deriving/debug.rs @@ -25,12 +25,12 @@ pub fn expand_deriving_debug( attributes: Vec::new(), path: path_std!(fmt::Debug), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::fmt, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![(fmtr, "f")], ret_ty: Literal(path_std!(fmt::Result)), diff --git a/src/librustc_builtin_macros/deriving/decodable.rs b/src/librustc_builtin_macros/deriving/decodable.rs index 9d6177c6c99c2..f5139d95a4c61 100644 --- a/src/librustc_builtin_macros/deriving/decodable.rs +++ b/src/librustc_builtin_macros/deriving/decodable.rs @@ -26,13 +26,12 @@ pub fn expand_deriving_rustc_decodable( attributes: Vec::new(), path: Path::new_(vec![krate, "Decodable"], None, vec![], PathKind::Global), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::decode, - generics: LifetimeBounds { - lifetimes: Vec::new(), + generics: Bounds { bounds: vec![( typaram, vec![Path::new_(vec![krate, "Decoder"], None, vec![], PathKind::Global)], diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs index 54a64edeac349..f8d9c76d372d8 100644 --- a/src/librustc_builtin_macros/deriving/default.rs +++ b/src/librustc_builtin_macros/deriving/default.rs @@ -23,12 +23,12 @@ pub fn expand_deriving_default( attributes: Vec::new(), path: path_std!(default::Default), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: kw::Default, - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), explicit_self: None, args: Vec::new(), ret_ty: Self_, diff --git a/src/librustc_builtin_macros/deriving/encodable.rs b/src/librustc_builtin_macros/deriving/encodable.rs index e6dffc6db1dc7..cbb263989e6fa 100644 --- a/src/librustc_builtin_macros/deriving/encodable.rs +++ b/src/librustc_builtin_macros/deriving/encodable.rs @@ -110,13 +110,12 @@ pub fn expand_deriving_rustc_encodable( attributes: Vec::new(), path: Path::new_(vec![krate, "Encodable"], None, vec![], PathKind::Global), additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::encode, - generics: LifetimeBounds { - lifetimes: Vec::new(), + generics: Bounds { bounds: vec![( typaram, vec![Path::new_(vec![krate, "Encoder"], None, vec![], PathKind::Global)], diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 050774aa24c96..be8eaa883eb33 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -191,7 +191,7 @@ use rustc_span::source_map::respan; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; -use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; +use ty::{Bounds, Path, Ptr, PtrTy, Self_, Ty}; use crate::deriving; @@ -211,7 +211,7 @@ pub struct TraitDef<'a> { pub additional_bounds: Vec>, /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder` - pub generics: LifetimeBounds<'a>, + pub generics: Bounds<'a>, /// Is it an `unsafe` trait? pub is_unsafe: bool, @@ -228,7 +228,7 @@ pub struct MethodDef<'a> { /// name of the method pub name: Symbol, /// List of generics, e.g., `R: rand::Rng` - pub generics: LifetimeBounds<'a>, + pub generics: Bounds<'a>, /// Whether there is a self argument (outer Option) i.e., whether /// this is a static function, and whether it is a pointer (inner diff --git a/src/librustc_builtin_macros/deriving/generic/ty.rs b/src/librustc_builtin_macros/deriving/generic/ty.rs index 609feb6f259d6..a031e4b649fa1 100644 --- a/src/librustc_builtin_macros/deriving/generic/ty.rs +++ b/src/librustc_builtin_macros/deriving/generic/ty.rs @@ -223,16 +223,15 @@ fn mk_generics(params: Vec, span: Span) -> Generics { } } -/// Lifetimes and bounds on type parameters +/// Bounds on type parameters. #[derive(Clone)] -pub struct LifetimeBounds<'a> { - pub lifetimes: Vec<(&'a str, Vec<&'a str>)>, +pub struct Bounds<'a> { pub bounds: Vec<(&'a str, Vec>)>, } -impl<'a> LifetimeBounds<'a> { - pub fn empty() -> LifetimeBounds<'a> { - LifetimeBounds { lifetimes: Vec::new(), bounds: Vec::new() } +impl<'a> Bounds<'a> { + pub fn empty() -> Bounds<'a> { + Bounds { bounds: Vec::new() } } pub fn to_generics( &self, @@ -242,18 +241,12 @@ impl<'a> LifetimeBounds<'a> { self_generics: &Generics, ) -> Generics { let generic_params = self - .lifetimes + .bounds .iter() - .map(|&(lt, ref bounds)| { - let bounds = bounds - .iter() - .map(|b| ast::GenericBound::Outlives(cx.lifetime(span, Ident::from_str(b)))); - cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds.collect()) - }) - .chain(self.bounds.iter().map(|t| { + .map(|t| { let (name, ref bounds) = *t; mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics) - })) + }) .collect(); mk_generics(generic_params, span) diff --git a/src/librustc_builtin_macros/deriving/hash.rs b/src/librustc_builtin_macros/deriving/hash.rs index 5c8a5501a208e..34e04a202696a 100644 --- a/src/librustc_builtin_macros/deriving/hash.rs +++ b/src/librustc_builtin_macros/deriving/hash.rs @@ -25,15 +25,12 @@ pub fn expand_deriving_hash( attributes: Vec::new(), path, additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), + generics: Bounds::empty(), is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::hash, - generics: LifetimeBounds { - lifetimes: Vec::new(), - bounds: vec![(typaram, vec![path_std!(hash::Hasher)])], - }, + generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] }, explicit_self: borrowed_explicit_self(), args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), "state")], ret_ty: nil_ty(), From 5271e98f4e8cf2e74e9b01fc2494ea9e90b08194 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 6 Jun 2020 17:19:21 -0400 Subject: [PATCH 28/50] Use get_module instead of `module_map` for `resolve_str_path_error` --- src/librustc_resolve/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c3686ca4899bc..0f2559e4b192e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2998,7 +2998,7 @@ impl<'a> Resolver<'a> { .collect(), } }; - let module = self.module_map.get(&module_id).copied().unwrap_or(self.graph_root); + let module = self.get_module(module_id.to_def_id()); let parent_scope = &ParentScope::module(module); let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; Ok((path, res)) From 848a766e24b799d27e7ae7479cd1f8c07047a53e Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 6 Jun 2020 13:09:05 -0400 Subject: [PATCH 29/50] Use the scope of the imported variable for resolution, not the current scope - Accept DefId in resolve_str_path_error This will probably break lots of internal invariants. --- src/librustc_resolve/lib.rs | 4 +- src/librustdoc/core.rs | 2 +- .../passes/collect_intra_doc_links.rs | 96 ++++++++++++++++++- 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0f2559e4b192e..686385e24ece8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2978,7 +2978,7 @@ impl<'a> Resolver<'a> { span: Span, path_str: &str, ns: Namespace, - module_id: LocalDefId, + module_id: DefId, ) -> Result<(ast::Path, Res), ()> { let path = if path_str.starts_with("::") { ast::Path { @@ -2998,7 +2998,7 @@ impl<'a> Resolver<'a> { .collect(), } }; - let module = self.get_module(module_id.to_def_id()); + let module = self.get_module(module_id); let parent_scope = &ParentScope::module(module); let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; Ok((path, res)) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 00315675fafe3..6a52974534f8b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -430,7 +430,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt DUMMY_SP, extern_name, TypeNS, - LocalDefId { local_def_index: CRATE_DEF_INDEX }, + LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(), ) .unwrap_or_else(|()| { panic!("Unable to resolve external crate {}", extern_name) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f707c1a3e1a10..fce7096a1af76 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { &self, path_str: &str, current_item: &Option, - module_id: LocalDefId, + module_id: DefId, ) -> Result<(Res, Option), ErrorKind> { let cx = self.cx; @@ -167,15 +167,103 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { disambiguator: Option<&str>, ns: Namespace, current_item: &Option, - parent_id: Option, + mut parent_id: Option, extra_fragment: &Option, item_opt: Option<&Item>, ) -> Result<(Res, Option), ErrorKind> { + use rustc_hir::{ItemKind, UseKind}; + let cx = self.cx; + // In case this is a re-export, try to resolve the docs relative to the original module. + // Since we don't document `use` statements, + // we don't have to consider the case where an item is documented in both the original module and the current module. + let mut module_id = None; + if let Some(item) = item_opt { + if let ItemEnum::ImportItem(import) = &item.inner { + if let Import::Simple(_, source) = import { + if let Some(def_id) = source.did { + use crate::rustc_middle::ty::DefIdTree; + + //let mut current_id = def_id; + if cx.tcx.def_kind(def_id) == DefKind::Mod { + module_id = Some(def_id); + debug!("found parent module {:?} for use statement", def_id); + //break; + } else { + debug!( + "not a module: {:?} (maybe an associated item?)", + cx.tcx.def_kind(def_id) + ); + } + + /* + // For associated items, the parent module might be multiple nodes above + while let Some(parent) = cx.tcx.parent(current_id) { + if cx.tcx.def_kind(parent) == DefKind::Mod { + parent_id = Some(parent); + debug!("found parent module {:?} for use statement", parent); + break; + } + current_id = parent; + } + */ + } else { + debug!("no def id found"); + } + } else { + debug!("glob imports not handled for intra-doc links"); + } + } + /* + if let Some(reexport) = item.reexport { + use crate::rustc_middle::ty::DefIdTree; + + let mut current_id = reexport; + // For associated items, the parent module might be multiple nodes above + while let Some(parent) = cx.tcx.parent(current_id) { + if cx.tcx.def_kind(parent) == DefKind::Mod { + parent_id = Some(parent); + debug!("found parent module {:?} for use statement", parent); + break; + } + current_id = parent; + } + } + */ + /* + if let ItemKind::Use(path, use_kind) = item.kind { + if use_kind == UseKind::Single { + match path.res { + Res::Def(def_kind, def_id) => { + use crate::rustc_middle::ty::DefIdTree; + + let mut current_id = def_id; + // For associated items, the parent module might be multiple nodes above + while let Some(parent) = cx.tcx.parent(current_id) { + if cx.tcx.def_kind(parent) == DefKind::Mod { + parent_id = Some(parent); + debug!("found parent module {:?} for use statement", parent); + break; + } + current_id = parent; + } + } + _ => debug!("use {:?} was not a definition, not treating as cross-crate", item.name), + } + } else { + debug!("don't know how to resolve multiple imports for {:?}, not treating as cross-crate", path); + } + } + */ + } + // In case we're in a module, try to resolve the relative path. - if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) { - let module_id = cx.tcx.hir().local_def_id(module_id); + if module_id.is_none() { + let id = parent_id.or(self.mod_ids.last().cloned()); + module_id = id.map(|id| cx.tcx.hir().local_def_id(id).to_def_id()); + } + if let Some(module_id) = module_id { let result = cx.enter_resolver(|resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) }); From 69bd13f233d2cf5ceaf358f69c8e0902f79be73c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 6 Jun 2020 23:06:21 -0400 Subject: [PATCH 30/50] Use DefId for modules --- .../passes/collect_intra_doc_links.rs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index fce7096a1af76..3c2e3eabf9f24 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -167,7 +167,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { disambiguator: Option<&str>, ns: Namespace, current_item: &Option, - mut parent_id: Option, + mut parent_id: Option, extra_fragment: &Option, item_opt: Option<&Item>, ) -> Result<(Res, Option), ErrorKind> { @@ -178,8 +178,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // In case this is a re-export, try to resolve the docs relative to the original module. // Since we don't document `use` statements, // we don't have to consider the case where an item is documented in both the original module and the current module. + /* let mut module_id = None; if let Some(item) = item_opt { + debug!("resolving {:?} with item kind {:?}", path_str, item.inner); if let ItemEnum::ImportItem(import) = &item.inner { if let Import::Simple(_, source) = import { if let Some(def_id) = source.did { @@ -214,6 +216,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } else { debug!("glob imports not handled for intra-doc links"); } + } else { + //debug!("item.inner not an import ({:?})", item.inner); } /* if let Some(reexport) = item.reexport { @@ -257,13 +261,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } */ } + */ // In case we're in a module, try to resolve the relative path. - if module_id.is_none() { - let id = parent_id.or(self.mod_ids.last().cloned()); - module_id = id.map(|id| cx.tcx.hir().local_def_id(id).to_def_id()); + if parent_id.is_none() { + let id = self.mod_ids.last().cloned(); + parent_id = id.map(|id| cx.tcx.hir().local_def_id(id).to_def_id()); } - if let Some(module_id) = module_id { + if let Some(module_id) = parent_id { let result = cx.enter_resolver(|resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) }); @@ -545,6 +550,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }; // FIXME: get the resolver to work with non-local resolve scopes. + use rustc_middle::ty::DefIdTree; + let parent_node = self.cx.tcx.parent(item.def_id); + /* let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| { // FIXME: this fails hard for impls in non-module scope, but is necessary for the // current `resolve()` implementation. @@ -553,6 +561,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { _ => None, } }); + */ if parent_node.is_some() { debug!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id); @@ -563,10 +572,10 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if item.attrs.inner_docs { if item_hir_id.unwrap() != hir::CRATE_HIR_ID { item.name.clone() } else { None } } else { - match parent_node.or(self.mod_ids.last().cloned()) { - Some(parent) if parent != hir::CRATE_HIR_ID => { + match parent_node.or(self.mod_ids.last().map(|&local| self.cx.tcx.hir().local_def_id(local).to_def_id())) { + Some(parent) if !parent.is_top_level_module() => { // FIXME: can we pull the parent module's name from elsewhere? - Some(self.cx.tcx.hir().name(parent).to_string()) + Some(self.cx.tcx.item_name(parent).to_string()) } _ => None, } From c3d9a730b748a3c8bf673b88a265faad67ec7d9d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 7 Jun 2020 13:05:01 -0400 Subject: [PATCH 31/50] Don't panic on fake IDs --- .../passes/collect_intra_doc_links.rs | 112 ++---------------- 1 file changed, 11 insertions(+), 101 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 3c2e3eabf9f24..65b852f1d619c 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -175,94 +175,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { let cx = self.cx; - // In case this is a re-export, try to resolve the docs relative to the original module. - // Since we don't document `use` statements, - // we don't have to consider the case where an item is documented in both the original module and the current module. - /* - let mut module_id = None; - if let Some(item) = item_opt { - debug!("resolving {:?} with item kind {:?}", path_str, item.inner); - if let ItemEnum::ImportItem(import) = &item.inner { - if let Import::Simple(_, source) = import { - if let Some(def_id) = source.did { - use crate::rustc_middle::ty::DefIdTree; - - //let mut current_id = def_id; - if cx.tcx.def_kind(def_id) == DefKind::Mod { - module_id = Some(def_id); - debug!("found parent module {:?} for use statement", def_id); - //break; - } else { - debug!( - "not a module: {:?} (maybe an associated item?)", - cx.tcx.def_kind(def_id) - ); - } - - /* - // For associated items, the parent module might be multiple nodes above - while let Some(parent) = cx.tcx.parent(current_id) { - if cx.tcx.def_kind(parent) == DefKind::Mod { - parent_id = Some(parent); - debug!("found parent module {:?} for use statement", parent); - break; - } - current_id = parent; - } - */ - } else { - debug!("no def id found"); - } - } else { - debug!("glob imports not handled for intra-doc links"); - } - } else { - //debug!("item.inner not an import ({:?})", item.inner); - } - /* - if let Some(reexport) = item.reexport { - use crate::rustc_middle::ty::DefIdTree; - - let mut current_id = reexport; - // For associated items, the parent module might be multiple nodes above - while let Some(parent) = cx.tcx.parent(current_id) { - if cx.tcx.def_kind(parent) == DefKind::Mod { - parent_id = Some(parent); - debug!("found parent module {:?} for use statement", parent); - break; - } - current_id = parent; - } - } - */ - /* - if let ItemKind::Use(path, use_kind) = item.kind { - if use_kind == UseKind::Single { - match path.res { - Res::Def(def_kind, def_id) => { - use crate::rustc_middle::ty::DefIdTree; - - let mut current_id = def_id; - // For associated items, the parent module might be multiple nodes above - while let Some(parent) = cx.tcx.parent(current_id) { - if cx.tcx.def_kind(parent) == DefKind::Mod { - parent_id = Some(parent); - debug!("found parent module {:?} for use statement", parent); - break; - } - current_id = parent; - } - } - _ => debug!("use {:?} was not a definition, not treating as cross-crate", item.name), - } - } else { - debug!("don't know how to resolve multiple imports for {:?}, not treating as cross-crate", path); - } - } - */ - } - */ - // In case we're in a module, try to resolve the relative path. if parent_id.is_none() { let id = self.mod_ids.last().cloned(); @@ -549,19 +461,13 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { None }; - // FIXME: get the resolver to work with non-local resolve scopes. use rustc_middle::ty::DefIdTree; - let parent_node = self.cx.tcx.parent(item.def_id); - /* - let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| { - // FIXME: this fails hard for impls in non-module scope, but is necessary for the - // current `resolve()` implementation. - match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id).to_def_id()).unwrap() { - id if id != hir_id => Some(id), - _ => None, - } - }); - */ + let parent_node = if item.is_fake() { + // FIXME: is this correct? + None + } else { + self.cx.tcx.parent(item.def_id) + }; if parent_node.is_some() { debug!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id); @@ -572,7 +478,11 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if item.attrs.inner_docs { if item_hir_id.unwrap() != hir::CRATE_HIR_ID { item.name.clone() } else { None } } else { - match parent_node.or(self.mod_ids.last().map(|&local| self.cx.tcx.hir().local_def_id(local).to_def_id())) { + match parent_node.or(self + .mod_ids + .last() + .map(|&local| self.cx.tcx.hir().local_def_id(local).to_def_id())) + { Some(parent) if !parent.is_top_level_module() => { // FIXME: can we pull the parent module's name from elsewhere? Some(self.cx.tcx.item_name(parent).to_string()) From 20106d5a2fda0f2fef97ce253e5d78d4cf030289 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 7 Jun 2020 13:45:02 -0400 Subject: [PATCH 32/50] unwrap() -> expect() --- src/librustc_resolve/build_reduced_graph.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 8db27babd058b..45253fc878222 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -111,12 +111,17 @@ impl<'a> Resolver<'a> { (self.cstore().crate_name_untracked(def_id.krate), None) } else { let def_key = self.cstore().def_key(def_id); - ( - // This unwrap is safe: crates must always have a name - def_key.disambiguated_data.data.get_opt_name().unwrap(), - // This unwrap is safe since we know this isn't the root - Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })), - ) + let name = def_key + .disambiguated_data + .data + .get_opt_name() + .expect("given a DefId that wasn't a module"); + // This unwrap is safe since we know this isn't the root + let parent = Some(self.get_module(DefId { + index: def_key.parent.expect("failed to get parent for module"), + ..def_id + })); + (name, parent) }; // Allocate and return a new module with the information we found From 24c3d85e66b0fd719d9ffa70ae5e56593cb9b644 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 7 Jun 2020 17:08:26 -0400 Subject: [PATCH 33/50] Make sure that module_id is actually a module --- src/librustdoc/passes/collect_intra_doc_links.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 65b852f1d619c..487a4a5b0a229 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -466,7 +466,19 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { // FIXME: is this correct? None } else { - self.cx.tcx.parent(item.def_id) + let mut current = item.def_id; + // The immediate parent might not always be a module. + // Find the first parent which is. + loop { + if let Some(parent) = self.cx.tcx.parent(current) { + if self.cx.tcx.def_kind(parent) == DefKind::Mod { + break Some(parent); + } + current = parent; + } else { + break None; + } + } }; if parent_node.is_some() { From 9542e23a7d915f50e84a048a5ed6aab34335ff52 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 7 Jun 2020 21:16:54 -0400 Subject: [PATCH 34/50] Add tests for basic intra-doc links --- .../rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs | 5 +++++ src/test/rustdoc/intra-doc-crate/basic.rs | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs create mode 100644 src/test/rustdoc/intra-doc-crate/basic.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs new file mode 100644 index 0000000000000..7f5609bcf5281 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs @@ -0,0 +1,5 @@ +#![crate_name = "a"] +pub struct Foo; + +/// Link to [Foo] +pub struct Bar; diff --git a/src/test/rustdoc/intra-doc-crate/basic.rs b/src/test/rustdoc/intra-doc-crate/basic.rs new file mode 100644 index 0000000000000..dd32908714f4f --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/basic.rs @@ -0,0 +1,6 @@ +// aux-build:intra-doc-basic.rs +// build-aux-docs +extern crate a; + +// @has 'basic/struct.Bar.html' '//a[@href="../a/struct.Foo.html"]' 'Foo' +pub use a::Bar; From 99f34d814e87e33e014433f791a13db3a3bd2273 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 7 Jun 2020 21:17:56 -0400 Subject: [PATCH 35/50] Remove warnings --- src/librustdoc/passes/collect_intra_doc_links.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 487a4a5b0a229..52518bcb631f1 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -8,7 +8,7 @@ use rustc_hir::def::{ Namespace::{self, *}, PerNS, Res, }; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_middle::ty; use rustc_resolve::ParentScope; use rustc_session::lint; @@ -171,8 +171,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { extra_fragment: &Option, item_opt: Option<&Item>, ) -> Result<(Res, Option), ErrorKind> { - use rustc_hir::{ItemKind, UseKind}; - let cx = self.cx; // In case we're in a module, try to resolve the relative path. From e78d499637761efceebf6f9cb8ab317a31541ec7 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 7 Jun 2020 21:48:31 -0400 Subject: [PATCH 36/50] Add test for re-exports I had a hard time getting this to work without the `extern crate`, suggestions are welcome. --- .../rustdoc/intra-doc-crate/auxiliary/submodule.rs | 12 ++++++++++++ src/test/rustdoc/intra-doc-crate/basic.rs | 2 ++ src/test/rustdoc/intra-doc-crate/submodule.rs | 14 ++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/submodule.rs create mode 100644 src/test/rustdoc/intra-doc-crate/submodule.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule.rs new file mode 100644 index 0000000000000..dfc8685f38428 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule.rs @@ -0,0 +1,12 @@ +#![crate_name = "bar"] + +pub trait Foo { + /// [`Bar`] [`Baz`] + fn foo(); +} + +pub trait Bar { +} + +pub trait Baz { +} diff --git a/src/test/rustdoc/intra-doc-crate/basic.rs b/src/test/rustdoc/intra-doc-crate/basic.rs index dd32908714f4f..3fb72b2b497f3 100644 --- a/src/test/rustdoc/intra-doc-crate/basic.rs +++ b/src/test/rustdoc/intra-doc-crate/basic.rs @@ -1,5 +1,7 @@ // aux-build:intra-doc-basic.rs // build-aux-docs + +// from https://github.com/rust-lang/rust/issues/65983 extern crate a; // @has 'basic/struct.Bar.html' '//a[@href="../a/struct.Foo.html"]' 'Foo' diff --git a/src/test/rustdoc/intra-doc-crate/submodule.rs b/src/test/rustdoc/intra-doc-crate/submodule.rs new file mode 100644 index 0000000000000..5caa220b570f1 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/submodule.rs @@ -0,0 +1,14 @@ +// aux-build:submodule.rs +// edition:2018 +extern crate bar as bar_; + +// from https://github.com/rust-lang/rust/issues/60883 +pub mod bar { + pub use ::bar_::Bar; +} + +// NOTE: we re-exported both `Foo` and `Bar` here, +// NOTE: so they are inlined and therefore we link to the current module. +// @has 'submodule/trait.Foo.html' '//a[@href="../submodule/bar/trait.Bar.html"]' 'Bar' +// @has 'submodule/trait.Foo.html' '//a[@href="../submodule/trait.Baz.html"]' 'Baz' +pub use ::bar_::{Foo, Baz}; From 9eb63945eb02b67e3edf4a7214c3148bffa49ed2 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 7 Jun 2020 22:11:03 -0400 Subject: [PATCH 37/50] Add test for documenting the re-export --- src/test/rustdoc/intra-doc-crate/additional_doc.rs | 8 ++++++++ .../rustdoc/intra-doc-crate/auxiliary/additional_doc.rs | 5 +++++ 2 files changed, 13 insertions(+) create mode 100644 src/test/rustdoc/intra-doc-crate/additional_doc.rs create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs diff --git a/src/test/rustdoc/intra-doc-crate/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/additional_doc.rs new file mode 100644 index 0000000000000..d72548b0e2de5 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/additional_doc.rs @@ -0,0 +1,8 @@ +// aux-build:additional_doc.rs +// build-aux-docs +extern crate rand; + +// @has 'additional_doc/trait.Rng.html' '//a[@href="../additional_doc/trait.Rng.html"]' 'Rng' +// @has 'additional_doc/trait.Rng.html' '//a[@href="../rand/trait.RngCore.html"]' 'RngCore' +/// This is an [`Rng`]. +pub use rand::Rng; diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs new file mode 100644 index 0000000000000..9d0a9882289e8 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs @@ -0,0 +1,5 @@ +#![crate_name = "rand"] + +pub trait RngCore {} +/// Rng extends [`RngCore`]. +pub trait Rng: RngCore {} From 71fe8f7cd8afa71892cb45046b11d0d3f53526a9 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 9 Jun 2020 20:12:01 -0400 Subject: [PATCH 38/50] Add test for submodules in inner crate --- .../intra-doc-crate/auxiliary/submodule-inner.rs | 11 +++++++++++ .../auxiliary/{submodule.rs => submodule-outer.rs} | 0 src/test/rustdoc/intra-doc-crate/submodule-inner.rs | 6 ++++++ .../{submodule.rs => submodule-outer.rs} | 6 +++--- 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs rename src/test/rustdoc/intra-doc-crate/auxiliary/{submodule.rs => submodule-outer.rs} (100%) create mode 100644 src/test/rustdoc/intra-doc-crate/submodule-inner.rs rename src/test/rustdoc/intra-doc-crate/{submodule.rs => submodule-outer.rs} (56%) diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs new file mode 100644 index 0000000000000..2258bb1956ce1 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs @@ -0,0 +1,11 @@ +#![crate_name = "a"] + +pub mod bar { + pub struct Bar; +} + +pub mod foo { + use crate::bar; + /// link to [bar::Bar] + pub struct Foo; +} diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/submodule.rs rename to src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs diff --git a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs new file mode 100644 index 0000000000000..ab508c8792d3d --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs @@ -0,0 +1,6 @@ +// aux-build:submodule-inner.rs +// build-aux-docs +extern crate a; + +// @has 'submodule_inner/struct.Foo.html' '//a[@href="../a/bar/struct.Bar.html"]' 'Bar' +pub use a::foo::Foo; diff --git a/src/test/rustdoc/intra-doc-crate/submodule.rs b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs similarity index 56% rename from src/test/rustdoc/intra-doc-crate/submodule.rs rename to src/test/rustdoc/intra-doc-crate/submodule-outer.rs index 5caa220b570f1..3ce92cacfc247 100644 --- a/src/test/rustdoc/intra-doc-crate/submodule.rs +++ b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs @@ -1,4 +1,4 @@ -// aux-build:submodule.rs +// aux-build:submodule-outer.rs // edition:2018 extern crate bar as bar_; @@ -9,6 +9,6 @@ pub mod bar { // NOTE: we re-exported both `Foo` and `Bar` here, // NOTE: so they are inlined and therefore we link to the current module. -// @has 'submodule/trait.Foo.html' '//a[@href="../submodule/bar/trait.Bar.html"]' 'Bar' -// @has 'submodule/trait.Foo.html' '//a[@href="../submodule/trait.Baz.html"]' 'Baz' +// @has 'submodule_outer/trait.Foo.html' '//a[@href="../submodule_outer/bar/trait.Bar.html"]' 'Bar' +// @has 'submodule_outer/trait.Foo.html' '//a[@href="../submodule_outer/trait.Baz.html"]' 'Baz' pub use ::bar_::{Foo, Baz}; From 432b0431ab0f087a6511c1f8b71c3837cb62237e Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 9 Jun 2020 21:00:06 -0400 Subject: [PATCH 39/50] Move import to top of function --- src/librustdoc/passes/collect_intra_doc_links.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 52518bcb631f1..3cbbb58353bba 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -448,6 +448,8 @@ fn is_derive_trait_collision(ns: &PerNS>) -> bool { impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { fn fold_item(&mut self, mut item: Item) -> Option { + use rustc_middle::ty::DefIdTree; + let item_hir_id = if item.is_mod() { if let Some(def_id) = item.def_id.as_local() { Some(self.cx.tcx.hir().as_local_hir_id(def_id)) @@ -459,7 +461,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { None }; - use rustc_middle::ty::DefIdTree; let parent_node = if item.is_fake() { // FIXME: is this correct? None From 769acbaca056aaa4b8ebbf5963806d1a3ee7a9f0 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 10 Jun 2020 08:56:44 -0400 Subject: [PATCH 40/50] #![deny(intra_doc_resolution_failure)] --- src/test/rustdoc/intra-doc-crate/additional_doc.rs | 2 ++ src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs | 1 + src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs | 2 ++ src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs | 1 + src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs | 1 + src/test/rustdoc/intra-doc-crate/basic.rs | 1 + src/test/rustdoc/intra-doc-crate/submodule-inner.rs | 2 ++ src/test/rustdoc/intra-doc-crate/submodule-outer.rs | 2 ++ 8 files changed, 12 insertions(+) diff --git a/src/test/rustdoc/intra-doc-crate/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/additional_doc.rs index d72548b0e2de5..95df8a781d29a 100644 --- a/src/test/rustdoc/intra-doc-crate/additional_doc.rs +++ b/src/test/rustdoc/intra-doc-crate/additional_doc.rs @@ -1,5 +1,7 @@ // aux-build:additional_doc.rs // build-aux-docs +#![deny(intra_doc_resolution_failure)] + extern crate rand; // @has 'additional_doc/trait.Rng.html' '//a[@href="../additional_doc/trait.Rng.html"]' 'Rng' diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs index 9d0a9882289e8..46aca95095fd2 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs @@ -1,4 +1,5 @@ #![crate_name = "rand"] +#![deny(intra_doc_resolution_failure)] pub trait RngCore {} /// Rng extends [`RngCore`]. diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs index 7f5609bcf5281..8c83633424fd9 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs @@ -1,4 +1,6 @@ #![crate_name = "a"] +#![deny(intra_doc_resolution_failure)] + pub struct Foo; /// Link to [Foo] diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs index 2258bb1956ce1..73073ebff1406 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs @@ -1,4 +1,5 @@ #![crate_name = "a"] +#![deny(intra_doc_resolution_failure)] pub mod bar { pub struct Bar; diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs index dfc8685f38428..c045d6488f46d 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs @@ -1,4 +1,5 @@ #![crate_name = "bar"] +#![deny(intra_doc_resolution_failure)] pub trait Foo { /// [`Bar`] [`Baz`] diff --git a/src/test/rustdoc/intra-doc-crate/basic.rs b/src/test/rustdoc/intra-doc-crate/basic.rs index 3fb72b2b497f3..6b6757b94e36a 100644 --- a/src/test/rustdoc/intra-doc-crate/basic.rs +++ b/src/test/rustdoc/intra-doc-crate/basic.rs @@ -1,5 +1,6 @@ // aux-build:intra-doc-basic.rs // build-aux-docs +#![deny(intra_doc_resolution_failure)] // from https://github.com/rust-lang/rust/issues/65983 extern crate a; diff --git a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs index ab508c8792d3d..e83d258c1df35 100644 --- a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs +++ b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs @@ -1,5 +1,7 @@ // aux-build:submodule-inner.rs // build-aux-docs +#![deny(intra_doc_resolution_failure)] + extern crate a; // @has 'submodule_inner/struct.Foo.html' '//a[@href="../a/bar/struct.Bar.html"]' 'Bar' diff --git a/src/test/rustdoc/intra-doc-crate/submodule-outer.rs b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs index 3ce92cacfc247..ccf226e1dfd03 100644 --- a/src/test/rustdoc/intra-doc-crate/submodule-outer.rs +++ b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs @@ -1,5 +1,7 @@ // aux-build:submodule-outer.rs // edition:2018 +#![deny(intra_doc_resolution_failure)] + extern crate bar as bar_; // from https://github.com/rust-lang/rust/issues/60883 From 5f49f55eb4fc73dc89ab80c124b9eb158e51f57b Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 10 Jun 2020 10:30:33 -0400 Subject: [PATCH 41/50] rand -> my_rand This fixes a failure in stage2 rustdoc tests. --- src/test/rustdoc/intra-doc-crate/additional_doc.rs | 6 +++--- .../rustdoc/intra-doc-crate/auxiliary/additional_doc.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc/intra-doc-crate/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/additional_doc.rs index 95df8a781d29a..dc1d85c9941f9 100644 --- a/src/test/rustdoc/intra-doc-crate/additional_doc.rs +++ b/src/test/rustdoc/intra-doc-crate/additional_doc.rs @@ -2,9 +2,9 @@ // build-aux-docs #![deny(intra_doc_resolution_failure)] -extern crate rand; +extern crate my_rand; // @has 'additional_doc/trait.Rng.html' '//a[@href="../additional_doc/trait.Rng.html"]' 'Rng' -// @has 'additional_doc/trait.Rng.html' '//a[@href="../rand/trait.RngCore.html"]' 'RngCore' +// @has 'additional_doc/trait.Rng.html' '//a[@href="../my_rand/trait.RngCore.html"]' 'RngCore' /// This is an [`Rng`]. -pub use rand::Rng; +pub use my_rand::Rng; diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs index 46aca95095fd2..353689a6d0db2 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs @@ -1,4 +1,4 @@ -#![crate_name = "rand"] +#![crate_name = "my_rand"] #![deny(intra_doc_resolution_failure)] pub trait RngCore {} From e63e5cdab02659beec0fd4a50d4b2556b7d6500d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 11 Jun 2020 22:58:09 -0400 Subject: [PATCH 42/50] Support intra-doc links on macro re-exports This includes both `macro_rules!` and proc-macros. --- .../passes/collect_intra_doc_links.rs | 18 ++++++++--------- .../intra-doc-crate/auxiliary/macro_inner.rs | 10 ++++++++++ .../intra-doc-crate/auxiliary/proc_macro.rs | 20 +++++++++++++++++++ src/test/rustdoc/intra-doc-crate/macro.rs | 12 +++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/proc_macro.rs create mode 100644 src/test/rustdoc/intra-doc-crate/macro.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 3cbbb58353bba..fa0cbea1d8062 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -124,7 +124,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } /// Resolves a string as a macro. - fn macro_resolve(&self, path_str: &str, parent_id: Option) -> Option { + fn macro_resolve(&self, path_str: &str, parent_id: Option) -> Option { let cx = self.cx; let path = ast::Path::from_ident(Ident::from_str(path_str)); cx.enter_resolver(|resolver| { @@ -142,8 +142,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) { return Some(res.map_id(|_| panic!("unexpected id"))); } - if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) { - let module_id = cx.tcx.hir().local_def_id(module_id); + if let Some(module_id) = parent_id { if let Ok((_, res)) = resolver.resolve_str_path_error(DUMMY_SP, path_str, MacroNS, module_id) { @@ -167,17 +166,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { disambiguator: Option<&str>, ns: Namespace, current_item: &Option, - mut parent_id: Option, + parent_id: Option, extra_fragment: &Option, item_opt: Option<&Item>, ) -> Result<(Res, Option), ErrorKind> { let cx = self.cx; // In case we're in a module, try to resolve the relative path. - if parent_id.is_none() { - let id = self.mod_ids.last().cloned(); - parent_id = id.map(|id| cx.tcx.hir().local_def_id(id).to_def_id()); - } if let Some(module_id) = parent_id { let result = cx.enter_resolver(|resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) @@ -659,8 +654,11 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { // we've already pushed this node onto the resolution stack but // for outer comments we explicitly try and resolve against the // parent_node first. - let base_node = - if item.is_mod() && item.attrs.inner_docs { None } else { parent_node }; + let base_node = if item.is_mod() && item.attrs.inner_docs { + self.mod_ids.last().map(|&id| self.cx.tcx.hir().local_def_id(id).to_def_id()) + } else { + parent_node + }; // replace `Self` with suitable item's parent name if path_str.starts_with("Self::") { diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs new file mode 100644 index 0000000000000..e54539f0bc5df --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs @@ -0,0 +1,10 @@ +#![crate_name = "macro_inner"] +#![deny(intra_doc_resolution_failure)] + +pub struct Foo; + +/// See also [`Foo`] +#[macro_export] +macro_rules! my_macro { + () => {} +} diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/proc_macro.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/proc_macro.rs new file mode 100644 index 0000000000000..0d5a954075df2 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/proc_macro.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic +// compile-flags: --crate-type proc-macro +#![crate_type="proc-macro"] +#![crate_name="proc_macro_inner"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +/// Links to [`OtherDerive`] +#[proc_macro_derive(DeriveA)] +pub fn a_derive(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(OtherDerive)] +pub fn other_derive(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/rustdoc/intra-doc-crate/macro.rs b/src/test/rustdoc/intra-doc-crate/macro.rs new file mode 100644 index 0000000000000..5c8cec128dfa0 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/macro.rs @@ -0,0 +1,12 @@ +// ignore-tidy-linelength +// aux-build:macro_inner.rs +// aux-build:proc_macro.rs +// build-aux-docs +#![deny(intra_doc_resolution_failure)] +extern crate macro_inner; +extern crate proc_macro_inner; + +// @has 'macro/macro.my_macro.html' '//a[@href="../macro_inner/struct.Foo.html"]' 'Foo' +pub use macro_inner::my_macro; +// @has 'macro/derive.DeriveA.html' '//a[@href="../proc_macro_inner/derive.OtherDerive.html"]' 'OtherDerive' +pub use proc_macro_inner::DeriveA; From 82b3b0705bfe67ab1565505ae1422f9302e12b6e Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 11 Jul 2020 13:28:05 -0400 Subject: [PATCH 43/50] Support intra-doc links on trait and module re-exports Trait implementations are treated the same as modules for the purposes of intra-doc links. --- .../passes/collect_intra_doc_links.rs | 28 +++++-------------- .../intra-doc-crate/auxiliary/module.rs | 7 +++++ .../intra-doc-crate/auxiliary/traits.rs | 16 +++++++++++ src/test/rustdoc/intra-doc-crate/module.rs | 8 ++++++ src/test/rustdoc/intra-doc-crate/traits.rs | 15 ++++++++++ 5 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/module.rs create mode 100644 src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs create mode 100644 src/test/rustdoc/intra-doc-crate/module.rs create mode 100644 src/test/rustdoc/intra-doc-crate/traits.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index fa0cbea1d8062..76b731f62f3db 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -50,7 +50,8 @@ enum ErrorKind { struct LinkCollector<'a, 'tcx> { cx: &'a DocContext<'tcx>, - mod_ids: Vec, + // NOTE: this may not necessarily be a module in the current crate + mod_ids: Vec, } impl<'a, 'tcx> LinkCollector<'a, 'tcx> { @@ -445,17 +446,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { fn fold_item(&mut self, mut item: Item) -> Option { use rustc_middle::ty::DefIdTree; - let item_hir_id = if item.is_mod() { - if let Some(def_id) = item.def_id.as_local() { - Some(self.cx.tcx.hir().as_local_hir_id(def_id)) - } else { - debug!("attempting to fold on a non-local item: {:?}", item); - return self.fold_item_recur(item); - } - } else { - None - }; - let parent_node = if item.is_fake() { // FIXME: is this correct? None @@ -482,13 +472,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let current_item = match item.inner { ModuleItem(..) => { if item.attrs.inner_docs { - if item_hir_id.unwrap() != hir::CRATE_HIR_ID { item.name.clone() } else { None } + if item.def_id.is_top_level_module() { item.name.clone() } else { None } } else { - match parent_node.or(self - .mod_ids - .last() - .map(|&local| self.cx.tcx.hir().local_def_id(local).to_def_id())) - { + match parent_node.or(self.mod_ids.last().copied()) { Some(parent) if !parent.is_top_level_module() => { // FIXME: can we pull the parent module's name from elsewhere? Some(self.cx.tcx.item_name(parent).to_string()) @@ -508,7 +494,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }; if item.is_mod() && item.attrs.inner_docs { - self.mod_ids.push(item_hir_id.unwrap()); + self.mod_ids.push(item.def_id); } let cx = self.cx; @@ -655,7 +641,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { // for outer comments we explicitly try and resolve against the // parent_node first. let base_node = if item.is_mod() && item.attrs.inner_docs { - self.mod_ids.last().map(|&id| self.cx.tcx.hir().local_def_id(id).to_def_id()) + self.mod_ids.last().copied() } else { parent_node }; @@ -842,7 +828,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } if item.is_mod() && !item.attrs.inner_docs { - self.mod_ids.push(item_hir_id.unwrap()); + self.mod_ids.push(item.def_id); } if item.is_mod() { diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs new file mode 100644 index 0000000000000..5d63d7e37b64d --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs @@ -0,0 +1,7 @@ +#![crate_name = "module_inner"] +#![deny(intra_doc_link_resolution_failure)] +/// [SomeType] links to [bar] +pub struct SomeType; +pub trait SomeTrait {} +/// [bar] links to [SomeTrait] and also [SomeType] +pub mod bar {} diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs new file mode 100644 index 0000000000000..5c3360dc5fdb3 --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs @@ -0,0 +1,16 @@ +#![crate_name = "inner"] +/// this is a trait +pub trait SomeTrait { + /// this is a method for [SomeTrait] + fn foo(); +} + +pub mod bar { + use super::SomeTrait; + + pub struct BarStruct; + + impl SomeTrait for BarStruct { + fn foo() {} + } +} diff --git a/src/test/rustdoc/intra-doc-crate/module.rs b/src/test/rustdoc/intra-doc-crate/module.rs new file mode 100644 index 0000000000000..67fa7293f37fb --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/module.rs @@ -0,0 +1,8 @@ +// outer.rs +// aux-build: module.rs +// build-aux-docs +#![deny(intra_doc_link_resolution_failure)] +extern crate module_inner; +// @has 'module/bar/index.html' '//a[@href="../../module_inner/trait.SomeTrait.html"]' 'SomeTrait' +// @has 'module/bar/index.html' '//a[@href="../../module_inner/struct.SomeType.html"]' 'SomeType' +pub use module_inner::bar; diff --git a/src/test/rustdoc/intra-doc-crate/traits.rs b/src/test/rustdoc/intra-doc-crate/traits.rs new file mode 100644 index 0000000000000..0672c76435b9a --- /dev/null +++ b/src/test/rustdoc/intra-doc-crate/traits.rs @@ -0,0 +1,15 @@ +// aux-build:traits.rs +// build-aux-docs +// ignore-tidy-line-length +#![deny(intra_doc_link_resolution_failure)] + +extern crate inner; +use inner::SomeTrait; + +pub struct SomeStruct; + + // @has 'traits/struct.SomeStruct.html' '//a[@href="../inner/trait.SomeTrait.html"]' 'SomeTrait' +impl SomeTrait for SomeStruct { + // @has 'traits/struct.SomeStruct.html' '//a[@href="../inner/trait.SomeTrait.html"]' 'SomeTrait' + fn foo() {} +} From 0ad1dcd6a04759a20b72debae5b114751fe6c7ff Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 12 Jul 2020 12:39:11 -0400 Subject: [PATCH 44/50] Add more debugging --- src/librustdoc/passes/collect_intra_doc_links.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 76b731f62f3db..b1db1328392e7 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -466,7 +466,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }; if parent_node.is_some() { - debug!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id); + trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id); } let current_item = match item.inner { @@ -487,7 +487,10 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { for_.def_id().map(|did| self.cx.tcx.item_name(did).to_string()) } // we don't display docs on `extern crate` items anyway, so don't process them. - ExternCrateItem(..) => return self.fold_item_recur(item), + ExternCrateItem(..) => { + debug!("ignoring extern crate item {:?}", item.def_id); + return self.fold_item_recur(item); + } ImportItem(Import::Simple(ref name, ..)) => Some(name.clone()), MacroItem(..) => None, _ => item.name.clone(), @@ -499,6 +502,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let cx = self.cx; let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new); + trace!("got documentation '{}'", dox); look_for_tests(&cx, &dox, &item, true); @@ -540,6 +544,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }); for (ori_link, link_range) in markdown_links(&dox) { + trace!("considering link '{}'", ori_link); + // Bail early for real links. if ori_link.contains('/') { continue; @@ -866,6 +872,7 @@ fn build_diagnostic( Some(hir_id) => hir_id, None => { // If non-local, no need to check anything. + info!("ignoring warning from parent crate: {}", err_msg); return; } }; From 8387e3825fa077b2c2e6d75d65592cb6c19361c1 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 14 Jul 2020 20:04:41 -0400 Subject: [PATCH 45/50] Add (broken and ignored) test for #73829 --- src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs | 2 +- src/test/rustdoc/intra-doc-crate/traits.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs index 5c3360dc5fdb3..c16e39d56f3d0 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs @@ -1,7 +1,7 @@ #![crate_name = "inner"] /// this is a trait pub trait SomeTrait { - /// this is a method for [SomeTrait] + /// this is a method for [a trait][SomeTrait] fn foo(); } diff --git a/src/test/rustdoc/intra-doc-crate/traits.rs b/src/test/rustdoc/intra-doc-crate/traits.rs index 0672c76435b9a..617331236902d 100644 --- a/src/test/rustdoc/intra-doc-crate/traits.rs +++ b/src/test/rustdoc/intra-doc-crate/traits.rs @@ -1,3 +1,5 @@ +// ignore-test +// ^ this is https://github.com/rust-lang/rust/issues/73829 // aux-build:traits.rs // build-aux-docs // ignore-tidy-line-length @@ -10,6 +12,6 @@ pub struct SomeStruct; // @has 'traits/struct.SomeStruct.html' '//a[@href="../inner/trait.SomeTrait.html"]' 'SomeTrait' impl SomeTrait for SomeStruct { - // @has 'traits/struct.SomeStruct.html' '//a[@href="../inner/trait.SomeTrait.html"]' 'SomeTrait' + // @has 'traits/struct.SomeStruct.html' '//a[@href="../inner/trait.SomeTrait.html"]' 'a trait' fn foo() {} } From c46e0386c5c3dcd448975cfa551b93045b013ce4 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 16 Jul 2020 18:25:53 -0400 Subject: [PATCH 46/50] Fix invalid lint intra_doc_resolution_failure is not a lint. --- src/test/rustdoc-ui/intra-links-private.rs | 2 +- src/test/rustdoc/intra-doc-crate/additional_doc.rs | 2 +- src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs | 2 +- src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs | 2 +- src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs | 2 +- src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs | 2 +- src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs | 2 +- src/test/rustdoc/intra-doc-crate/basic.rs | 2 +- src/test/rustdoc/intra-doc-crate/macro.rs | 2 +- src/test/rustdoc/intra-doc-crate/submodule-inner.rs | 2 +- src/test/rustdoc/intra-doc-crate/submodule-outer.rs | 2 +- src/test/rustdoc/intra-link-prim-precedence.rs | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/rustdoc-ui/intra-links-private.rs b/src/test/rustdoc-ui/intra-links-private.rs index b7906aba5b1a9..86cf9fed3dab4 100644 --- a/src/test/rustdoc-ui/intra-links-private.rs +++ b/src/test/rustdoc-ui/intra-links-private.rs @@ -1,7 +1,7 @@ // check-pass // revisions: public private // [private]compile-flags: --document-private-items -#![cfg_attr(private, deny(intra_doc_resolution_failure))] +#![cfg_attr(private, deny(intra_doc_link_resolution_failure))] /// docs [DontDocMe] //[public]~^ WARNING `[DontDocMe]` public documentation for `DocMe` links to a private item diff --git a/src/test/rustdoc/intra-doc-crate/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/additional_doc.rs index dc1d85c9941f9..adfa7f5754eb9 100644 --- a/src/test/rustdoc/intra-doc-crate/additional_doc.rs +++ b/src/test/rustdoc/intra-doc-crate/additional_doc.rs @@ -1,6 +1,6 @@ // aux-build:additional_doc.rs // build-aux-docs -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] extern crate my_rand; diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs index 353689a6d0db2..8b8793e75ed59 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs @@ -1,5 +1,5 @@ #![crate_name = "my_rand"] -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] pub trait RngCore {} /// Rng extends [`RngCore`]. diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs index 8c83633424fd9..2ee5835a7df84 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs @@ -1,5 +1,5 @@ #![crate_name = "a"] -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] pub struct Foo; diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs index e54539f0bc5df..abd41fec13016 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs @@ -1,5 +1,5 @@ #![crate_name = "macro_inner"] -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] pub struct Foo; diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs index 73073ebff1406..3a22d13e673ac 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs @@ -1,5 +1,5 @@ #![crate_name = "a"] -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] pub mod bar { pub struct Bar; diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs index c045d6488f46d..b8ca4e44e1f16 100644 --- a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs +++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs @@ -1,5 +1,5 @@ #![crate_name = "bar"] -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] pub trait Foo { /// [`Bar`] [`Baz`] diff --git a/src/test/rustdoc/intra-doc-crate/basic.rs b/src/test/rustdoc/intra-doc-crate/basic.rs index 6b6757b94e36a..a245a0f84539c 100644 --- a/src/test/rustdoc/intra-doc-crate/basic.rs +++ b/src/test/rustdoc/intra-doc-crate/basic.rs @@ -1,6 +1,6 @@ // aux-build:intra-doc-basic.rs // build-aux-docs -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] // from https://github.com/rust-lang/rust/issues/65983 extern crate a; diff --git a/src/test/rustdoc/intra-doc-crate/macro.rs b/src/test/rustdoc/intra-doc-crate/macro.rs index 5c8cec128dfa0..72fd57b6b0c7f 100644 --- a/src/test/rustdoc/intra-doc-crate/macro.rs +++ b/src/test/rustdoc/intra-doc-crate/macro.rs @@ -2,7 +2,7 @@ // aux-build:macro_inner.rs // aux-build:proc_macro.rs // build-aux-docs -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] extern crate macro_inner; extern crate proc_macro_inner; diff --git a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs index e83d258c1df35..b4b615bf9edad 100644 --- a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs +++ b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs @@ -1,6 +1,6 @@ // aux-build:submodule-inner.rs // build-aux-docs -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] extern crate a; diff --git a/src/test/rustdoc/intra-doc-crate/submodule-outer.rs b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs index ccf226e1dfd03..6b30ef8b3dec8 100644 --- a/src/test/rustdoc/intra-doc-crate/submodule-outer.rs +++ b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs @@ -1,6 +1,6 @@ // aux-build:submodule-outer.rs // edition:2018 -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] extern crate bar as bar_; diff --git a/src/test/rustdoc/intra-link-prim-precedence.rs b/src/test/rustdoc/intra-link-prim-precedence.rs index ca83d5e2281a7..d7ebb73b3be7d 100644 --- a/src/test/rustdoc/intra-link-prim-precedence.rs +++ b/src/test/rustdoc/intra-link-prim-precedence.rs @@ -1,5 +1,5 @@ // ignore-tidy-linelength -#![deny(intra_doc_resolution_failure)] +#![deny(intra_doc_link_resolution_failure)] pub mod char {} From 9f0080801da75c596cd8548ffb539bb8f046fa62 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 Jul 2020 15:05:26 +1000 Subject: [PATCH 47/50] Remove `ExtCtxt::ident_of`. It's equivalent to `Ident::from_str_and_span`. The commit also introduces some more static symbols so that `Ident::new` can be used in various places instead of `Ident::from_str_and_span`. The commit also changes `Path::path` from a `&str` to a `Symbol`, which then allows the lifetime annotation to be removed from `Ty`. Also, the use of `Symbol` in `Bounds` removes the need for its lifetime annotation. --- .../deriving/cmp/ord.rs | 2 +- .../deriving/cmp/partial_eq.rs | 2 +- .../deriving/cmp/partial_ord.rs | 4 +- src/librustc_builtin_macros/deriving/debug.rs | 11 ++-- .../deriving/decodable.rs | 36 ++++++------ .../deriving/default.rs | 3 +- .../deriving/encodable.rs | 39 +++++++------ .../deriving/generic/mod.rs | 26 +++++---- .../deriving/generic/ty.rs | 54 +++++++++--------- src/librustc_builtin_macros/deriving/hash.rs | 4 +- src/librustc_builtin_macros/deriving/mod.rs | 6 +- src/librustc_builtin_macros/format.rs | 46 ++++++++-------- .../global_allocator.rs | 4 +- .../proc_macro_harness.rs | 14 ++--- src/librustc_builtin_macros/test.rs | 30 +++++++--- src/librustc_builtin_macros/test_harness.rs | 2 +- src/librustc_expand/base.rs | 3 - src/librustc_expand/build.rs | 2 +- src/librustc_span/symbol.rs | 55 +++++++++++++++++++ 19 files changed, 209 insertions(+), 134 deletions(-) diff --git a/src/librustc_builtin_macros/deriving/cmp/ord.rs b/src/librustc_builtin_macros/deriving/cmp/ord.rs index a4009f9f58b8d..3bf3860d32307 100644 --- a/src/librustc_builtin_macros/deriving/cmp/ord.rs +++ b/src/librustc_builtin_macros/deriving/cmp/ord.rs @@ -29,7 +29,7 @@ pub fn expand_deriving_ord( name: sym::cmp, generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], + args: vec![(borrowed_self(), sym::other)], ret_ty: Literal(path_std!(cmp::Ordering)), attributes: attrs, is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs index d0676d8d8235e..d8edd641acd52 100644 --- a/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs +++ b/src/librustc_builtin_macros/deriving/cmp/partial_eq.rs @@ -71,7 +71,7 @@ pub fn expand_deriving_partial_eq( name: $name, generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], + args: vec![(borrowed_self(), sym::other)], ret_ty: Literal(path_local!(bool)), attributes: attrs, is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs index e562c6c4092ff..39a747c856839 100644 --- a/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs +++ b/src/librustc_builtin_macros/deriving/cmp/partial_ord.rs @@ -25,7 +25,7 @@ pub fn expand_deriving_partial_ord( name: $name, generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], + args: vec![(borrowed_self(), sym::other)], ret_ty: Literal(path_local!(bool)), attributes: attrs, is_unsafe: false, @@ -52,7 +52,7 @@ pub fn expand_deriving_partial_ord( name: sym::partial_cmp, generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), "other")], + args: vec![(borrowed_self(), sym::other)], ret_ty, attributes: attrs, is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/debug.rs b/src/librustc_builtin_macros/deriving/debug.rs index 830eeb87f8d8f..76e21bc43c52d 100644 --- a/src/librustc_builtin_macros/deriving/debug.rs +++ b/src/librustc_builtin_macros/deriving/debug.rs @@ -32,7 +32,7 @@ pub fn expand_deriving_debug( name: sym::fmt, generics: Bounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec![(fmtr, "f")], + args: vec![(fmtr, sym::f)], ret_ty: Literal(path_std!(fmt::Result)), attributes: Vec::new(), is_unsafe: false, @@ -62,7 +62,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // We want to make sure we have the ctxt set so that we can use unstable methods let span = cx.with_def_site_ctxt(span); let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); - let builder = cx.ident_of("debug_trait_builder", span); + let builder = Ident::new(sym::debug_trait_builder, span); let builder_expr = cx.expr_ident(span, builder); let fmt = substr.nonself_args[0].clone(); @@ -71,7 +71,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> match vdata { ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { // tuple struct/"normal" variant - let expr = cx.expr_method_call(span, fmt, cx.ident_of("debug_tuple", span), vec![name]); + let expr = + cx.expr_method_call(span, fmt, Ident::new(sym::debug_tuple, span), vec![name]); stmts.push(cx.stmt_let(span, true, builder, expr)); for field in fields { @@ -94,7 +95,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> ast::VariantData::Struct(..) => { // normal struct/struct variant let expr = - cx.expr_method_call(span, fmt, cx.ident_of("debug_struct", span), vec![name]); + cx.expr_method_call(span, fmt, Ident::new(sym::debug_struct, span), vec![name]); stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); for field in fields { @@ -117,7 +118,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> } } - let expr = cx.expr_method_call(span, builder_expr, cx.ident_of("finish", span), vec![]); + let expr = cx.expr_method_call(span, builder_expr, Ident::new(sym::finish, span), vec![]); stmts.push(cx.stmt_expr(expr)); let block = cx.block(span, stmts); diff --git a/src/librustc_builtin_macros/deriving/decodable.rs b/src/librustc_builtin_macros/deriving/decodable.rs index f5139d95a4c61..ce8c2dfe4d5a0 100644 --- a/src/librustc_builtin_macros/deriving/decodable.rs +++ b/src/librustc_builtin_macros/deriving/decodable.rs @@ -8,7 +8,7 @@ use rustc_ast::ast; use rustc_ast::ast::{Expr, MetaItem, Mutability}; use rustc_ast::ptr::P; use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; pub fn expand_deriving_rustc_decodable( @@ -18,13 +18,13 @@ pub fn expand_deriving_rustc_decodable( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - let krate = "rustc_serialize"; - let typaram = "__D"; + let krate = sym::rustc_serialize; + let typaram = sym::__D; let trait_def = TraitDef { span, attributes: Vec::new(), - path: Path::new_(vec![krate, "Decodable"], None, vec![], PathKind::Global), + path: Path::new_(vec![krate, sym::Decodable], None, vec![], PathKind::Global), additional_bounds: Vec::new(), generics: Bounds::empty(), is_unsafe: false, @@ -34,13 +34,13 @@ pub fn expand_deriving_rustc_decodable( generics: Bounds { bounds: vec![( typaram, - vec![Path::new_(vec![krate, "Decoder"], None, vec![], PathKind::Global)], + vec![Path::new_(vec![krate, sym::Decoder], None, vec![], PathKind::Global)], )], }, explicit_self: None, args: vec![( Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - "d", + sym::d, )], ret_ty: Literal(Path::new_( pathvec_std!(result::Result), @@ -48,7 +48,7 @@ pub fn expand_deriving_rustc_decodable( vec![ Box::new(Self_), Box::new(Literal(Path::new_( - vec![typaram, "Error"], + vec![typaram, sym::Error], None, vec![], PathKind::Local, @@ -73,17 +73,17 @@ fn decodable_substructure( cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>, - krate: &str, + krate: Symbol, ) -> P { let decoder = substr.nonself_args[0].clone(); let recurse = vec![ - cx.ident_of(krate, trait_span), - cx.ident_of("Decodable", trait_span), - cx.ident_of("decode", trait_span), + Ident::new(krate, trait_span), + Ident::new(sym::Decodable, trait_span), + Ident::new(sym::decode, trait_span), ]; let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse)); // throw an underscore in front to suppress unused variable warnings - let blkarg = cx.ident_of("_d", trait_span); + let blkarg = Ident::new(sym::_d, trait_span); let blkdecoder = cx.expr_ident(trait_span, blkarg); match *substr.fields { @@ -92,7 +92,7 @@ fn decodable_substructure( Unnamed(ref fields, _) => fields.len(), Named(ref fields) => fields.len(), }; - let read_struct_field = cx.ident_of("read_struct_field", trait_span); + let read_struct_field = Ident::new(sym::read_struct_field, trait_span); let path = cx.path_ident(trait_span, substr.type_ident); let result = @@ -115,7 +115,7 @@ fn decodable_substructure( cx.expr_method_call( trait_span, decoder, - cx.ident_of("read_struct", trait_span), + Ident::new(sym::read_struct, trait_span), vec![ cx.expr_str(trait_span, substr.type_ident.name), cx.expr_usize(trait_span, nfields), @@ -124,11 +124,11 @@ fn decodable_substructure( ) } StaticEnum(_, ref fields) => { - let variant = cx.ident_of("i", trait_span); + let variant = Ident::new(sym::i, trait_span); let mut arms = Vec::with_capacity(fields.len() + 1); let mut variants = Vec::with_capacity(fields.len()); - let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span); + let rvariant_arg = Ident::new(sym::read_enum_variant_arg, trait_span); for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() { variants.push(cx.expr_str(v_span, ident.name)); @@ -163,13 +163,13 @@ fn decodable_substructure( let result = cx.expr_method_call( trait_span, blkdecoder, - cx.ident_of("read_enum_variant", trait_span), + Ident::new(sym::read_enum_variant, trait_span), vec![variant_vec, lambda], ); cx.expr_method_call( trait_span, decoder, - cx.ident_of("read_enum", trait_span), + Ident::new(sym::read_enum, trait_span), vec![ cx.expr_str(trait_span, substr.type_ident.name), cx.lambda1(trait_span, result, blkarg), diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs index f8d9c76d372d8..8ca1be1efb635 100644 --- a/src/librustc_builtin_macros/deriving/default.rs +++ b/src/librustc_builtin_macros/deriving/default.rs @@ -1,6 +1,5 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::path_std; use rustc_ast::ast::{Expr, MetaItem}; use rustc_ast::ptr::P; @@ -21,7 +20,7 @@ pub fn expand_deriving_default( let trait_def = TraitDef { span, attributes: Vec::new(), - path: path_std!(default::Default), + path: Path::new(vec![kw::Default, sym::Default]), additional_bounds: Vec::new(), generics: Bounds::empty(), is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/encodable.rs b/src/librustc_builtin_macros/deriving/encodable.rs index cbb263989e6fa..7a880357a5947 100644 --- a/src/librustc_builtin_macros/deriving/encodable.rs +++ b/src/librustc_builtin_macros/deriving/encodable.rs @@ -92,7 +92,7 @@ use crate::deriving::pathvec_std; use rustc_ast::ast::{Expr, ExprKind, MetaItem, Mutability}; use rustc_ast::ptr::P; use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; pub fn expand_deriving_rustc_encodable( @@ -102,13 +102,13 @@ pub fn expand_deriving_rustc_encodable( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - let krate = "rustc_serialize"; - let typaram = "__S"; + let krate = sym::rustc_serialize; + let typaram = sym::__S; let trait_def = TraitDef { span, attributes: Vec::new(), - path: Path::new_(vec![krate, "Encodable"], None, vec![], PathKind::Global), + path: Path::new_(vec![krate, sym::Encodable], None, vec![], PathKind::Global), additional_bounds: Vec::new(), generics: Bounds::empty(), is_unsafe: false, @@ -118,13 +118,18 @@ pub fn expand_deriving_rustc_encodable( generics: Bounds { bounds: vec![( typaram, - vec![Path::new_(vec![krate, "Encoder"], None, vec![], PathKind::Global)], + vec![Path::new_(vec![krate, sym::Encoder], None, vec![], PathKind::Global)], )], }, explicit_self: borrowed_explicit_self(), args: vec![( Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - "s", + // FIXME: we could use `sym::s` here, but making `s` a static + // symbol changes the symbol index ordering in a way that makes + // ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs + // fail. The linting code should be fixed so that its output + // does not depend on the symbol index ordering. + Symbol::intern("s"), )], ret_ty: Literal(Path::new_( pathvec_std!(result::Result), @@ -132,7 +137,7 @@ pub fn expand_deriving_rustc_encodable( vec![ Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_( - vec![typaram, "Error"], + vec![typaram, sym::Error], None, vec![], PathKind::Local, @@ -157,24 +162,24 @@ fn encodable_substructure( cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>, - krate: &'static str, + krate: Symbol, ) -> P { let encoder = substr.nonself_args[0].clone(); // throw an underscore in front to suppress unused variable warnings - let blkarg = cx.ident_of("_e", trait_span); + let blkarg = Ident::new(sym::_e, trait_span); let blkencoder = cx.expr_ident(trait_span, blkarg); let fn_path = cx.expr_path(cx.path_global( trait_span, vec![ - cx.ident_of(krate, trait_span), - cx.ident_of("Encodable", trait_span), - cx.ident_of("encode", trait_span), + Ident::new(krate, trait_span), + Ident::new(sym::Encodable, trait_span), + Ident::new(sym::encode, trait_span), ], )); match *substr.fields { Struct(_, ref fields) => { - let emit_struct_field = cx.ident_of("emit_struct_field", trait_span); + let emit_struct_field = Ident::new(sym::emit_struct_field, trait_span); let mut stmts = Vec::new(); for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() { let name = match name { @@ -214,7 +219,7 @@ fn encodable_substructure( cx.expr_method_call( trait_span, encoder, - cx.ident_of("emit_struct", trait_span), + Ident::new(sym::emit_struct, trait_span), vec![ cx.expr_str(trait_span, substr.type_ident.name), cx.expr_usize(trait_span, fields.len()), @@ -230,7 +235,7 @@ fn encodable_substructure( // actually exist. let me = cx.stmt_let(trait_span, false, blkarg, encoder); let encoder = cx.expr_ident(trait_span, blkarg); - let emit_variant_arg = cx.ident_of("emit_enum_variant_arg", trait_span); + let emit_variant_arg = Ident::new(sym::emit_enum_variant_arg, trait_span); let mut stmts = Vec::new(); if !fields.is_empty() { let last = fields.len() - 1; @@ -263,7 +268,7 @@ fn encodable_substructure( let call = cx.expr_method_call( trait_span, blkencoder, - cx.ident_of("emit_enum_variant", trait_span), + Ident::new(sym::emit_enum_variant, trait_span), vec![ name, cx.expr_usize(trait_span, idx), @@ -275,7 +280,7 @@ fn encodable_substructure( let ret = cx.expr_method_call( trait_span, encoder, - cx.ident_of("emit_enum", trait_span), + Ident::new(sym::emit_enum, trait_span), vec![cx.expr_str(trait_span, substr.type_ident.name), blk], ); cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)])) diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index be8eaa883eb33..c43d1cf1888c4 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -204,14 +204,14 @@ pub struct TraitDef<'a> { pub attributes: Vec, /// Path of the trait, including any type parameters - pub path: Path<'a>, + pub path: Path, /// Additional bounds required of any type parameters of the type, /// other than the current trait - pub additional_bounds: Vec>, + pub additional_bounds: Vec, /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder` - pub generics: Bounds<'a>, + pub generics: Bounds, /// Is it an `unsafe` trait? pub is_unsafe: bool, @@ -221,14 +221,14 @@ pub struct TraitDef<'a> { pub methods: Vec>, - pub associated_types: Vec<(Ident, Ty<'a>)>, + pub associated_types: Vec<(Ident, Ty)>, } pub struct MethodDef<'a> { /// name of the method pub name: Symbol, /// List of generics, e.g., `R: rand::Rng` - pub generics: Bounds<'a>, + pub generics: Bounds, /// Whether there is a self argument (outer Option) i.e., whether /// this is a static function, and whether it is a pointer (inner @@ -236,10 +236,10 @@ pub struct MethodDef<'a> { pub explicit_self: Option>, /// Arguments other than the self argument - pub args: Vec<(Ty<'a>, &'a str)>, + pub args: Vec<(Ty, Symbol)>, /// Returns type - pub ret_ty: Ty<'a>, + pub ret_ty: Ty, pub attributes: Vec, @@ -865,7 +865,7 @@ impl<'a> MethodDef<'a> { for (ty, name) in self.args.iter() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(name, trait_.span); + let ident = Ident::new(*name, trait_.span); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -1170,8 +1170,10 @@ impl<'a> MethodDef<'a> { ) .collect::>(); - let self_arg_idents = - self_arg_names.iter().map(|name| cx.ident_of(name, sp)).collect::>(); + let self_arg_idents = self_arg_names + .iter() + .map(|name| Ident::from_str_and_span(name, sp)) + .collect::>(); // The `vi_idents` will be bound, solely in the catch-all, to // a series of let statements mapping each self_arg to an int @@ -1180,7 +1182,7 @@ impl<'a> MethodDef<'a> { .iter() .map(|name| { let vi_suffix = format!("{}_vi", &name[..]); - cx.ident_of(&vi_suffix[..], trait_.span) + Ident::from_str_and_span(&vi_suffix, trait_.span) }) .collect::>(); @@ -1568,7 +1570,7 @@ impl<'a> TraitDef<'a> { let mut ident_exprs = Vec::new(); for (i, struct_field) in struct_def.fields().iter().enumerate() { let sp = struct_field.span.with_ctxt(self.span.ctxt()); - let ident = cx.ident_of(&format!("{}_{}", prefix, i), self.span); + let ident = Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span); paths.push(ident.with_span_pos(sp)); let val = cx.expr_path(cx.path_ident(sp, ident)); let val = if use_temporaries { val } else { cx.expr_deref(sp, val) }; diff --git a/src/librustc_builtin_macros/deriving/generic/ty.rs b/src/librustc_builtin_macros/deriving/generic/ty.rs index a031e4b649fa1..51314dbcffc06 100644 --- a/src/librustc_builtin_macros/deriving/generic/ty.rs +++ b/src/librustc_builtin_macros/deriving/generic/ty.rs @@ -8,7 +8,7 @@ use rustc_ast::ast::{self, Expr, GenericArg, GenericParamKind, Generics, SelfKin use rustc_ast::ptr::P; use rustc_expand::base::ExtCtxt; use rustc_span::source_map::{respan, DUMMY_SP}; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; /// The types of pointers @@ -24,10 +24,10 @@ pub enum PtrTy { /// A path, e.g., `::std::option::Option::` (global). Has support /// for type parameters and a lifetime. #[derive(Clone)] -pub struct Path<'a> { - path: Vec<&'a str>, +pub struct Path { + path: Vec, lifetime: Option, - params: Vec>>, + params: Vec>, kind: PathKind, } @@ -38,19 +38,19 @@ pub enum PathKind { Std, } -impl<'a> Path<'a> { - pub fn new(path: Vec<&str>) -> Path<'_> { +impl Path { + pub fn new(path: Vec) -> Path { Path::new_(path, None, Vec::new(), PathKind::Std) } - pub fn new_local(path: &str) -> Path<'_> { + pub fn new_local(path: Symbol) -> Path { Path::new_(vec![path], None, Vec::new(), PathKind::Local) } - pub fn new_<'r>( - path: Vec<&'r str>, + pub fn new_( + path: Vec, lifetime: Option, - params: Vec>>, + params: Vec>, kind: PathKind, - ) -> Path<'r> { + ) -> Path { Path { path, lifetime, params, kind } } @@ -70,7 +70,7 @@ impl<'a> Path<'a> { self_ty: Ident, self_generics: &Generics, ) -> ast::Path { - let mut idents = self.path.iter().map(|s| cx.ident_of(*s, span)).collect(); + let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect(); let lt = mk_lifetimes(cx, span, &self.lifetime); let tys: Vec> = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); @@ -94,21 +94,21 @@ impl<'a> Path<'a> { /// A type. Supports pointers, Self, and literals. #[derive(Clone)] -pub enum Ty<'a> { +pub enum Ty { Self_, /// &/Box/ Ty - Ptr(Box>, PtrTy), + Ptr(Box, PtrTy), /// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type /// parameter, and things like `i32` - Literal(Path<'a>), + Literal(Path), /// includes unit - Tuple(Vec>), + Tuple(Vec), } pub fn borrowed_ptrty() -> PtrTy { Borrowed(None, ast::Mutability::Not) } -pub fn borrowed(ty: Box>) -> Ty<'_> { +pub fn borrowed(ty: Box) -> Ty { Ptr(ty, borrowed_ptrty()) } @@ -116,11 +116,11 @@ pub fn borrowed_explicit_self() -> Option> { Some(Some(borrowed_ptrty())) } -pub fn borrowed_self<'r>() -> Ty<'r> { +pub fn borrowed_self() -> Ty { borrowed(Box::new(Self_)) } -pub fn nil_ty<'r>() -> Ty<'r> { +pub fn nil_ty() -> Ty { Tuple(Vec::new()) } @@ -132,7 +132,7 @@ fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option) -> Vec Ty<'a> { +impl Ty { pub fn to_ty( &self, cx: &ExtCtxt<'_>, @@ -199,9 +199,9 @@ impl<'a> Ty<'a> { fn mk_ty_param( cx: &ExtCtxt<'_>, span: Span, - name: &str, + name: Symbol, attrs: &[ast::Attribute], - bounds: &[Path<'_>], + bounds: &[Path], self_ident: Ident, self_generics: &Generics, ) -> ast::GenericParam { @@ -212,7 +212,7 @@ fn mk_ty_param( cx.trait_bound(path) }) .collect(); - cx.typaram(span, cx.ident_of(name, span), attrs.to_owned(), bounds, None) + cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None) } fn mk_generics(params: Vec, span: Span) -> Generics { @@ -225,12 +225,12 @@ fn mk_generics(params: Vec, span: Span) -> Generics { /// Bounds on type parameters. #[derive(Clone)] -pub struct Bounds<'a> { - pub bounds: Vec<(&'a str, Vec>)>, +pub struct Bounds { + pub bounds: Vec<(Symbol, Vec)>, } -impl<'a> Bounds<'a> { - pub fn empty() -> Bounds<'a> { +impl Bounds { + pub fn empty() -> Bounds { Bounds { bounds: Vec::new() } } pub fn to_generics( diff --git a/src/librustc_builtin_macros/deriving/hash.rs b/src/librustc_builtin_macros/deriving/hash.rs index 34e04a202696a..d7195188085f0 100644 --- a/src/librustc_builtin_macros/deriving/hash.rs +++ b/src/librustc_builtin_macros/deriving/hash.rs @@ -17,7 +17,7 @@ pub fn expand_deriving_hash( ) { let path = Path::new_(pathvec_std!(hash::Hash), None, vec![], PathKind::Std); - let typaram = "__H"; + let typaram = sym::__H; let arg = Path::new_local(typaram); let hash_trait_def = TraitDef { @@ -32,7 +32,7 @@ pub fn expand_deriving_hash( name: sym::hash, generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] }, explicit_self: borrowed_explicit_self(), - args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), "state")], + args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), sym::state)], ret_ty: nil_ty(), attributes: vec![], is_unsafe: false, diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs index 777640035677a..33c0edde98f0b 100644 --- a/src/librustc_builtin_macros/deriving/mod.rs +++ b/src/librustc_builtin_macros/deriving/mod.rs @@ -7,11 +7,11 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; macro path_local($x:ident) { - generic::ty::Path::new_local(stringify!($x)) + generic::ty::Path::new_local(sym::$x) } macro pathvec_std($($rest:ident)::+) {{ - vec![ $( stringify!($rest) ),+ ] + vec![ $( sym::$rest ),+ ] }} macro path_std($($x:tt)*) { @@ -84,7 +84,7 @@ fn inject_impl_of_structural_trait( cx: &mut ExtCtxt<'_>, span: Span, item: &Annotatable, - structural_path: generic::ty::Path<'_>, + structural_path: generic::ty::Path, push: &mut dyn FnMut(Annotatable), ) { let item = match *item { diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 2becbe2f6758a..55eab24b8a510 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -578,31 +578,31 @@ impl<'a, 'b> Context<'a, 'b> { self.count_args_index_offset = sofar; } - fn rtpath(ecx: &ExtCtxt<'_>, s: &str) -> Vec { - ecx.std_path(&[sym::fmt, sym::rt, sym::v1, Symbol::intern(s)]) + fn rtpath(ecx: &ExtCtxt<'_>, s: Symbol) -> Vec { + ecx.std_path(&[sym::fmt, sym::rt, sym::v1, s]) } fn build_count(&self, c: parse::Count) -> P { let sp = self.macsp; let count = |c, arg| { - let mut path = Context::rtpath(self.ecx, "Count"); - path.push(self.ecx.ident_of(c, sp)); + let mut path = Context::rtpath(self.ecx, sym::Count); + path.push(Ident::new(c, sp)); match arg { Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]), None => self.ecx.expr_path(self.ecx.path_global(sp, path)), } }; match c { - parse::CountIs(i) => count("Is", Some(self.ecx.expr_usize(sp, i))), + parse::CountIs(i) => count(sym::Is, Some(self.ecx.expr_usize(sp, i))), parse::CountIsParam(i) => { // This needs mapping too, as `i` is referring to a macro // argument. If `i` is not found in `count_positions` then // the error had already been emitted elsewhere. let i = self.count_positions.get(&i).cloned().unwrap_or(0) + self.count_args_index_offset; - count("Param", Some(self.ecx.expr_usize(sp, i))) + count(sym::Param, Some(self.ecx.expr_usize(sp, i))) } - parse::CountImplied => count("Implied", None), + parse::CountImplied => count(sym::Implied, None), // should never be the case, names are already resolved parse::CountIsName(_) => panic!("should never happen"), } @@ -690,40 +690,40 @@ impl<'a, 'b> Context<'a, 'b> { // Build the format let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill)); let align = |name| { - let mut p = Context::rtpath(self.ecx, "Alignment"); - p.push(self.ecx.ident_of(name, sp)); + let mut p = Context::rtpath(self.ecx, sym::Alignment); + p.push(Ident::new(name, sp)); self.ecx.path_global(sp, p) }; let align = match arg.format.align { - parse::AlignLeft => align("Left"), - parse::AlignRight => align("Right"), - parse::AlignCenter => align("Center"), - parse::AlignUnknown => align("Unknown"), + parse::AlignLeft => align(sym::Left), + parse::AlignRight => align(sym::Right), + parse::AlignCenter => align(sym::Center), + parse::AlignUnknown => align(sym::Unknown), }; let align = self.ecx.expr_path(align); let flags = self.ecx.expr_u32(sp, arg.format.flags); let prec = self.build_count(arg.format.precision); let width = self.build_count(arg.format.width); - let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec")); + let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::FormatSpec)); let fmt = self.ecx.expr_struct( sp, path, vec![ - self.ecx.field_imm(sp, self.ecx.ident_of("fill", sp), fill), - self.ecx.field_imm(sp, self.ecx.ident_of("align", sp), align), - self.ecx.field_imm(sp, self.ecx.ident_of("flags", sp), flags), - self.ecx.field_imm(sp, self.ecx.ident_of("precision", sp), prec), - self.ecx.field_imm(sp, self.ecx.ident_of("width", sp), width), + self.ecx.field_imm(sp, Ident::new(sym::fill, sp), fill), + self.ecx.field_imm(sp, Ident::new(sym::align, sp), align), + self.ecx.field_imm(sp, Ident::new(sym::flags, sp), flags), + self.ecx.field_imm(sp, Ident::new(sym::precision, sp), prec), + self.ecx.field_imm(sp, Ident::new(sym::width, sp), width), ], ); - let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "Argument")); + let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::Argument)); Some(self.ecx.expr_struct( sp, path, vec![ - self.ecx.field_imm(sp, self.ecx.ident_of("position", sp), pos), - self.ecx.field_imm(sp, self.ecx.ident_of("format", sp), fmt), + self.ecx.field_imm(sp, Ident::new(sym::position, sp), pos), + self.ecx.field_imm(sp, Ident::new(sym::format, sp), fmt), ], )) } @@ -740,7 +740,7 @@ impl<'a, 'b> Context<'a, 'b> { let mut heads = Vec::with_capacity(self.args.len()); let names_pos: Vec<_> = (0..self.args.len()) - .map(|i| self.ecx.ident_of(&format!("arg{}", i), self.macsp)) + .map(|i| Ident::from_str_and_span(&format!("arg{}", i), self.macsp)) .collect(); // First, build up the static array which will become our precompiled diff --git a/src/librustc_builtin_macros/global_allocator.rs b/src/librustc_builtin_macros/global_allocator.rs index f8a9a97b2a50e..89446a1aa96f9 100644 --- a/src/librustc_builtin_macros/global_allocator.rs +++ b/src/librustc_builtin_macros/global_allocator.rs @@ -58,7 +58,7 @@ impl AllocFnFactory<'_, '_> { let mut abi_args = Vec::new(); let mut i = 0; let mut mk = || { - let name = self.cx.ident_of(&format!("arg{}", i), self.span); + let name = Ident::from_str_and_span(&format!("arg{}", i), self.span); i += 1; name }; @@ -72,7 +72,7 @@ impl AllocFnFactory<'_, '_> { let kind = ItemKind::Fn(ast::Defaultness::Final, sig, Generics::default(), block); let item = self.cx.item( self.span, - self.cx.ident_of(&self.kind.fn_name(method.name), self.span), + Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span), self.attrs(), kind, ); diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs index 7cc9c1f76631e..f044ce41e879e 100644 --- a/src/librustc_builtin_macros/proc_macro_harness.rs +++ b/src/librustc_builtin_macros/proc_macro_harness.rs @@ -384,12 +384,12 @@ fn mk_decls( let proc_macro = Ident::new(sym::proc_macro, span); let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None)); - let bridge = cx.ident_of("bridge", span); - let client = cx.ident_of("client", span); - let proc_macro_ty = cx.ident_of("ProcMacro", span); - let custom_derive = cx.ident_of("custom_derive", span); - let attr = cx.ident_of("attr", span); - let bang = cx.ident_of("bang", span); + let bridge = Ident::new(sym::bridge, span); + let client = Ident::new(sym::client, span); + let proc_macro_ty = Ident::new(sym::ProcMacro, span); + let custom_derive = Ident::new(sym::custom_derive, span); + let attr = Ident::new(sym::attr, span); + let bang = Ident::new(sym::bang, span); let krate_ref = RefCell::new(ast_krate); @@ -447,7 +447,7 @@ fn mk_decls( let decls_static = cx .item_static( span, - cx.ident_of("_DECLS", span), + Ident::new(sym::_DECLS, span), cx.ty_rptr( span, cx.ty( diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index d62f34bab1a31..460f947a792af 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -108,22 +108,38 @@ pub fn expand_test_or_bench( let test_id = Ident::new(sym::test, attr_sp); // creates test::$name - let test_path = |name| cx.path(sp, vec![test_id, cx.ident_of(name, sp)]); + let test_path = |name| cx.path(sp, vec![test_id, Ident::from_str_and_span(name, sp)]); // creates test::ShouldPanic::$name - let should_panic_path = - |name| cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)]); + let should_panic_path = |name| { + cx.path( + sp, + vec![ + test_id, + Ident::from_str_and_span("ShouldPanic", sp), + Ident::from_str_and_span(name, sp), + ], + ) + }; // creates test::TestType::$name - let test_type_path = - |name| cx.path(sp, vec![test_id, cx.ident_of("TestType", sp), cx.ident_of(name, sp)]); + let test_type_path = |name| { + cx.path( + sp, + vec![ + test_id, + Ident::from_str_and_span("TestType", sp), + Ident::from_str_and_span(name, sp), + ], + ) + }; // creates $name: $expr - let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr); + let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr); let test_fn = if is_bench { // A simple ident for a lambda - let b = cx.ident_of("b", attr_sp); + let b = Ident::from_str_and_span("b", attr_sp); cx.expr_call( sp, diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index 98e42ebf46f2a..98c5c6936d779 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -270,7 +270,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let mut test_runner = cx .test_runner .clone() - .unwrap_or(ecx.path(sp, vec![test_id, ecx.ident_of(runner_name, sp)])); + .unwrap_or(ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)])); test_runner.span = sp; diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 3e48224ef9f20..64e2d5b3a467c 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -1061,9 +1061,6 @@ impl<'a> ExtCtxt<'a> { pub fn set_trace_macros(&mut self, x: bool) { self.ecfg.trace_mac = x } - pub fn ident_of(&self, st: &str, sp: Span) -> Ident { - Ident::from_str_and_span(st, sp) - } pub fn std_path(&self, components: &[Symbol]) -> Vec { let def_site = self.with_def_site_ctxt(DUMMY_SP); iter::once(Ident::new(kw::DollarCrate, def_site)) diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs index 20d2ea0a215d4..81ff4b3157845 100644 --- a/src/librustc_expand/build.rs +++ b/src/librustc_expand/build.rs @@ -368,7 +368,7 @@ impl<'a> ExtCtxt<'a> { let err = self.std_path(&[sym::result, sym::Result, sym::Err]); let err_path = self.path_global(sp, err); - let binding_variable = self.ident_of("__try_var", sp); + let binding_variable = Ident::new(sym::__try_var, sp); let binding_pat = self.pat_ident(sp, binding_variable); let binding_expr = self.expr_ident(sp, binding_variable); diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 75f588918a020..c4c6fcec4dc5a 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -122,19 +122,28 @@ symbols! { // There is currently no checking that all symbols are used; that would be // nice to have. Symbols { + Alignment, Arc, + Argument, ArgumentV1, Arguments, C, + Center, Clone, Copy, + Count, Debug, Decodable, + Decoder, Default, Encodable, + Encoder, Eq, Equal, Err, + Error, + FormatSpec, + Formatter, From, Future, FxHashMap, @@ -143,11 +152,15 @@ symbols! { Hash, HashMap, HashSet, + Hasher, + Implied, Input, IntoIterator, + Is, ItemContext, Iterator, Layout, + Left, LintPass, None, Ok, @@ -155,11 +168,13 @@ symbols! { Ord, Ordering, Output, + Param, PartialEq, PartialOrd, Pending, Pin, Poll, + ProcMacro, ProcMacroHack, ProceduralMasqueradeDummyType, Range, @@ -172,20 +187,31 @@ symbols! { Ready, Result, Return, + Right, RustcDecodable, RustcEncodable, Send, Some, + StructuralEq, + StructuralPartialEq, Sync, Target, Try, Ty, TyCtxt, TyKind, + Unknown, Vec, Yield, + _DECLS, _Self, + __D, + __H, + __S, __next, + __try_var, + _d, + _e, _task_context, aarch64_target_feature, abi, @@ -256,6 +282,7 @@ symbols! { automatically_derived, avx512_target_feature, await_macro, + bang, begin_panic, bench, bin, @@ -278,6 +305,7 @@ symbols! { box_syntax, braced_empty_structs, breakpoint, + bridge, bswap, c_variadic, call, @@ -299,6 +327,7 @@ symbols! { cfg_target_vendor, cfg_version, char, + client, clippy, clone, clone_closures, @@ -370,11 +399,15 @@ symbols! { custom_derive, custom_inner_attributes, custom_test_frameworks, + d, dead_code, dealloc, debug, debug_assertions, + debug_struct, debug_trait, + debug_trait_builder, + debug_tuple, decl_macro, declare_lint_pass, decode, @@ -420,6 +453,11 @@ symbols! { dyn_trait, eh_catch_typeinfo, eh_personality, + emit_enum, + emit_enum_variant, + emit_enum_variant_arg, + emit_struct, + emit_struct_field, enable, enclosing_scope, encode, @@ -447,6 +485,7 @@ symbols! { extern_prelude, extern_types, external_doc, + f, f16c_target_feature, f32, f32_runtime, @@ -463,6 +502,9 @@ symbols! { field, field_init_shorthand, file, + fill, + finish, + flags, float_to_int_unchecked, floorf32, floorf64, @@ -477,6 +519,7 @@ symbols! { fn_once_output, forbid, forget, + format, format_args, format_args_capture, format_args_nl, @@ -518,6 +561,7 @@ symbols! { html_no_source, html_playground_url, html_root_url, + i, i128, i128_type, i16, @@ -707,6 +751,7 @@ symbols! { options, or, or_patterns, + other, out, overlapping_marker_traits, owned_box, @@ -738,6 +783,7 @@ symbols! { plugins, pointer, poll, + position, post_dash_lto: "post-lto", powerpc_target_feature, powf32, @@ -746,6 +792,7 @@ symbols! { powif64, pre_dash_lto: "pre-lto", precise_pointer_size_matching, + precision, pref_align_of, prefetch_read_data, prefetch_read_instruction, @@ -782,6 +829,11 @@ symbols! { raw_identifiers, raw_ref_op, re_rebalance_coherence, + read_enum, + read_enum_variant, + read_enum_variant_arg, + read_struct, + read_struct_field, readonly, realloc, reason, @@ -871,6 +923,7 @@ symbols! { rustc_promotable, rustc_regions, rustc_reservation_impl, + rustc_serialize, rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, @@ -974,6 +1027,7 @@ symbols! { stable, staged_api, start, + state, static_in_const, static_nobundle, static_recursion, @@ -1121,6 +1175,7 @@ symbols! { wasm_import_module, wasm_target_feature, while_let, + width, windows, windows_subsystem, wrapping_add, From 002af4d0c7aac6607ca4e0a6629ab679df20aeac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Jul 2020 16:45:35 +1000 Subject: [PATCH 48/50] Avoid storing `SymbolStr` in a struct. It's intended only for very temporary use. --- .../clippy/clippy_lints/src/non_expressive_names.rs | 13 +++++++------ .../clippy_lints/src/unsafe_removed_from_name.rs | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index 7128fee9bcf51..1d4772bb3d606 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -8,7 +8,7 @@ use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; -use rustc_span::symbol::{Ident, SymbolStr}; +use rustc_span::symbol::{Ident, Symbol}; use std::cmp::Ordering; declare_clippy_lint! { @@ -75,7 +75,7 @@ pub struct NonExpressiveNames { impl_lint_pass!(NonExpressiveNames => [SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES, JUST_UNDERSCORES_AND_DIGITS]); struct ExistingName { - interned: SymbolStr, + interned: Symbol, span: Span, len: usize, exemptions: &'static [&'static str], @@ -218,18 +218,19 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let mut split_at = None; match existing_name.len.cmp(&count) { Ordering::Greater => { - if existing_name.len - count != 1 || levenstein_not_1(&interned_name, &existing_name.interned) { + if existing_name.len - count != 1 || levenstein_not_1(&interned_name, &existing_name.interned.as_str()) { continue; } }, Ordering::Less => { - if count - existing_name.len != 1 || levenstein_not_1(&existing_name.interned, &interned_name) { + if count - existing_name.len != 1 || levenstein_not_1(&existing_name.interned.as_str(), &interned_name) { continue; } }, Ordering::Equal => { let mut interned_chars = interned_name.chars(); - let mut existing_chars = existing_name.interned.chars(); + let interned_str = existing_name.interned.as_str(); + let mut existing_chars = interned_str.chars(); let first_i = interned_chars.next().expect("we know we have at least one char"); let first_e = existing_chars.next().expect("we know we have at least one char"); let eq_or_numeric = |(a, b): (char, char)| a == b || a.is_numeric() && b.is_numeric(); @@ -302,7 +303,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { } self.0.names.push(ExistingName { exemptions: get_exemptions(&interned_name).unwrap_or(&[]), - interned: interned_name, + interned: ident.name, span: ident.span, len: count, }); diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs index 735800e7e7416..154082a0fdb53 100644 --- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs +++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs @@ -3,7 +3,7 @@ use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::{Ident, SymbolStr}; +use rustc_span::symbol::Ident; declare_clippy_lint! { /// **What it does:** Checks for imports that remove "unsafe" from an item's @@ -73,6 +73,6 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>, } #[must_use] -fn contains_unsafe(name: &SymbolStr) -> bool { +fn contains_unsafe(name: &str) -> bool { name.contains("Unsafe") || name.contains("unsafe") } From f03c7f83eb72d44077f03b8140768eefb60150a0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 Jul 2020 12:12:01 +1000 Subject: [PATCH 49/50] Add `UnsafetyViolationDetails`. This replaces the need for the `description` and `details` symbols in `UnsafetyViolation`, which are static. As a result some `Symbol::as_str()` calls are no longer necessary, which is nice. --- src/librustc_middle/mir/query.rs | 92 ++++++++++++++- src/librustc_mir/transform/check_unsafety.rs | 112 +++++-------------- 2 files changed, 118 insertions(+), 86 deletions(-) diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index 560a8421c1797..b311f8344bb6d 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::BitMatrix; use rustc_index::vec::IndexVec; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; use rustc_target::abi::VariantIdx; use smallvec::SmallVec; use std::cell::Cell; @@ -18,7 +18,7 @@ use super::{Field, SourceInfo}; #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsafetyViolationKind { - /// Only permitted in regular `fn`s, prohibitted in `const fn`s. + /// Only permitted in regular `fn`s, prohibited in `const fn`s. General, /// Permitted both in `const fn`s and regular `fn`s. GeneralAndConstFn, @@ -35,13 +35,97 @@ pub enum UnsafetyViolationKind { UnsafeFnBorrowPacked, } +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +pub enum UnsafetyViolationDetails { + CallToUnsafeFunction, + UseOfInlineAssembly, + InitializingTypeWith, + CastOfPointerToInt, + BorrowOfPackedField, + UseOfMutableStatic, + UseOfExternStatic, + DerefOfRawPointer, + AssignToNonCopyUnionField, + AccessToUnionField, + MutationOfLayoutConstrainedField, + BorrowOfLayoutConstrainedField, + CallToFunctionWith, +} + +impl UnsafetyViolationDetails { + pub fn description_and_note(&self) -> (&'static str, &'static str) { + use UnsafetyViolationDetails::*; + match self { + CallToUnsafeFunction => ( + "call to unsafe function", + "consult the function's documentation for information on how to avoid undefined \ + behavior", + ), + UseOfInlineAssembly => ( + "use of inline assembly", + "inline assembly is entirely unchecked and can cause undefined behavior", + ), + InitializingTypeWith => ( + "initializing type with `rustc_layout_scalar_valid_range` attr", + "initializing a layout restricted type's field with a value outside the valid \ + range is undefined behavior", + ), + CastOfPointerToInt => { + ("cast of pointer to int", "casting pointers to integers in constants") + } + BorrowOfPackedField => ( + "borrow of packed field", + "fields of packed structs might be misaligned: dereferencing a misaligned pointer \ + or even just creating a misaligned reference is undefined behavior", + ), + UseOfMutableStatic => ( + "use of mutable static", + "mutable statics can be mutated by multiple threads: aliasing violations or data \ + races will cause undefined behavior", + ), + UseOfExternStatic => ( + "use of extern static", + "extern statics are not controlled by the Rust type system: invalid data, \ + aliasing violations or data races will cause undefined behavior", + ), + DerefOfRawPointer => ( + "dereference of raw pointer", + "raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules \ + and cause data races: all of these are undefined behavior", + ), + AssignToNonCopyUnionField => ( + "assignment to non-`Copy` union field", + "the previous content of the field will be dropped, which causes undefined \ + behavior if the field was not properly initialized", + ), + AccessToUnionField => ( + "access to union field", + "the field may not be properly initialized: using uninitialized data will cause \ + undefined behavior", + ), + MutationOfLayoutConstrainedField => ( + "mutation of layout constrained field", + "mutating layout constrained fields cannot statically be checked for valid values", + ), + BorrowOfLayoutConstrainedField => ( + "borrow of layout constrained field with interior mutability", + "references to fields of layout constrained fields lose the constraints. Coupled \ + with interior mutability, the field can be changed to invalid values", + ), + CallToFunctionWith => ( + "call to function with `#[target_feature]`", + "can only be called if the required target features are available", + ), + } + } +} + #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyViolation { pub source_info: SourceInfo, pub lint_root: hir::HirId, - pub description: Symbol, - pub details: Symbol, pub kind: UnsafetyViolationKind, + pub details: UnsafetyViolationDetails, } #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 2605d45f8101e..81d7ac0892622 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; use std::ops::Bound; @@ -86,10 +86,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { let sig = func_ty.fn_sig(self.tcx); if let hir::Unsafety::Unsafe = sig.unsafety() { self.require_unsafe( - "call to unsafe function", - "consult the function's documentation for information on how to avoid \ - undefined behavior", UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationDetails::CallToUnsafeFunction, ) } @@ -99,9 +97,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } TerminatorKind::InlineAsm { .. } => self.require_unsafe( - "use of inline assembly", - "inline assembly is entirely unchecked and can cause undefined behavior", UnsafetyViolationKind::General, + UnsafetyViolationDetails::UseOfInlineAssembly, ), } self.super_terminator(terminator, location); @@ -122,9 +119,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } StatementKind::LlvmInlineAsm { .. } => self.require_unsafe( - "use of inline assembly", - "inline assembly is entirely unchecked and can cause undefined behavior", UnsafetyViolationKind::General, + UnsafetyViolationDetails::UseOfInlineAssembly, ), } self.super_statement(statement, location); @@ -138,10 +134,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { match self.tcx.layout_scalar_valid_range(def.did) { (Bound::Unbounded, Bound::Unbounded) => {} _ => self.require_unsafe( - "initializing type with `rustc_layout_scalar_valid_range` attr", - "initializing a layout restricted type's field with a value \ - outside the valid range is undefined behavior", UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationDetails::InitializingTypeWith, ), } } @@ -163,9 +157,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { match (cast_in, cast_out) { (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => { self.require_unsafe( - "cast of pointer to int", - "casting pointers to integers in constants", UnsafetyViolationKind::General, + UnsafetyViolationDetails::CastOfPointerToInt, ); } _ => {} @@ -190,11 +183,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { self.require_unsafe( - "borrow of packed field", - "fields of packed structs might be misaligned: dereferencing a \ - misaligned pointer or even just creating a misaligned reference \ - is undefined behavior", UnsafetyViolationKind::BorrowPacked, + UnsafetyViolationDetails::BorrowOfPackedField, ); } } @@ -204,11 +194,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { self.require_unsafe( - "borrow of packed field", - "fields of packed structs might be misaligned: dereferencing a \ - misaligned pointer or even just creating a misaligned reference \ - is undefined behavior", UnsafetyViolationKind::BorrowPacked, + UnsafetyViolationDetails::BorrowOfPackedField, ); } } @@ -219,19 +206,14 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( - "use of mutable static", - "mutable statics can be mutated by multiple threads: aliasing \ - violations or data races will cause undefined behavior", UnsafetyViolationKind::General, + UnsafetyViolationDetails::UseOfMutableStatic, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( - "use of extern static", - "extern statics are not controlled by the Rust type system: \ - invalid data, aliasing violations or data races will cause \ - undefined behavior", UnsafetyViolationKind::General, + UnsafetyViolationDetails::UseOfExternStatic, ); return; } @@ -246,11 +228,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty; match base_ty.kind { ty::RawPtr(..) => self.require_unsafe( - "dereference of raw pointer", - "raw pointers may be NULL, dangling or unaligned; they can violate \ - aliasing rules and cause data races: all of these are undefined \ - behavior", UnsafetyViolationKind::General, + UnsafetyViolationDetails::DerefOfRawPointer, ), ty::Adt(adt, _) => { if adt.is_union() { @@ -271,21 +250,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.param_env, ) { self.require_unsafe( - "assignment to non-`Copy` union field", - "the previous content of the field will be dropped, which \ - causes undefined behavior if the field was not properly \ - initialized", UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationDetails::AssignToNonCopyUnionField, ) } else { // write to non-move union, safe } } else { self.require_unsafe( - "access to union field", - "the field may not be properly initialized: using \ - uninitialized data will cause undefined behavior", UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationDetails::AccessToUnionField, ) } } @@ -298,12 +272,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { - fn require_unsafe( - &mut self, - description: &'static str, - details: &'static str, - kind: UnsafetyViolationKind, - ) { + fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) { let source_info = self.source_info; let lint_root = self.body.source_scopes[self.source_info.scope] .local_data @@ -311,13 +280,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { .assert_crate_local() .lint_root; self.register_violations( - &[UnsafetyViolation { - source_info, - lint_root, - description: Symbol::intern(description), - details: Symbol::intern(details), - kind, - }], + &[UnsafetyViolation { source_info, lint_root, kind, details }], &[], ); } @@ -434,12 +397,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { if self.tcx.layout_scalar_valid_range(def.did) != (Bound::Unbounded, Bound::Unbounded) { - let (description, details) = if is_mut_use { - ( - "mutation of layout constrained field", - "mutating layout constrained fields cannot statically be \ - checked for valid values", - ) + let details = if is_mut_use { + UnsafetyViolationDetails::MutationOfLayoutConstrainedField // Check `is_freeze` as late as possible to avoid cycle errors // with opaque types. @@ -448,21 +407,11 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { .ty .is_freeze(self.tcx.at(self.source_info.span), self.param_env) { - ( - "borrow of layout constrained field with interior \ - mutability", - "references to fields of layout constrained fields \ - lose the constraints. Coupled with interior mutability, \ - the field can be changed to invalid values", - ) + UnsafetyViolationDetails::BorrowOfLayoutConstrainedField } else { continue; }; - self.require_unsafe( - description, - details, - UnsafetyViolationKind::GeneralAndConstFn, - ); + self.require_unsafe(UnsafetyViolationKind::GeneralAndConstFn, details); } } } @@ -480,9 +429,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { // Is `callee_features` a subset of `calling_features`? if !callee_features.iter().all(|feature| self_features.contains(feature)) { self.require_unsafe( - "call to function with `#[target_feature]`", - "can only be called if the required target features are available", UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationDetails::CallToFunctionWith, ) } } @@ -675,9 +623,9 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { let UnsafetyCheckResult { violations, unsafe_blocks } = tcx.unsafety_check_result(def_id); - for &UnsafetyViolation { source_info, lint_root, description, details, kind } in - violations.iter() - { + for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() { + let (description, note) = details.description_and_note(); + // Report an error. let unsafe_fn_msg = if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" }; @@ -693,8 +641,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { description, unsafe_fn_msg, ) - .span_label(source_info.span, &*description.as_str()) - .note(&details.as_str()) + .span_label(source_info.span, description) + .note(note) .emit(); } UnsafetyViolationKind::BorrowPacked => { @@ -712,7 +660,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { "{} is unsafe and requires unsafe{} block (error E0133)", description, unsafe_fn_msg, )) - .note(&details.as_str()) + .note(note) .emit() }, ) @@ -727,8 +675,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { "{} is unsafe and requires unsafe block (error E0133)", description, )) - .span_label(source_info.span, &*description.as_str()) - .note(&details.as_str()) + .span_label(source_info.span, description) + .note(note) .emit(); }, ), @@ -756,8 +704,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { "{} is unsafe and requires unsafe block (error E0133)", description, )) - .span_label(source_info.span, &*description.as_str()) - .note(&details.as_str()) + .span_label(source_info.span, description) + .note(note) .emit(); }) } From a4ba18164a70d61eeed5b36a4cdcc6ed523a7d55 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 Jul 2020 16:29:44 +1000 Subject: [PATCH 50/50] Remove some `Symbol:as_str()` calls. --- src/librustc_middle/ty/print/pretty.rs | 6 +++--- src/librustc_middle/ty/query/profiling_support.rs | 7 ++++--- src/librustc_span/symbol.rs | 2 ++ src/librustc_trait_selection/traits/error_reporting/mod.rs | 4 ++-- src/librustc_typeck/check/demand.rs | 4 ++-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index b50d2852c1c5c..043d85cb6efa6 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -1440,12 +1440,12 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { // FIXME(eddyb) `name` should never be empty, but it // currently is for `extern { ... }` "foreign modules". - let name = disambiguated_data.data.as_symbol().as_str(); - if !name.is_empty() { + let name = disambiguated_data.data.as_symbol(); + if name != kw::Invalid { if !self.empty_path { write!(self, "::")?; } - if Ident::from_str(&name).is_raw_guess() { + if Ident::with_dummy_span(name).is_raw_guess() { write!(self, "r#")?; } write!(self, "{}", name)?; diff --git a/src/librustc_middle/ty/query/profiling_support.rs b/src/librustc_middle/ty/query/profiling_support.rs index 3c44662441890..0683dc0201129 100644 --- a/src/librustc_middle/ty/query/profiling_support.rs +++ b/src/librustc_middle/ty/query/profiling_support.rs @@ -60,12 +60,12 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { match def_key.disambiguated_data.data { DefPathData::CrateRoot => { - name = self.tcx.original_crate_name(def_id.krate).as_str(); + name = self.tcx.original_crate_name(def_id.krate); dis = ""; end_index = 3; } other => { - name = other.as_symbol().as_str(); + name = other.as_symbol(); if def_key.disambiguated_data.disambiguator == 0 { dis = ""; end_index = 3; @@ -79,10 +79,11 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { } } + let name = &*name.as_str(); let components = [ StringComponent::Ref(parent_string_id), StringComponent::Value("::"), - StringComponent::Value(&name[..]), + StringComponent::Value(name), StringComponent::Value(dis), ]; diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index c4c6fcec4dc5a..3112e3101ce57 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -252,6 +252,7 @@ symbols! { allowed, always, and, + and_then, any, arbitrary_enum_discriminant, arbitrary_self_types, @@ -649,6 +650,7 @@ symbols! { main, managed_boxes, manually_drop, + map, marker, marker_trait_attr, masked, diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 79d5c148ce4fe..a9b045cee6087 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -26,7 +26,7 @@ use rustc_middle::ty::{ TypeFoldable, WithConstness, }; use rustc_session::DiagnosticMessageId; -use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; use std::fmt; @@ -1524,7 +1524,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code) { let generics = self.tcx.generics_of(*def_id); - if generics.params.iter().any(|p| p.name.as_str() != "Self") + if generics.params.iter().any(|p| p.name != kw::SelfUpper) && !snippet.ends_with('>') { // FIXME: To avoid spurious suggestions in functions where type arguments diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 9a9630f095886..f575548ddd638 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -322,12 +322,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let self_ty = self.tables.borrow().node_type(method_expr[0].hir_id); let self_ty = format!("{:?}", self_ty); - let name = method_path.ident.as_str(); + let name = method_path.ident.name; let is_as_ref_able = (self_ty.starts_with("&std::option::Option") || self_ty.starts_with("&std::result::Result") || self_ty.starts_with("std::option::Option") || self_ty.starts_with("std::result::Result")) - && (name == "map" || name == "and_then"); + && (name == sym::map || name == sym::and_then); match (is_as_ref_able, self.sess().source_map().span_to_snippet(*method_span)) { (true, Ok(src)) => { let suggestion = format!("as_ref().{}", src);