Auto merge of #149979 - ChrisDenton:rollup-9rvyn3h, r=ChrisDenton
Rollup of 8 pull requests Successful merges: - rust-lang/rust#148755 (Constify `DropGuard::dismiss` and trait impls) - rust-lang/rust#148825 (Add SystemTime::{MIN, MAX}) - rust-lang/rust#149272 (Fix vec iter zst alignment) - rust-lang/rust#149417 (tidy: Detect outdated workspaces in workspace list) - rust-lang/rust#149773 (fix va_list test by adding a llvmir signext check) - rust-lang/rust#149894 (Update to mdbook 0.5) - rust-lang/rust#149955 (Fix typo in armv7a-vex-v5 documentation) - rust-lang/rust#149972 (Enable to ping LoongArch group via triagebot) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0208ee09be
34 changed files with 691 additions and 893 deletions
|
|
@ -411,7 +411,12 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
|
|||
// SAFETY: same as for advance_by()
|
||||
self.end = unsafe { self.end.sub(step_size) };
|
||||
}
|
||||
let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size);
|
||||
let to_drop = if T::IS_ZST {
|
||||
// ZST may cause unalignment
|
||||
ptr::slice_from_raw_parts_mut(ptr::NonNull::<T>::dangling().as_ptr(), step_size)
|
||||
} else {
|
||||
ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size)
|
||||
};
|
||||
// SAFETY: same as for advance_by()
|
||||
unsafe {
|
||||
ptr::drop_in_place(to_drop);
|
||||
|
|
|
|||
|
|
@ -2717,3 +2717,35 @@ fn vec_null_ptr_roundtrip() {
|
|||
let new = roundtripped.with_addr(ptr.addr());
|
||||
unsafe { new.read() };
|
||||
}
|
||||
|
||||
// Regression test for Undefined Behavior (UB) caused by IntoIter::nth_back (#148682)
|
||||
// when dealing with high-aligned Zero-Sized Types (ZSTs).
|
||||
use std::collections::{BTreeMap, BinaryHeap, HashMap, LinkedList, VecDeque};
|
||||
#[test]
|
||||
fn zst_collections_iter_nth_back_regression() {
|
||||
#[repr(align(8))]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||
struct Thing;
|
||||
let v = vec![Thing, Thing];
|
||||
let _ = v.into_iter().nth_back(1);
|
||||
let mut d = VecDeque::new();
|
||||
d.push_back(Thing);
|
||||
d.push_back(Thing);
|
||||
let _ = d.into_iter().nth_back(1);
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert(0, Thing);
|
||||
map.insert(1, Thing);
|
||||
let _ = map.into_values().nth_back(0);
|
||||
let mut hash_map = HashMap::new();
|
||||
hash_map.insert(1, Thing);
|
||||
hash_map.insert(2, Thing);
|
||||
let _ = hash_map.into_values().nth(1);
|
||||
let mut heap = BinaryHeap::new();
|
||||
heap.push(Thing);
|
||||
heap.push(Thing);
|
||||
let _ = heap.into_iter().nth_back(1);
|
||||
let mut list = LinkedList::new();
|
||||
list.push_back(Thing);
|
||||
list.push_back(Thing);
|
||||
let _ = list.into_iter().nth_back(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::fmt::{self, Debug};
|
||||
use crate::marker::Destruct;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::ops::{Deref, DerefMut};
|
||||
|
||||
|
|
@ -78,32 +79,37 @@ where
|
|||
///
|
||||
/// let value = String::from("Nori likes chicken");
|
||||
/// let guard = DropGuard::new(value, |s| println!("{s}"));
|
||||
/// assert_eq!(guard.dismiss(), "Nori likes chicken");
|
||||
/// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken");
|
||||
/// ```
|
||||
#[unstable(feature = "drop_guard", issue = "144426")]
|
||||
#[rustc_const_unstable(feature = "const_drop_guard", issue = "none")]
|
||||
#[inline]
|
||||
pub fn dismiss(self) -> T {
|
||||
pub const fn dismiss(guard: Self) -> T
|
||||
where
|
||||
F: [const] Destruct,
|
||||
{
|
||||
// First we ensure that dropping the guard will not trigger
|
||||
// its destructor
|
||||
let mut this = ManuallyDrop::new(self);
|
||||
let mut guard = ManuallyDrop::new(guard);
|
||||
|
||||
// Next we manually read the stored value from the guard.
|
||||
//
|
||||
// SAFETY: this is safe because we've taken ownership of the guard.
|
||||
let value = unsafe { ManuallyDrop::take(&mut this.inner) };
|
||||
let value = unsafe { ManuallyDrop::take(&mut guard.inner) };
|
||||
|
||||
// Finally we drop the stored closure. We do this *after* having read
|
||||
// the value, so that even if the closure's `drop` function panics,
|
||||
// unwinding still tries to drop the value.
|
||||
//
|
||||
// SAFETY: this is safe because we've taken ownership of the guard.
|
||||
unsafe { ManuallyDrop::drop(&mut this.f) };
|
||||
unsafe { ManuallyDrop::drop(&mut guard.f) };
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "drop_guard", issue = "144426")]
|
||||
impl<T, F> Deref for DropGuard<T, F>
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
|
||||
impl<T, F> const Deref for DropGuard<T, F>
|
||||
where
|
||||
F: FnOnce(T),
|
||||
{
|
||||
|
|
@ -115,7 +121,8 @@ where
|
|||
}
|
||||
|
||||
#[unstable(feature = "drop_guard", issue = "144426")]
|
||||
impl<T, F> DerefMut for DropGuard<T, F>
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
|
||||
impl<T, F> const DerefMut for DropGuard<T, F>
|
||||
where
|
||||
F: FnOnce(T),
|
||||
{
|
||||
|
|
@ -125,9 +132,10 @@ where
|
|||
}
|
||||
|
||||
#[unstable(feature = "drop_guard", issue = "144426")]
|
||||
impl<T, F> Drop for DropGuard<T, F>
|
||||
#[rustc_const_unstable(feature = "const_drop_guard", issue = "none")]
|
||||
impl<T, F> const Drop for DropGuard<T, F>
|
||||
where
|
||||
F: FnOnce(T),
|
||||
F: [const] FnOnce(T),
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: `DropGuard` is in the process of being dropped.
|
||||
|
|
|
|||
|
|
@ -815,7 +815,7 @@ fn drop_guard_into_inner() {
|
|||
let dropped = Cell::new(false);
|
||||
let value = DropGuard::new(42, |_| dropped.set(true));
|
||||
let guard = DropGuard::new(value, |_| dropped.set(true));
|
||||
let inner = guard.dismiss();
|
||||
let inner = DropGuard::dismiss(guard);
|
||||
assert_eq!(dropped.get(), false);
|
||||
assert_eq!(*inner, 42);
|
||||
}
|
||||
|
|
@ -837,7 +837,7 @@ fn drop_guard_always_drops_value_if_closure_drop_unwinds() {
|
|||
// run the destructor of the value we passed, which we validate.
|
||||
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||
let guard = DropGuard::new(value_with_tracked_destruction, closure_that_panics_on_drop);
|
||||
guard.dismiss();
|
||||
DropGuard::dismiss(guard);
|
||||
}));
|
||||
assert!(value_was_dropped);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ struct Timespec {
|
|||
}
|
||||
|
||||
impl Timespec {
|
||||
const MAX: Timespec = Self::new(i64::MAX, 1_000_000_000 - 1);
|
||||
|
||||
const MIN: Timespec = Self::new(i64::MIN, 0);
|
||||
|
||||
const fn zero() -> Timespec {
|
||||
Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
|
||||
}
|
||||
|
|
@ -209,6 +213,10 @@ pub struct SystemTime(Timespec);
|
|||
pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime { t: Timespec::MAX };
|
||||
|
||||
pub const MIN: SystemTime = SystemTime { t: Timespec::MIN };
|
||||
|
||||
pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime {
|
||||
SystemTime(Timespec::new(tv_sec, tv_nsec))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ impl Instant {
|
|||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime(Duration::MAX);
|
||||
|
||||
pub const MIN: SystemTime = SystemTime(Duration::ZERO);
|
||||
|
||||
pub fn now() -> SystemTime {
|
||||
SystemTime(usercalls::insecure_time())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ pub struct SystemTime(abi::time_t);
|
|||
pub const UNIX_EPOCH: SystemTime = SystemTime(0);
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime(abi::time_t::MAX);
|
||||
|
||||
pub const MIN: SystemTime = SystemTime(abi::time_t::MIN);
|
||||
|
||||
pub fn now() -> SystemTime {
|
||||
let rtc = unsafe {
|
||||
let mut out = MaybeUninit::zeroed();
|
||||
|
|
|
|||
|
|
@ -70,6 +70,23 @@ impl Instant {
|
|||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = MAX_UEFI_TIME;
|
||||
|
||||
pub const MIN: SystemTime = SystemTime::from_uefi(r_efi::efi::Time {
|
||||
year: 1900,
|
||||
month: 1,
|
||||
day: 1,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
nanosecond: 0,
|
||||
timezone: -1440,
|
||||
daylight: 0,
|
||||
pad1: 0,
|
||||
pad2: 0,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Option<Self> {
|
||||
match system_time_internal::from_uefi(&t) {
|
||||
Some(x) => Some(Self(x)),
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ pub(crate) struct Timespec {
|
|||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime { t: Timespec::MAX };
|
||||
|
||||
pub const MIN: SystemTime = SystemTime { t: Timespec::MIN };
|
||||
|
||||
#[cfg_attr(any(target_os = "horizon", target_os = "hurd"), allow(unused))]
|
||||
pub fn new(tv_sec: i64, tv_nsec: i64) -> Result<SystemTime, io::Error> {
|
||||
Ok(SystemTime { t: Timespec::new(tv_sec, tv_nsec)? })
|
||||
|
|
@ -62,6 +66,13 @@ impl fmt::Debug for SystemTime {
|
|||
}
|
||||
|
||||
impl Timespec {
|
||||
const MAX: Timespec = unsafe { Self::new_unchecked(i64::MAX, 1_000_000_000 - 1) };
|
||||
|
||||
// As described below, on Apple OS, dates before epoch are represented differently.
|
||||
// This is not an issue here however, because we are using tv_sec = i64::MIN,
|
||||
// which will cause the compatibility wrapper to not be executed at all.
|
||||
const MIN: Timespec = unsafe { Self::new_unchecked(i64::MIN, 0) };
|
||||
|
||||
const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> Timespec {
|
||||
Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds::new_unchecked(tv_nsec as u32) } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ impl Instant {
|
|||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime(Duration::MAX);
|
||||
|
||||
pub const MIN: SystemTime = SystemTime(Duration::ZERO);
|
||||
|
||||
pub fn now() -> SystemTime {
|
||||
panic!("time not implemented on this platform")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,16 @@ impl Instant {
|
|||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime {
|
||||
t: c::FILETIME {
|
||||
dwLowDateTime: (i64::MAX & 0xFFFFFFFF) as u32,
|
||||
dwHighDateTime: (i64::MAX >> 32) as u32,
|
||||
},
|
||||
};
|
||||
|
||||
pub const MIN: SystemTime =
|
||||
SystemTime { t: c::FILETIME { dwLowDateTime: 0, dwHighDateTime: 0 } };
|
||||
|
||||
pub fn now() -> SystemTime {
|
||||
unsafe {
|
||||
let mut t: SystemTime = mem::zeroed();
|
||||
|
|
@ -101,8 +111,13 @@ impl SystemTime {
|
|||
}
|
||||
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?;
|
||||
Some(SystemTime::from_intervals(intervals))
|
||||
// Windows does not support times before 1601, hence why we don't
|
||||
// support negatives. In order to tackle this, we try to convert the
|
||||
// resulting value into an u64, which should obviously fail in the case
|
||||
// that the value is below zero.
|
||||
let intervals: u64 =
|
||||
self.intervals().checked_sub(checked_dur2intervals(other)?)?.try_into().ok()?;
|
||||
Some(SystemTime::from_intervals(intervals as i64))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ impl Instant {
|
|||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime(Duration::MAX);
|
||||
|
||||
pub const MIN: SystemTime = SystemTime(Duration::ZERO);
|
||||
|
||||
pub fn now() -> SystemTime {
|
||||
let result = blocking_scalar(systime_server(), GetUtcTimeMs.into())
|
||||
.expect("failed to request utc time in ms");
|
||||
|
|
|
|||
|
|
@ -511,6 +511,83 @@ impl SystemTime {
|
|||
#[stable(feature = "assoc_unix_epoch", since = "1.28.0")]
|
||||
pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH;
|
||||
|
||||
/// Represents the maximum value representable by [`SystemTime`] on this platform.
|
||||
///
|
||||
/// This value differs a lot between platforms, but it is always the case
|
||||
/// that any positive addition of a [`Duration`], whose value is greater
|
||||
/// than or equal to the time precision of the operating system, to
|
||||
/// [`SystemTime::MAX`] will fail.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(time_systemtime_limits)]
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// // Adding zero will change nothing.
|
||||
/// assert_eq!(SystemTime::MAX.checked_add(Duration::ZERO), Some(SystemTime::MAX));
|
||||
///
|
||||
/// // But adding just one second will already fail ...
|
||||
/// //
|
||||
/// // Keep in mind that this in fact may succeed, if the Duration is
|
||||
/// // smaller than the time precision of the operating system, which
|
||||
/// // happens to be 1ns on most operating systems, with Windows being the
|
||||
/// // notable exception by using 100ns, hence why this example uses 1s.
|
||||
/// assert_eq!(SystemTime::MAX.checked_add(Duration::new(1, 0)), None);
|
||||
///
|
||||
/// // Utilize this for saturating arithmetic to improve error handling.
|
||||
/// // In this case, we will use a certificate with a timestamp in the
|
||||
/// // future as a practical example.
|
||||
/// let configured_offset = Duration::from_secs(60 * 60 * 24);
|
||||
/// let valid_after =
|
||||
/// SystemTime::now()
|
||||
/// .checked_add(configured_offset)
|
||||
/// .unwrap_or(SystemTime::MAX);
|
||||
/// ```
|
||||
#[unstable(feature = "time_systemtime_limits", issue = "149067")]
|
||||
pub const MAX: SystemTime = SystemTime(time::SystemTime::MAX);
|
||||
|
||||
/// Represents the minimum value representable by [`SystemTime`] on this platform.
|
||||
///
|
||||
/// This value differs a lot between platforms, but it is always the case
|
||||
/// that any positive subtraction of a [`Duration`] from, whose value is
|
||||
/// greater than or equal to the time precision of the operating system, to
|
||||
/// [`SystemTime::MIN`] will fail.
|
||||
///
|
||||
/// Depending on the platform, this may be either less than or equal to
|
||||
/// [`SystemTime::UNIX_EPOCH`], depending on whether the operating system
|
||||
/// supports the representation of timestamps before the Unix epoch or not.
|
||||
/// However, it is always guaranteed that a [`SystemTime::UNIX_EPOCH`] fits
|
||||
/// between a [`SystemTime::MIN`] and [`SystemTime::MAX`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(time_systemtime_limits)]
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// // Subtracting zero will change nothing.
|
||||
/// assert_eq!(SystemTime::MIN.checked_sub(Duration::ZERO), Some(SystemTime::MIN));
|
||||
///
|
||||
/// // But subtracting just one second will already fail.
|
||||
/// //
|
||||
/// // Keep in mind that this in fact may succeed, if the Duration is
|
||||
/// // smaller than the time precision of the operating system, which
|
||||
/// // happens to be 1ns on most operating systems, with Windows being the
|
||||
/// // notable exception by using 100ns, hence why this example uses 1s.
|
||||
/// assert_eq!(SystemTime::MIN.checked_sub(Duration::new(1, 0)), None);
|
||||
///
|
||||
/// // Utilize this for saturating arithmetic to improve error handling.
|
||||
/// // In this case, we will use a cache expiry as a practical example.
|
||||
/// let configured_expiry = Duration::from_secs(60 * 3);
|
||||
/// let expiry_threshold =
|
||||
/// SystemTime::now()
|
||||
/// .checked_sub(configured_expiry)
|
||||
/// .unwrap_or(SystemTime::MIN);
|
||||
/// ```
|
||||
#[unstable(feature = "time_systemtime_limits", issue = "149067")]
|
||||
pub const MIN: SystemTime = SystemTime(time::SystemTime::MIN);
|
||||
|
||||
/// Returns the system time corresponding to "now".
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -588,6 +665,9 @@ impl SystemTime {
|
|||
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
|
||||
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
///
|
||||
/// In the case that the `duration` is smaller than the time precision of the operating
|
||||
/// system, `Some(self)` will be returned.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_add_duration(&duration).map(SystemTime)
|
||||
|
|
@ -596,6 +676,9 @@ impl SystemTime {
|
|||
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
|
||||
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
///
|
||||
/// In the case that the `duration` is smaller than the time precision of the operating
|
||||
/// system, `Some(self)` will be returned.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_sub_duration(&duration).map(SystemTime)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#![feature(duration_constants)]
|
||||
#![feature(time_systemtime_limits)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
|
|
@ -237,9 +238,34 @@ fn system_time_duration_since_max_range_on_unix() {
|
|||
let min = SystemTime::UNIX_EPOCH - (Duration::new(i64::MAX as u64 + 1, 0));
|
||||
let max = SystemTime::UNIX_EPOCH + (Duration::new(i64::MAX as u64, 999_999_999));
|
||||
|
||||
assert_eq!(min, SystemTime::MIN);
|
||||
assert_eq!(max, SystemTime::MAX);
|
||||
|
||||
let delta_a = max.duration_since(min).expect("duration_since overflow");
|
||||
let delta_b = min.duration_since(max).expect_err("duration_since overflow").duration();
|
||||
|
||||
assert_eq!(Duration::MAX, delta_a);
|
||||
assert_eq!(Duration::MAX, delta_b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn system_time_max_min() {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
/// Most (all?) non-Windows systems have nanosecond precision.
|
||||
const MIN_INTERVAL: Duration = Duration::new(0, 1);
|
||||
#[cfg(target_os = "windows")]
|
||||
/// Windows' time precision is at 100ns.
|
||||
const MIN_INTERVAL: Duration = Duration::new(0, 100);
|
||||
|
||||
// First, test everything with checked_* and Duration::ZERO.
|
||||
assert_eq!(SystemTime::MAX.checked_add(Duration::ZERO), Some(SystemTime::MAX));
|
||||
assert_eq!(SystemTime::MAX.checked_sub(Duration::ZERO), Some(SystemTime::MAX));
|
||||
assert_eq!(SystemTime::MIN.checked_add(Duration::ZERO), Some(SystemTime::MIN));
|
||||
assert_eq!(SystemTime::MIN.checked_sub(Duration::ZERO), Some(SystemTime::MIN));
|
||||
|
||||
// Now do the same again with checked_* but try by ± the lowest time precision.
|
||||
assert!(SystemTime::MAX.checked_add(MIN_INTERVAL).is_none());
|
||||
assert!(SystemTime::MAX.checked_sub(MIN_INTERVAL).is_some());
|
||||
assert!(SystemTime::MIN.checked_add(MIN_INTERVAL).is_some());
|
||||
assert!(SystemTime::MIN.checked_sub(MIN_INTERVAL).is_none());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 8c0eacd5c4acbb650497454f3a58c9e8083202a4
|
||||
Subproject commit 39aeceaa3aeab845bc4517e7a44e48727d3b9dbe
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 9cf5443d632673c4d41edad5e8ed8be86eeb3b8f
|
||||
Subproject commit c3c0f0b3da26610138b7ba7663f60cd2c68cf184
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 0fe83ab28985b99aba36a1f0dbde3e08286fefda
|
||||
Subproject commit 9fe8fa599ad228dda74f240cc32b54bc5c1aa3e6
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit b14b4e40f53ca468beaf2f5d0dfb4f4c4ba6bc7b
|
||||
Subproject commit 50c5de90487b68d429a30cc9466dc8f5b410128f
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 111cfae2f9c3a43f7b0ff8fa68c51cc8f930637c
|
||||
Subproject commit 7d21279e40e8f0e91c2a22c5148dd2d745aef8b6
|
||||
|
|
@ -1,13 +1,9 @@
|
|||
[book]
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "The rustc book"
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/rust-lang/rust/tree/HEAD/src/doc/rustc"
|
||||
edit-url-template = "https://github.com/rust-lang/rust/edit/HEAD/src/doc/rustc/{path}"
|
||||
additional-css = ["theme/pagetoc.css"]
|
||||
additional-js = ["theme/pagetoc.js"]
|
||||
|
||||
[output.html.search]
|
||||
use-boolean-and = true
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ This target is cross-compiled. Dynamic linking is unsupported.
|
|||
|
||||
`#![no_std]` crates can be built using `build-std` to build `core` and `panic_abort` and optionally `alloc`. Unwinding panics are not yet supported on this target.
|
||||
|
||||
`std` has only partial support due platform limitations. Notably:
|
||||
`std` has only partial support due to platform limitations. Notably:
|
||||
- `std::process` and `std::net` are unimplemented. `std::thread` only supports sleeping and yielding, as this is a single-threaded environment.
|
||||
- `std::time` has full support for `Instant`, but no support for `SystemTime`.
|
||||
- `std::io` has full support for `stdin`/`stdout`/`stderr`. `stdout` and `stderr` both write to to USB channel 1 on this platform and are not differentiated.
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
/* Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) */
|
||||
|
||||
:root {
|
||||
--toc-width: 270px;
|
||||
--center-content-toc-shift: calc(-1 * var(--toc-width) / 2);
|
||||
}
|
||||
|
||||
.nav-chapters {
|
||||
/* adjust width of buttons that bring to the previous or the next page */
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
@media only screen {
|
||||
@media (max-width: 1179px) {
|
||||
.sidebar-hidden #sidetoc {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1439px) {
|
||||
.sidebar-visible #sidetoc {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (1180px <= width <= 1439px) {
|
||||
.sidebar-hidden main {
|
||||
position: relative;
|
||||
left: var(--center-content-toc-shift);
|
||||
}
|
||||
}
|
||||
|
||||
@media (1440px <= width <= 1700px) {
|
||||
.sidebar-visible main {
|
||||
position: relative;
|
||||
left: var(--center-content-toc-shift);
|
||||
}
|
||||
}
|
||||
|
||||
#sidetoc {
|
||||
margin-left: calc(100% + 20px);
|
||||
}
|
||||
#pagetoc {
|
||||
position: fixed;
|
||||
/* adjust TOC width */
|
||||
width: var(--toc-width);
|
||||
height: calc(100vh - var(--menu-bar-height) - 0.67em * 4);
|
||||
overflow: auto;
|
||||
}
|
||||
#pagetoc a {
|
||||
border-left: 1px solid var(--sidebar-bg);
|
||||
color: var(--fg);
|
||||
display: block;
|
||||
padding-bottom: 5px;
|
||||
padding-top: 5px;
|
||||
padding-left: 10px;
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
}
|
||||
#pagetoc a:hover,
|
||||
#pagetoc a.active {
|
||||
background: var(--sidebar-bg);
|
||||
color: var(--sidebar-active) !important;
|
||||
}
|
||||
#pagetoc .active {
|
||||
background: var(--sidebar-bg);
|
||||
color: var(--sidebar-active);
|
||||
}
|
||||
#pagetoc .pagetoc-H2 {
|
||||
padding-left: 20px;
|
||||
}
|
||||
#pagetoc .pagetoc-H3 {
|
||||
padding-left: 40px;
|
||||
}
|
||||
#pagetoc .pagetoc-H4 {
|
||||
padding-left: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
#sidetoc {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL)
|
||||
|
||||
let activeHref = location.href;
|
||||
function updatePageToc(elem = undefined) {
|
||||
let selectedPageTocElem = elem;
|
||||
const pagetoc = document.getElementById("pagetoc");
|
||||
|
||||
function getRect(element) {
|
||||
return element.getBoundingClientRect();
|
||||
}
|
||||
|
||||
function overflowTop(container, element) {
|
||||
return getRect(container).top - getRect(element).top;
|
||||
}
|
||||
|
||||
function overflowBottom(container, element) {
|
||||
return getRect(container).bottom - getRect(element).bottom;
|
||||
}
|
||||
|
||||
// We've not selected a heading to highlight, and the URL needs updating
|
||||
// so we need to find a heading based on the URL
|
||||
if (selectedPageTocElem === undefined && location.href !== activeHref) {
|
||||
activeHref = location.href;
|
||||
for (const pageTocElement of pagetoc.children) {
|
||||
if (pageTocElement.href === activeHref) {
|
||||
selectedPageTocElem = pageTocElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We still don't have a selected heading, let's try and find the most
|
||||
// suitable heading based on the scroll position
|
||||
if (selectedPageTocElem === undefined) {
|
||||
const margin = window.innerHeight / 3;
|
||||
|
||||
const headers = document.getElementsByClassName("header");
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
const header = headers[i];
|
||||
if (selectedPageTocElem === undefined && getRect(header).top >= 0) {
|
||||
if (getRect(header).top < margin) {
|
||||
selectedPageTocElem = header;
|
||||
} else {
|
||||
selectedPageTocElem = headers[Math.max(0, i - 1)];
|
||||
}
|
||||
}
|
||||
// a very long last section's heading is over the screen
|
||||
if (selectedPageTocElem === undefined && i === headers.length - 1) {
|
||||
selectedPageTocElem = header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the active flag from all pagetoc elements
|
||||
for (const pageTocElement of pagetoc.children) {
|
||||
pageTocElement.classList.remove("active");
|
||||
}
|
||||
|
||||
// If we have a selected heading, set it to active and scroll to it
|
||||
if (selectedPageTocElem !== undefined) {
|
||||
for (const pageTocElement of pagetoc.children) {
|
||||
if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) {
|
||||
pageTocElement.classList.add("active");
|
||||
if (overflowTop(pagetoc, pageTocElement) > 0) {
|
||||
pagetoc.scrollTop = pageTocElement.offsetTop;
|
||||
}
|
||||
if (overflowBottom(pagetoc, pageTocElement) < 0) {
|
||||
pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById("sidetoc") === null &&
|
||||
document.getElementsByClassName("header").length > 0) {
|
||||
// The sidetoc element doesn't exist yet, let's create it
|
||||
|
||||
// Create the empty sidetoc and pagetoc elements
|
||||
const sidetoc = document.createElement("div");
|
||||
const pagetoc = document.createElement("div");
|
||||
sidetoc.id = "sidetoc";
|
||||
pagetoc.id = "pagetoc";
|
||||
sidetoc.appendChild(pagetoc);
|
||||
|
||||
// And append them to the current DOM
|
||||
const main = document.querySelector('main');
|
||||
main.insertBefore(sidetoc, main.firstChild);
|
||||
|
||||
// Populate sidebar on load
|
||||
window.addEventListener("load", () => {
|
||||
for (const header of document.getElementsByClassName("header")) {
|
||||
const link = document.createElement("a");
|
||||
link.innerHTML = header.innerHTML;
|
||||
link.href = header.hash;
|
||||
link.classList.add("pagetoc-" + header.parentElement.tagName);
|
||||
document.getElementById("pagetoc").appendChild(link);
|
||||
link.onclick = () => updatePageToc(link);
|
||||
}
|
||||
updatePageToc();
|
||||
});
|
||||
|
||||
// Update page table of contents selected heading on scroll
|
||||
window.addEventListener("scroll", () => updatePageToc());
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ Rustdoc's HTML output includes a settings menu, and this chapter describes what
|
|||
each setting in this menu does.
|
||||
|
||||
It can be accessed by clicking on the gear button
|
||||
(<i class="fa fa-cog" aria-hidden="true"></i>) in the upper right.
|
||||
(<i class="fas fa-gear" aria-hidden="true"></i>) in the upper right.
|
||||
|
||||
## Changing displayed theme
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
[book]
|
||||
title = "The Rust Style Guide"
|
||||
author = "The Rust Style Team"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
authors = ["The Rust Style Team"]
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
[book]
|
||||
title = "The Rust Unstable Book"
|
||||
author = "The Rust Community"
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/rust-lang/rust/tree/HEAD/src/doc/unstable-book"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ edition = "2021"
|
|||
workspace = "../rustbook"
|
||||
|
||||
[dependencies]
|
||||
mdbook = { version = "0.4", default-features = false, features = ["search"] }
|
||||
mdbook-driver = { version = "0.5.1", features = ["search"] }
|
||||
mdbook-summary = "0.5.1"
|
||||
|
||||
[[bin]]
|
||||
name = "error_index_generator"
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ use std::io::Write;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
||||
use mdbook::book::{BookItem, Chapter, parse_summary};
|
||||
use mdbook::{Config, MDBook};
|
||||
use mdbook_driver::MDBook;
|
||||
use mdbook_driver::book::{BookItem, Chapter};
|
||||
use mdbook_driver::config::Config;
|
||||
use mdbook_summary::parse_summary;
|
||||
use rustc_errors::codes::DIAGNOSTICS;
|
||||
|
||||
enum OutputFormat {
|
||||
|
|
@ -121,7 +123,7 @@ This page lists all the error codes emitted by the Rust compiler.
|
|||
source_path: None,
|
||||
parent_names: Vec::new(),
|
||||
};
|
||||
book.book.sections.push(BookItem::Chapter(chapter));
|
||||
book.book.items.push(BookItem::Chapter(chapter));
|
||||
book.build()?;
|
||||
|
||||
// The error-index used to be generated manually (without mdbook), and the
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -8,14 +8,9 @@ license = "MIT OR Apache-2.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = "4.0.32"
|
||||
env_logger = "0.11"
|
||||
libc = "0.2"
|
||||
mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" }
|
||||
mdbook-i18n-helpers = "0.3.3"
|
||||
clap = { version = "4.0.32", features = ["cargo"] }
|
||||
mdbook-driver = { version = "0.5.2", features = ["search"] }
|
||||
mdbook-i18n-helpers = "0.4.0"
|
||||
mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
|
||||
|
||||
[dependencies.mdbook]
|
||||
version = "0.4.52"
|
||||
default-features = false
|
||||
features = ["search"]
|
||||
mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" }
|
||||
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
|
||||
|
|
|
|||
|
|
@ -2,15 +2,27 @@ use std::env;
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use clap::{ArgMatches, Command, arg, crate_version};
|
||||
use mdbook::MDBook;
|
||||
use mdbook::errors::Result as Result3;
|
||||
use mdbook_driver::MDBook;
|
||||
use mdbook_driver::errors::Result as Result3;
|
||||
use mdbook_i18n_helpers::preprocessors::Gettext;
|
||||
use mdbook_spec::Spec;
|
||||
use mdbook_trpl::{Figure, Listing, Note};
|
||||
|
||||
fn main() {
|
||||
let crate_version = concat!("v", crate_version!());
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
|
||||
let filter = tracing_subscriber::EnvFilter::builder()
|
||||
.with_env_var("MDBOOK_LOG")
|
||||
.with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into())
|
||||
.from_env_lossy();
|
||||
tracing_subscriber::fmt()
|
||||
.without_time()
|
||||
.with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))
|
||||
.with_writer(std::io::stderr)
|
||||
.with_env_filter(filter)
|
||||
.with_target(std::env::var_os("MDBOOK_LOG").is_some())
|
||||
.init();
|
||||
|
||||
// env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
||||
let d_arg = arg!(-d --"dest-dir" <DEST_DIR>
|
||||
"The output directory for your book\n(Defaults to ./book when omitted)")
|
||||
.required(false)
|
||||
|
|
@ -82,60 +94,22 @@ fn main() {
|
|||
};
|
||||
}
|
||||
|
||||
// Build command implementation
|
||||
pub fn build(args: &ArgMatches) -> Result3<()> {
|
||||
fn build(args: &ArgMatches) -> Result3<()> {
|
||||
let book_dir = get_book_dir(args);
|
||||
let mut book = load_book(&book_dir)?;
|
||||
|
||||
if let Some(lang) = args.get_one::<String>("lang") {
|
||||
let gettext = Gettext;
|
||||
book.with_preprocessor(gettext);
|
||||
book.config.set("book.language", lang).unwrap();
|
||||
}
|
||||
|
||||
// Set this to allow us to catch bugs in advance.
|
||||
book.config.build.create_missing = false;
|
||||
|
||||
if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") {
|
||||
book.config.build.build_dir = dest_dir.into();
|
||||
}
|
||||
|
||||
// NOTE: Replacing preprocessors using this technique causes error
|
||||
// messages to be displayed when the original preprocessor doesn't work
|
||||
// (but it otherwise succeeds).
|
||||
//
|
||||
// This should probably be fixed in mdbook to remove the existing
|
||||
// preprocessor, or this should modify the config and use
|
||||
// MDBook::load_with_config.
|
||||
if book.config.get_preprocessor("trpl-note").is_some() {
|
||||
book.with_preprocessor(Note);
|
||||
}
|
||||
|
||||
if book.config.get_preprocessor("trpl-listing").is_some() {
|
||||
book.with_preprocessor(Listing);
|
||||
}
|
||||
|
||||
if book.config.get_preprocessor("trpl-figure").is_some() {
|
||||
book.with_preprocessor(Figure);
|
||||
}
|
||||
|
||||
if book.config.get_preprocessor("spec").is_some() {
|
||||
let rust_root = args.get_one::<PathBuf>("rust-root").cloned();
|
||||
book.with_preprocessor(Spec::new(rust_root)?);
|
||||
}
|
||||
|
||||
book.build()?;
|
||||
|
||||
Ok(())
|
||||
let dest_dir = args.get_one::<PathBuf>("dest-dir");
|
||||
let lang = args.get_one::<String>("lang");
|
||||
let rust_root = args.get_one::<PathBuf>("rust-root");
|
||||
let book = load_book(&book_dir, dest_dir, lang, rust_root.cloned())?;
|
||||
book.build()
|
||||
}
|
||||
|
||||
fn test(args: &ArgMatches) -> Result3<()> {
|
||||
let book_dir = get_book_dir(args);
|
||||
let mut book = load_book(&book_dir, None, None, None)?;
|
||||
let library_paths = args
|
||||
.try_get_one::<Vec<String>>("library-path")?
|
||||
.map(|v| v.iter().map(|s| s.as_str()).collect::<Vec<&str>>())
|
||||
.unwrap_or_default();
|
||||
let mut book = load_book(&book_dir)?;
|
||||
book.test(library_paths)
|
||||
}
|
||||
|
||||
|
|
@ -148,10 +122,52 @@ fn get_book_dir(args: &ArgMatches) -> PathBuf {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_book(book_dir: &Path) -> Result3<MDBook> {
|
||||
fn load_book(
|
||||
book_dir: &Path,
|
||||
dest_dir: Option<&PathBuf>,
|
||||
lang: Option<&String>,
|
||||
rust_root: Option<PathBuf>,
|
||||
) -> Result3<MDBook> {
|
||||
let mut book = MDBook::load(book_dir)?;
|
||||
book.config.set("output.html.input-404", "").unwrap();
|
||||
book.config.set("output.html.hash-files", true).unwrap();
|
||||
|
||||
if let Some(lang) = lang {
|
||||
let gettext = Gettext;
|
||||
book.with_preprocessor(gettext);
|
||||
book.config.set("book.language", lang).unwrap();
|
||||
}
|
||||
|
||||
// Set this to allow us to catch bugs in advance.
|
||||
book.config.build.create_missing = false;
|
||||
|
||||
if let Some(dest_dir) = dest_dir {
|
||||
book.config.build.build_dir = dest_dir.into();
|
||||
}
|
||||
|
||||
// NOTE: Replacing preprocessors using this technique causes error
|
||||
// messages to be displayed when the original preprocessor doesn't work
|
||||
// (but it otherwise succeeds).
|
||||
//
|
||||
// This should probably be fixed in mdbook to remove the existing
|
||||
// preprocessor, or this should modify the config and use
|
||||
// MDBook::load_with_config.
|
||||
if book.config.contains_key("preprocessor.trpl-note") {
|
||||
book.with_preprocessor(Note);
|
||||
}
|
||||
|
||||
if book.config.contains_key("preprocessor.trpl-listing") {
|
||||
book.with_preprocessor(Listing);
|
||||
}
|
||||
|
||||
if book.config.contains_key("preprocessor.trpl-figure") {
|
||||
book.with_preprocessor(Figure);
|
||||
}
|
||||
|
||||
if book.config.contains_key("preprocessor.spec") {
|
||||
book.with_preprocessor(Spec::new(rust_root)?);
|
||||
}
|
||||
|
||||
Ok(book)
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +175,7 @@ fn parse_library_paths(input: &str) -> Result<Vec<String>, String> {
|
|||
Ok(input.split(",").map(String::from).collect())
|
||||
}
|
||||
|
||||
fn handle_error(error: mdbook::errors::Error) -> ! {
|
||||
fn handle_error(error: mdbook_driver::errors::Error) -> ! {
|
||||
eprintln!("Error: {}", error);
|
||||
|
||||
for cause in error.chain().skip(1) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! Checks the licenses of third-party dependencies.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::{File, read_dir};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
|
@ -14,6 +15,25 @@ use crate::diagnostics::{RunningCheck, TidyCtx};
|
|||
#[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"]
|
||||
mod proc_macro_deps;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct ListLocation {
|
||||
path: &'static str,
|
||||
line: u32,
|
||||
}
|
||||
|
||||
impl Display for ListLocation {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}:{}", self.path, self.line)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a [`ListLocation`] for the current location (with an additional offset to the actual list start);
|
||||
macro_rules! location {
|
||||
(+ $offset:literal) => {
|
||||
ListLocation { path: file!(), line: line!() + $offset }
|
||||
};
|
||||
}
|
||||
|
||||
/// These are licenses that are allowed for all crates, including the runtime,
|
||||
/// rustc, tools, etc.
|
||||
#[rustfmt::skip]
|
||||
|
|
@ -87,6 +107,8 @@ pub(crate) struct WorkspaceInfo<'a> {
|
|||
pub(crate) submodules: &'a [&'a str],
|
||||
}
|
||||
|
||||
const WORKSPACE_LOCATION: ListLocation = location!(+4);
|
||||
|
||||
/// The workspaces to check for licensing and optionally permitted dependencies.
|
||||
// FIXME auto detect all cargo workspaces
|
||||
pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[
|
||||
|
|
@ -222,10 +244,14 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[
|
|||
|
||||
const EXCEPTIONS_RUSTBOOK: ExceptionList = &[
|
||||
// tidy-alphabetical-start
|
||||
("cssparser", "MPL-2.0"),
|
||||
("cssparser-macros", "MPL-2.0"),
|
||||
("dtoa-short", "MPL-2.0"),
|
||||
("mdbook", "MPL-2.0"),
|
||||
("font-awesome-as-a-crate", "CC-BY-4.0 AND MIT"),
|
||||
("mdbook-core", "MPL-2.0"),
|
||||
("mdbook-driver", "MPL-2.0"),
|
||||
("mdbook-html", "MPL-2.0"),
|
||||
("mdbook-markdown", "MPL-2.0"),
|
||||
("mdbook-preprocessor", "MPL-2.0"),
|
||||
("mdbook-renderer", "MPL-2.0"),
|
||||
("mdbook-summary", "MPL-2.0"),
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
|
||||
|
|
@ -242,19 +268,6 @@ const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[];
|
|||
|
||||
const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[];
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct ListLocation {
|
||||
path: &'static str,
|
||||
line: u32,
|
||||
}
|
||||
|
||||
/// Creates a [`ListLocation`] for the current location (with an additional offset to the actual list start);
|
||||
macro_rules! location {
|
||||
(+ $offset:literal) => {
|
||||
ListLocation { path: file!(), line: line!() + $offset }
|
||||
};
|
||||
}
|
||||
|
||||
const PERMITTED_RUSTC_DEPS_LOCATION: ListLocation = location!(+6);
|
||||
|
||||
/// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
|
||||
|
|
@ -641,6 +654,13 @@ pub fn check(root: &Path, cargo: &Path, tidy_ctx: TidyCtx) {
|
|||
.other_options(vec!["--locked".to_owned()]);
|
||||
let metadata = t!(cmd.exec());
|
||||
|
||||
// Check for packages which have been moved into a different workspace and not updated
|
||||
let absolute_root =
|
||||
if path == "." { root.to_path_buf() } else { t!(std::path::absolute(root.join(path))) };
|
||||
let absolute_root_real = t!(std::path::absolute(&metadata.workspace_root));
|
||||
if absolute_root_real != absolute_root {
|
||||
check.error(format!("{path} is part of another workspace ({} != {}), remove from `WORKSPACES` ({WORKSPACE_LOCATION})", absolute_root.display(), absolute_root_real.display()));
|
||||
}
|
||||
check_license_exceptions(&metadata, path, exceptions, &mut check);
|
||||
if let Some((crates, permitted_deps, location)) = crates_and_deps {
|
||||
let descr = crates.get(0).unwrap_or(&path);
|
||||
|
|
|
|||
|
|
@ -22,15 +22,15 @@ pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
|
|||
|
||||
// CHECK-LABEL: use_foreign_c_variadic_1_1
|
||||
pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
|
||||
// CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, i32 noundef 42)
|
||||
// CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, i32 noundef{{( signext)?}} 42)
|
||||
foreign_c_variadic_1(ap, 42i32);
|
||||
}
|
||||
pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
|
||||
// CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, i32 noundef 2, i32 noundef 42)
|
||||
// CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, i32 noundef{{( signext)?}} 2, i32 noundef{{( signext)?}} 42)
|
||||
foreign_c_variadic_1(ap, 2i32, 42i32);
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
|
||||
// CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, i32 noundef 2, i32 noundef 42, i32 noundef 0)
|
||||
// CHECK: call void ({{.*}}, ...) @foreign_c_variadic_1({{.*}} %ap, i32 noundef{{( signext)?}} 2, i32 noundef{{( signext)?}} 42, i32 noundef{{( signext)?}} 0)
|
||||
foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,17 @@ Thanks! <3
|
|||
"""
|
||||
label = "O-ARM"
|
||||
|
||||
[ping.loongarch]
|
||||
message = """\
|
||||
Hey LoongArch Group! This bug has been identified as a good "LoongArch candidate".
|
||||
In case it's useful, here are some [instructions] for tackling these sorts of
|
||||
bugs. Maybe take a look?
|
||||
Thanks! <3
|
||||
|
||||
[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/loongarch.html
|
||||
"""
|
||||
label = "O-loongarch"
|
||||
|
||||
[ping.risc-v]
|
||||
message = """\
|
||||
Hey RISC-V Group! This bug has been identified as a good "RISC-V candidate".
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue